[BUGFIX] Notice free FormEngine testing
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Tests / Unit / Form / FormDataProvider / DatabaseSystemLanguageRowsTest.php
1 <?php
2 namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Doctrine\DBAL\Driver\Statement;
18 use Prophecy\Argument;
19 use Prophecy\Prophecy\ObjectProphecy;
20 use TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseSystemLanguageRows;
21 use TYPO3\CMS\Core\Database\ConnectionPool;
22 use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
23 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
24 use TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionContainerInterface;
25 use TYPO3\CMS\Core\Localization\LanguageService;
26 use TYPO3\CMS\Core\Messaging\FlashMessage;
27 use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
28 use TYPO3\CMS\Core\Messaging\FlashMessageService;
29 use TYPO3\CMS\Core\Utility\GeneralUtility;
30 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
31
32 /**
33 * Test case
34 */
35 class DatabaseSystemLanguageRowsTest extends UnitTestCase
36 {
37 /**
38 * @var DatabaseSystemLanguageRows
39 */
40 protected $subject;
41
42 /**
43 * @var array A backup of registered singleton instances
44 */
45 protected $singletonInstances = [];
46
47 protected function setUp()
48 {
49 $this->singletonInstances = GeneralUtility::getSingletonInstances();
50 $languageService = $this->prophesize(LanguageService::class);
51 $GLOBALS['LANG'] = $languageService->reveal();
52 $languageService->sL(Argument::cetera())->willReturnArgument(0);
53 $this->subject = new DatabaseSystemLanguageRows();
54 }
55
56 protected function tearDown()
57 {
58 GeneralUtility::purgeInstances();
59 GeneralUtility::resetSingletonInstances($this->singletonInstances);
60 parent::tearDown();
61 }
62
63 /**
64 * @test
65 */
66 public function addDataSetsDefaultLanguageAndAllEntries()
67 {
68 $input = [
69 'pageTsConfig' => [],
70 ];
71 $expected = [
72 'pageTsConfig' => [],
73 'systemLanguageRows' => [
74 -1 => [
75 'uid' => -1,
76 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
77 'iso' => 'DEF',
78 'flagIconIdentifier' => 'flags-multiple',
79 ],
80 0 => [
81 'uid' => 0,
82 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage',
83 'iso' => 'DEF',
84 'flagIconIdentifier' => 'empty-empty',
85 ],
86 ],
87 ];
88
89 // Prophecies and revelations for a lot of the database stack classes
90 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
91 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
92 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
93 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
94 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
95 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
96 $statementProphecy = $this->prophesize(Statement::class);
97
98 // Register connection pool revelation in framework, this is the entry point used by the system during tests
99 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
100
101 // Simulate method call flow on database objects and verify correct query is built
102 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
103 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
104 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
105 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
106 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
107 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
108 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
109 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
110 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
111 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
112 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
113 $statementProphecy->fetch()->shouldBeCalledTimes(1)->willReturn(false);
114
115 $this->assertSame($expected, $this->subject->addData($input));
116 }
117
118 /**
119 * @test
120 */
121 public function addDataSetsDefaultLanguageTitleFromPageTsConfig()
122 {
123 $input = [
124 'pageTsConfig' => [
125 'mod.' => [
126 'SHARED.' => [
127 'defaultLanguageLabel' => 'foo',
128 ],
129 ]
130 ],
131 ];
132
133 // Prophecies and revelations for a lot of the database stack classes
134 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
135 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
136 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
137 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
138 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
139 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
140 $statementProphecy = $this->prophesize(Statement::class);
141
142 // Register connection pool revelation in framework, this is the entry point used by the system during tests
143 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
144
145 // Simulate method call flow on database objects and verify correct query is built
146 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
147 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
148 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
149 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
150 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
151 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
152 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
153 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
154 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
155 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
156 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
157 $statementProphecy->fetch()->shouldBeCalledTimes(1)->willReturn(false);
158
159 $expected = $input;
160 $expected['systemLanguageRows'] = [
161 -1 => [
162 'uid' => -1,
163 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
164 'iso' => 'DEF',
165 'flagIconIdentifier' => 'flags-multiple',
166 ],
167 0 => [
168 'uid' => 0,
169 'title' => 'foo (LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage)',
170 'iso' => 'DEF',
171 'flagIconIdentifier' => 'empty-empty',
172 ],
173 ];
174 $this->assertSame($expected, $this->subject->addData($input));
175 }
176
177 /**
178 * @test
179 */
180 public function addDataSetsDefaultLanguageFlagFromPageTsConfig()
181 {
182 $input = [
183 'pageTsConfig' => [
184 'mod.' => [
185 'SHARED.' => [
186 'defaultLanguageFlag' => 'uk',
187 ],
188 ]
189 ],
190 ];
191
192 // Prophecies and revelations for a lot of the database stack classes
193 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
194 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
195 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
196 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
197 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
198 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
199 $statementProphecy = $this->prophesize(Statement::class);
200
201 // Register connection pool revelation in framework, this is the entry point used by the system during tests
202 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
203
204 // Simulate method call flow on database objects and verify correct query is built
205 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
206 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
207 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
208 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
209 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
210 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
211 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
212 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
213 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
214 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
215 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
216 $statementProphecy->fetch()->shouldBeCalledTimes(1)->willReturn(false);
217
218 $expected = $input;
219 $expected['systemLanguageRows'] = [
220 -1 => [
221 'uid' => -1,
222 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
223 'iso' => 'DEF',
224 'flagIconIdentifier' => 'flags-multiple',
225 ],
226 0 => [
227 'uid' => 0,
228 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage',
229 'iso' => 'DEF',
230 'flagIconIdentifier' => 'flags-uk',
231 ],
232 ];
233 $this->assertSame($expected, $this->subject->addData($input));
234 }
235
236 /**
237 * @test
238 */
239 public function addDataResolvesLanguageIsocodeFromDatabaseField()
240 {
241 $aDatabaseResultRow = [
242 'uid' => 3,
243 'title' => 'french',
244 'language_isocode' => 'fr',
245 'static_lang_isocode' => '',
246 'flag' => 'fr',
247 ];
248
249 // Prophecies and revelations for a lot of the database stack classes
250 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
251 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
252 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
253 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
254 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
255 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
256 $statementProphecy = $this->prophesize(Statement::class);
257
258 // Register connection pool revelation in framework, this is the entry point used by the system during tests
259 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
260
261 // Simulate method call flow on database objects and verify correct query is built
262 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
263 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
264 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
265 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
266 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
267 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
268 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
269 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
270 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
271 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
272 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
273
274 $statementProphecy->fetch()->shouldBeCalledTimes(2)->willReturn($aDatabaseResultRow, false);
275
276 $input = [
277 'pageTsConfig' => [],
278 ];
279
280 $expected = [
281 'pageTsConfig' => [],
282 'systemLanguageRows' => [
283 -1 => [
284 'uid' => -1,
285 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
286 'iso' => 'DEF',
287 'flagIconIdentifier' => 'flags-multiple',
288 ],
289 0 => [
290 'uid' => 0,
291 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage',
292 'iso' => 'DEF',
293 'flagIconIdentifier' => 'empty-empty',
294 ],
295 3 => [
296 'uid' => 3,
297 'title' => 'french',
298 'flagIconIdentifier' => 'flags-fr',
299 'iso' => 'fr',
300 ],
301 ],
302 ];
303 $this->assertSame($expected, $this->subject->addData($input));
304 }
305
306 /**
307 * @test
308 */
309 public function addDataAddFlashMessageWithMissingIsoCode()
310 {
311 $aDatabaseResultRow = [
312 'uid' => 3,
313 'title' => 'french',
314 'language_isocode' => '',
315 'static_lang_isocode' => '',
316 'flag' => 'fr',
317 ];
318
319 // Prophecies and revelations for a lot of the database stack classes
320 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
321 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
322 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
323 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
324 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
325 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
326 $statementProphecy = $this->prophesize(Statement::class);
327
328 // Register connection pool revelation in framework, this is the entry point used by the system during tests
329 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
330
331 // Simulate method call flow on database objects and verify correct query is built
332 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
333 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
334 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
335 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
336 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
337 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
338 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
339 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
340 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
341 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
342 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
343
344 $statementProphecy->fetch()->shouldBeCalledTimes(2)->willReturn($aDatabaseResultRow, false);
345
346 $input = [
347 'pageTsConfig' => [],
348 ];
349
350 // Needed for backendUtility::getRecord()
351 $GLOBALS['TCA']['static_languages'] = [ 'foo' ];
352 $expected = [
353 'pageTsConfig' => [],
354 'systemLanguageRows' => [
355 -1 => [
356 'uid' => -1,
357 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
358 'iso' => 'DEF',
359 'flagIconIdentifier' => 'flags-multiple',
360 ],
361 0 => [
362 'uid' => 0,
363 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage',
364 'iso' => 'DEF',
365 'flagIconIdentifier' => 'empty-empty',
366 ],
367 3 => [
368 'uid' => 3,
369 'title' => 'french',
370 'flagIconIdentifier' => 'flags-fr',
371 'iso' => '',
372 ],
373 ],
374 ];
375
376 /** @var FlashMessage|ObjectProphecy $flashMessage */
377 $flashMessage = $this->prophesize(FlashMessage::class);
378 GeneralUtility::addInstance(FlashMessage::class, $flashMessage->reveal());
379 /** @var FlashMessageService|ObjectProphecy $flashMessageService */
380 $flashMessageService = $this->prophesize(FlashMessageService::class);
381 GeneralUtility::setSingletonInstance(FlashMessageService::class, $flashMessageService->reveal());
382 /** @var FlashMessageQueue|ObjectProphecy $flashMessageQueue */
383 $flashMessageQueue = $this->prophesize(FlashMessageQueue::class);
384 $flashMessageService->getMessageQueueByIdentifier(Argument::cetera())->willReturn($flashMessageQueue->reveal());
385
386 $flashMessageQueue->enqueue($flashMessage)->shouldBeCalled();
387
388 $this->assertSame($expected, $this->subject->addData($input));
389 }
390 }