d24ff0d11985ec4e6abae22521694e1a13b696ce
[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
31 /**
32 * Test case
33 */
34 class DatabaseSystemLanguageRowsTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
35 {
36 /**
37 * Subject is not notice free, disable E_NOTICES
38 */
39 protected static $suppressNotices = true;
40
41 /**
42 * @var DatabaseSystemLanguageRows
43 */
44 protected $subject;
45
46 /**
47 * @var array A backup of registered singleton instances
48 */
49 protected $singletonInstances = [];
50
51 protected function setUp()
52 {
53 $this->singletonInstances = GeneralUtility::getSingletonInstances();
54 $languageService = $this->prophesize(LanguageService::class);
55 $GLOBALS['LANG'] = $languageService->reveal();
56 $languageService->sL(Argument::cetera())->willReturnArgument(0);
57 $this->subject = new DatabaseSystemLanguageRows();
58 }
59
60 protected function tearDown()
61 {
62 GeneralUtility::purgeInstances();
63 GeneralUtility::resetSingletonInstances($this->singletonInstances);
64 parent::tearDown();
65 }
66
67 /**
68 * @test
69 */
70 public function addDataSetsDefaultLanguageAndAllEntries()
71 {
72 $expected = [
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([]));
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 $expected = [
277 'systemLanguageRows' => [
278 -1 => [
279 'uid' => -1,
280 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
281 'iso' => 'DEF',
282 'flagIconIdentifier' => 'flags-multiple',
283 ],
284 0 => [
285 'uid' => 0,
286 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage',
287 'iso' => 'DEF',
288 'flagIconIdentifier' => 'empty-empty',
289 ],
290 3 => [
291 'uid' => 3,
292 'title' => 'french',
293 'flagIconIdentifier' => 'flags-fr',
294 'iso' => 'fr',
295 ],
296 ],
297 ];
298 $this->assertSame($expected, $this->subject->addData([]));
299 }
300
301 /**
302 * @test
303 */
304 public function addDataAddFlashMessageWithMissingIsoCode()
305 {
306 $aDatabaseResultRow = [
307 'uid' => 3,
308 'title' => 'french',
309 'language_isocode' => '',
310 'static_lang_isocode' => '',
311 'flag' => 'fr',
312 ];
313
314 // Prophecies and revelations for a lot of the database stack classes
315 $queryBuilderProphecy = $this->prophesize(QueryBuilder::class);
316 $queryBuilderRevelation = $queryBuilderProphecy->reveal();
317 $connectionPoolProphecy = $this->prophesize(ConnectionPool::class);
318 $queryRestrictionContainerProphecy = $this->prophesize(QueryRestrictionContainerInterface::class);
319 $queryRestrictionContainerRevelation = $queryRestrictionContainerProphecy->reveal();
320 $expressionBuilderProphecy = $this->prophesize(ExpressionBuilder::class);
321 $statementProphecy = $this->prophesize(Statement::class);
322
323 // Register connection pool revelation in framework, this is the entry point used by the system during tests
324 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphecy->reveal());
325
326 // Simulate method call flow on database objects and verify correct query is built
327 $connectionPoolProphecy->getQueryBuilderForTable('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
328 $queryRestrictionContainerProphecy->removeAll()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
329 $queryBuilderProphecy->getRestrictions()->shouldBeCalled()->willReturn($queryRestrictionContainerRevelation);
330 $queryBuilderProphecy->select('uid', 'title', 'language_isocode', 'flag')->shouldBeCalled()->willReturn($queryBuilderRevelation);
331 $queryBuilderProphecy->from('sys_language')->shouldBeCalled()->willReturn($queryBuilderRevelation);
332 $queryBuilderProphecy->orderBy('sorting')->shouldBeCalled()->willReturn($queryBuilderRevelation);
333 $queryBuilderProphecy->expr()->shouldBeCalled()->willReturn($expressionBuilderProphecy->reveal());
334 $expressionBuilderProphecy->eq('pid', 0)->shouldBeCalled()->willReturn('pid = 0');
335 $queryBuilderProphecy->where('pid = 0')->shouldBeCalled()->willReturn($queryBuilderRevelation);
336 $queryBuilderProphecy->createNamedParameter(Argument::cetera())->willReturnArgument(0);
337 $queryBuilderProphecy->execute()->shouldBeCalled()->willReturn($statementProphecy->reveal());
338
339 $statementProphecy->fetch()->shouldBeCalledTimes(2)->willReturn($aDatabaseResultRow, false);
340
341 // Needed for backendUtility::getRecord()
342 $GLOBALS['TCA']['static_languages'] = [ 'foo' ];
343 $expected = [
344 'systemLanguageRows' => [
345 -1 => [
346 'uid' => -1,
347 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages',
348 'iso' => 'DEF',
349 'flagIconIdentifier' => 'flags-multiple',
350 ],
351 0 => [
352 'uid' => 0,
353 'title' => 'LLL:EXT:lang/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage',
354 'iso' => 'DEF',
355 'flagIconIdentifier' => 'empty-empty',
356 ],
357 3 => [
358 'uid' => 3,
359 'title' => 'french',
360 'flagIconIdentifier' => 'flags-fr',
361 'iso' => '',
362 ],
363 ],
364 ];
365
366 /** @var FlashMessage|ObjectProphecy $flashMessage */
367 $flashMessage = $this->prophesize(FlashMessage::class);
368 GeneralUtility::addInstance(FlashMessage::class, $flashMessage->reveal());
369 /** @var FlashMessageService|ObjectProphecy $flashMessageService */
370 $flashMessageService = $this->prophesize(FlashMessageService::class);
371 GeneralUtility::setSingletonInstance(FlashMessageService::class, $flashMessageService->reveal());
372 /** @var FlashMessageQueue|ObjectProphecy $flashMessageQueue */
373 $flashMessageQueue = $this->prophesize(FlashMessageQueue::class);
374 $flashMessageService->getMessageQueueByIdentifier(Argument::cetera())->willReturn($flashMessageQueue->reveal());
375
376 $flashMessageQueue->enqueue($flashMessage)->shouldBeCalled();
377
378 $this->assertSame($expected, $this->subject->addData([]));
379 }
380 }