204ef47be0cef3ea3c038dccd8042460089dc891
[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 protected function setUp()
43 {
44 $languageService = $this->prophesize(LanguageService::class);
45 $GLOBALS['LANG'] = $languageService->reveal();
46 $languageService->sL(Argument::cetera())->willReturnArgument(0);
47 $this->subject = new DatabaseSystemLanguageRows();
48 }
49
50 protected function tearDown()
51 {
52 GeneralUtility::purgeInstances();
53 parent::tearDown();
54 }
55
56 /**
57 * @test
58 */
59 public function addDataSetsDefaultLanguageAndAllEntries()
60 {
61 $input = [
62 'pageTsConfig' => [],
63 ];
64 $expected = [
65 'pageTsConfig' => [],
66 'systemLanguageRows' => [
67 -1 => [
68 'uid' => -1,
69 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
70 'iso' => 'DEF',
71 'flagIconIdentifier' => 'flags-multiple',
72 ],
73 0 => [
74 'uid' => 0,
75 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage',
76 'iso' => 'DEF',
77 'flagIconIdentifier' => 'empty-empty',
78 ],
79 ],
80 ];
81
82 // Prophecies and revelations for a lot of the database stack classes
83 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
84 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
85 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
86 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
87 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
88 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
89 $statementProphecy = $this->prophesize(Statement::class);
90
91 // Register connection pool revelation in framework, this is the entry point used by the system during tests
92 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
93
94 // Simulate method call flow on database objects and verify correct query is built
95 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
96 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
97 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
98 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
99 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
100 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
101 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
102 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
103 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
104 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
105 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
106 $statementProphecy->fetch()->shouldBeCalledTimes(1)->willReturn(false);
107
108 $this->assertSame($expected, $this->subject->addData($input));
109 }
110
111 /**
112 * @test
113 */
114 public function addDataSetsDefaultLanguageTitleFromPageTsConfig()
115 {
116 $input = [
117 'pageTsConfig' => [
118 'mod.' => [
119 'SHARED.' => [
120 'defaultLanguageLabel' => 'foo',
121 ],
122 ]
123 ],
124 ];
125
126 // Prophecies and revelations for a lot of the database stack classes
127 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
128 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
129 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
130 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
131 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
132 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
133 $statementProphecy = $this->prophesize(Statement::class);
134
135 // Register connection pool revelation in framework, this is the entry point used by the system during tests
136 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
137
138 // Simulate method call flow on database objects and verify correct query is built
139 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
140 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
141 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
142 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
143 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
144 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
145 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
146 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
147 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
148 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
149 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
150 $statementProphecy->fetch()->shouldBeCalledTimes(1)->willReturn(false);
151
152 $expected = $input;
153 $expected['systemLanguageRows'] = [
154 -1 => [
155 'uid' => -1,
156 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
157 'iso' => 'DEF',
158 'flagIconIdentifier' => 'flags-multiple',
159 ],
160 0 => [
161 'uid' => 0,
162 'title' => 'foo (LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage)',
163 'iso' => 'DEF',
164 'flagIconIdentifier' => 'empty-empty',
165 ],
166 ];
167 $this->assertSame($expected, $this->subject->addData($input));
168 }
169
170 /**
171 * @test
172 */
173 public function addDataSetsDefaultLanguageFlagFromPageTsConfig()
174 {
175 $input = [
176 'pageTsConfig' => [
177 'mod.' => [
178 'SHARED.' => [
179 'defaultLanguageFlag' => 'uk',
180 ],
181 ]
182 ],
183 ];
184
185 // Prophecies and revelations for a lot of the database stack classes
186 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
187 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
188 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
189 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
190 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
191 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
192 $statementProphecy = $this->prophesize(Statement::class);
193
194 // Register connection pool revelation in framework, this is the entry point used by the system during tests
195 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
196
197 // Simulate method call flow on database objects and verify correct query is built
198 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
199 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
200 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
201 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
202 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
203 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
204 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
205 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
206 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
207 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
208 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
209 $statementProphecy->fetch()->shouldBeCalledTimes(1)->willReturn(false);
210
211 $expected = $input;
212 $expected['systemLanguageRows'] = [
213 -1 => [
214 'uid' => -1,
215 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
216 'iso' => 'DEF',
217 'flagIconIdentifier' => 'flags-multiple',
218 ],
219 0 => [
220 'uid' => 0,
221 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage',
222 'iso' => 'DEF',
223 'flagIconIdentifier' => 'flags-uk',
224 ],
225 ];
226 $this->assertSame($expected, $this->subject->addData($input));
227 }
228
229 /**
230 * @test
231 */
232 public function addDataResolvesLanguageIsocodeFromDatabaseField()
233 {
234 $aDatabaseResultRow = [
235 'uid' => 3,
236 'title' => 'french',
237 'language_isocode' => 'fr',
238 'static_lang_isocode' => '',
239 'flag' => 'fr',
240 ];
241
242 // Prophecies and revelations for a lot of the database stack classes
243 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
244 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
245 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
246 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
247 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
248 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
249 $statementProphecy = $this->prophesize(Statement::class);
250
251 // Register connection pool revelation in framework, this is the entry point used by the system during tests
252 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
253
254 // Simulate method call flow on database objects and verify correct query is built
255 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
256 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
257 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
258 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
259 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
260 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
261 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
262 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
263 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
264 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
265 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
266
267 $statementProphecy->fetch()->shouldBeCalledTimes(2)->willReturn($aDatabaseResultRow, false);
268
269 $input = [
270 'pageTsConfig' => [],
271 ];
272
273 $expected = [
274 'pageTsConfig' => [],
275 'systemLanguageRows' => [
276 -1 => [
277 'uid' => -1,
278 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
279 'iso' => 'DEF',
280 'flagIconIdentifier' => 'flags-multiple',
281 ],
282 0 => [
283 'uid' => 0,
284 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage',
285 'iso' => 'DEF',
286 'flagIconIdentifier' => 'empty-empty',
287 ],
288 3 => [
289 'uid' => 3,
290 'title' => 'french',
291 'flagIconIdentifier' => 'flags-fr',
292 'iso' => 'fr',
293 ],
294 ],
295 ];
296 $this->assertSame($expected, $this->subject->addData($input));
297 }
298
299 /**
300 * @test
301 */
302 public function addDataAddFlashMessageWithMissingIsoCode()
303 {
304 $aDatabaseResultRow = [
305 'uid' => 3,
306 'title' => 'french',
307 'language_isocode' => '',
308 'static_lang_isocode' => '',
309 'flag' => 'fr',
310 ];
311
312 // Prophecies and revelations for a lot of the database stack classes
313 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
314 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
315 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
316 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
317 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
318 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
319 $statementProphecy = $this->prophesize(Statement::class);
320
321 // Register connection pool revelation in framework, this is the entry point used by the system during tests
322 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
323
324 // Simulate method call flow on database objects and verify correct query is built
325 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
326 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
327 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
328 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
329 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
330 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
331 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
332 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
333 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
334 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
335 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
336
337 $statementProphecy->fetch()->shouldBeCalledTimes(2)->willReturn($aDatabaseResultRow, false);
338
339 $input = [
340 'pageTsConfig' => [],
341 ];
342
343 // Needed for backendUtility::getRecord()
344 $GLOBALS['TCA']['static_languages'] = [ 'foo' ];
345 $expected = [
346 'pageTsConfig' => [],
347 'systemLanguageRows' => [
348 -1 => [
349 'uid' => -1,
350 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
351 'iso' => 'DEF',
352 'flagIconIdentifier' => 'flags-multiple',
353 ],
354 0 => [
355 'uid' => 0,
356 'title' => 'LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage',
357 'iso' => 'DEF',
358 'flagIconIdentifier' => 'empty-empty',
359 ],
360 3 => [
361 'uid' => 3,
362 'title' => 'french',
363 'flagIconIdentifier' => 'flags-fr',
364 'iso' => '',
365 ],
366 ],
367 ];
368
369 /** @var FlashMessage|ObjectProphecy $flashMessage */
370 $flashMessage = $this->prophesize(FlashMessage::class);
371 GeneralUtility::addInstance(FlashMessage::class, $flashMessage->reveal());
372 /** @var FlashMessageService|ObjectProphecy $flashMessageService */
373 $flashMessageService = $this->prophesize(FlashMessageService::class);
374 GeneralUtility::setSingletonInstance(FlashMessageService::class, $flashMessageService->reveal());
375 /** @var FlashMessageQueue|ObjectProphecy $flashMessageQueue */
376 $flashMessageQueue = $this->prophesize(FlashMessageQueue::class);
377 $flashMessageService->getMessageQueueByIdentifier(Argument::cetera())->willReturn($flashMessageQueue->reveal());
378
379 $flashMessageQueue->enqueue($flashMessage)->shouldBeCalled();
380
381 $this->assertSame($expected, $this->subject->addData($input));
382 }
383 }