[BUGFIX] FormEngine: Custom functions
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Tests / Unit / Form / FormDataProvider / TcaCheckboxItemsTest.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 Prophecy\Argument;
18 use Prophecy\Prophecy\ObjectProphecy;
19 use TYPO3\CMS\Core\Tests\UnitTestCase;
20 use TYPO3\CMS\Backend\Form\FormDataProvider\TcaCheckboxItems;
21 use TYPO3\CMS\Lang\LanguageService;
22 use TYPO3\CMS\Core\Messaging\FlashMessage;
23 use TYPO3\CMS\Core\Messaging\FlashMessageService;
24 use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26
27 /**
28 * Test case
29 */
30 class TcaCheckboxItemsTest extends UnitTestCase
31 {
32 /**
33 * @var TcaCheckboxItems
34 */
35 protected $subject;
36
37 /**
38 * @var array A backup of registered singleton instances
39 */
40 protected $singletonInstances = array();
41
42 protected function setUp()
43 {
44 $this->singletonInstances = GeneralUtility::getSingletonInstances();
45 $this->subject = new TcaCheckboxItems();
46 }
47
48 protected function tearDown()
49 {
50 GeneralUtility::purgeInstances();
51 GeneralUtility::resetSingletonInstances($this->singletonInstances);
52 parent::tearDown();
53 }
54
55 /**
56 * @test
57 */
58 public function addDataKeepExistingItems()
59 {
60 $input = [
61 'processedTca' => [
62 'columns' => [
63 'aField' => [
64 'config' => [
65 'type' => 'check',
66 'items' => [
67 0 => [
68 'foo',
69 'bar',
70 ],
71 ],
72 ],
73 ],
74 ],
75 ],
76 ];
77 $languageService = $this->prophesize(LanguageService::class);
78 $GLOBALS['LANG'] = $languageService->reveal();
79 $languageService->sL(Argument::cetera())->willReturnArgument(0);
80
81 $expected = $input;
82 $this->assertSame($expected, $this->subject->addData($input));
83 }
84
85 /**
86 * @test
87 */
88 public function addDataThrowsExceptionIfItemsAreNoArray()
89 {
90 $input = [
91 'processedTca' => [
92 'columns' => [
93 'aField' => [
94 'config' => [
95 'type' => 'check',
96 'items' => [
97 0 => 'aoeu',
98 ],
99 ],
100 ],
101 ],
102 ],
103 ];
104 $this->setExpectedException(\UnexpectedValueException::class, $this->any(), 1440499337);
105 $this->subject->addData($input);
106 }
107
108 /**
109 * @test
110 */
111 public function addDataThrowsExceptionIfItemLabelIsNotSet()
112 {
113 $input = [
114 'processedTca' => [
115 'columns' => [
116 'aField' => [
117 'config' => [
118 'type' => 'check',
119 'items' => [
120 0 => [
121 'funnyKey' => 'funnyValue',
122 ],
123 ],
124 ],
125 ],
126 ],
127 ],
128 ];
129 $this->setExpectedException(\UnexpectedValueException::class, $this->any(), 1440499338);
130 $this->subject->addData($input);
131 }
132
133 /**
134 * @test
135 */
136 public function addDataTranslatesItemLabels()
137 {
138 $input = [
139 'processedTca' => [
140 'columns' => [
141 'aField' => [
142 'config' => [
143 'type' => 'check',
144 'items' => [
145 0 => [
146 0 => 'aLabel',
147 1 => 'aValue',
148 ],
149 ],
150 ],
151 ],
152 ],
153 ],
154 ];
155
156 /** @var LanguageService|ObjectProphecy $languageService */
157 $languageService = $this->prophesize(LanguageService::class);
158 $GLOBALS['LANG'] = $languageService->reveal();
159
160 $languageService->sL('aLabel')->shouldBeCalled()->willReturn('translated');
161
162 $expected = $input;
163 $expected['processedTca']['columns']['aField']['config']['items'][0][0] = 'translated';
164
165 $this->assertSame($expected, $this->subject->addData($input));
166 $this->subject->addData($input);
167 }
168
169 /**
170 * @test
171 */
172 public function addDataCallsItemsProcFunc()
173 {
174 $input = [
175 'tableName' => 'aTable',
176 'databaseRow' => [],
177 'processedTca' => [
178 'columns' => [
179 'aField' => [
180 'config' => [
181 'type' => 'check',
182 'items' => [],
183 'itemsProcFunc' => function (array $parameters, $pObj) {
184 $parameters['items'] = [
185 'foo' => 'bar',
186 ];
187 },
188 ],
189 ],
190 ],
191 ],
192 ];
193 $expected = $input;
194 $expected['processedTca']['columns']['aField']['config'] = [
195 'type' => 'check',
196 'items' => [
197 'foo' => 'bar',
198 ],
199 ];
200 $this->assertSame($expected, $this->subject->addData($input));
201 }
202
203 /**
204 * @test
205 */
206 public function addDataItemsProcFuncReceivesParameters()
207 {
208 $input = [
209 'tableName' => 'aTable',
210 'databaseRow' => [
211 'aField' => 'aValue',
212 ],
213 'pageTsConfig' => [
214 'TCEFORM.' => [
215 'aTable.' => [
216 'aField.' => [
217 'itemsProcFunc.' => [
218 'itemParamKey' => 'itemParamValue',
219 ],
220 ]
221 ],
222 ],
223 ],
224 'flexParentDatabaseRow' => [
225 'aParentDatabaseRowFieldName' => 'aParentDatabaseRowFieldValue',
226 ],
227 'processedTca' => [
228 'columns' => [
229 'aField' => [
230 'config' => [
231 'type' => 'check',
232 'aKey' => 'aValue',
233 'items' => [
234 0 => [
235 'foo',
236 'bar',
237 ],
238 ],
239 'itemsProcFunc' => function (array $parameters, $pObj) {
240 if ($parameters['items'] !== [ 0 => [ 'foo', 'bar'] ]
241 || $parameters['config']['aKey'] !== 'aValue'
242 || $parameters['TSconfig'] !== [ 'itemParamKey' => 'itemParamValue' ]
243 || $parameters['table'] !== 'aTable'
244 || $parameters['row'] !== [ 'aField' => 'aValue' ]
245 || $parameters['field'] !== 'aField'
246 || $parameters['flexParentDatabaseRow']['aParentDatabaseRowFieldName'] !== 'aParentDatabaseRowFieldValue'
247 ) {
248 throw new \UnexpectedValueException('broken', 1438604329);
249 }
250 },
251 ],
252 ],
253 ],
254 ],
255 ];
256
257 $languageService = $this->prophesize(LanguageService::class);
258 $GLOBALS['LANG'] = $languageService->reveal();
259 $languageService->sL(Argument::cetera())->willReturnArgument(0);
260 /** @var FlashMessage|ObjectProphecy $flashMessage */
261 $flashMessage = $this->prophesize(FlashMessage::class);
262 GeneralUtility::addInstance(FlashMessage::class, $flashMessage->reveal());
263 /** @var FlashMessageService|ObjectProphecy $flashMessageService */
264 $flashMessageService = $this->prophesize(FlashMessageService::class);
265 GeneralUtility::setSingletonInstance(FlashMessageService::class, $flashMessageService->reveal());
266 /** @var FlashMessageQueue|ObjectProphecy $flashMessageQueue */
267 $flashMessageQueue = $this->prophesize(FlashMessageQueue::class);
268 $flashMessageService->getMessageQueueByIdentifier(Argument::cetera())->willReturn($flashMessageQueue->reveal());
269
270 // itemsProcFunc must NOT have raised an exception
271 $flashMessageQueue->enqueue($flashMessage)->shouldNotBeCalled();
272
273 $this->subject->addData($input);
274 }
275
276 /**
277 * @test
278 */
279 public function addDataItemsProcFuncEnqueuesFlashMessageOnException()
280 {
281 $input = [
282 'tableName' => 'aTable',
283 'databaseRow' => [
284 'aField' => 'aValue',
285 ],
286 'pageTsConfig' => [
287 'TCEFORM.' => [
288 'aTable.' => [
289 'aField.' => [
290 'itemsProcFunc.' => [
291 'itemParamKey' => 'itemParamValue',
292 ],
293 ]
294 ],
295 ],
296 ],
297 'processedTca' => [
298 'columns' => [
299 'aField' => [
300 'config' => [
301 'type' => 'check',
302 'aKey' => 'aValue',
303 'items' => [
304 0 => [
305 'foo',
306 'bar',
307 ],
308 ],
309 'itemsProcFunc' => function (array $parameters, $pObj) {
310 throw new \UnexpectedValueException('anException', 1438604329);
311 },
312 ],
313 ],
314 ],
315 ],
316 ];
317
318 $languageService = $this->prophesize(LanguageService::class);
319 $GLOBALS['LANG'] = $languageService->reveal();
320 /** @var FlashMessage|ObjectProphecy $flashMessage */
321 $flashMessage = $this->prophesize(FlashMessage::class);
322 GeneralUtility::addInstance(FlashMessage::class, $flashMessage->reveal());
323 /** @var FlashMessageService|ObjectProphecy $flashMessageService */
324 $flashMessageService = $this->prophesize(FlashMessageService::class);
325 GeneralUtility::setSingletonInstance(FlashMessageService::class, $flashMessageService->reveal());
326 /** @var FlashMessageQueue|ObjectProphecy $flashMessageQueue */
327 $flashMessageQueue = $this->prophesize(FlashMessageQueue::class);
328 $flashMessageService->getMessageQueueByIdentifier(Argument::cetera())->willReturn($flashMessageQueue->reveal());
329
330 $flashMessageQueue->enqueue($flashMessage)->shouldBeCalled();
331
332 $this->subject->addData($input);
333 }
334
335 /**
336 * @test
337 */
338 public function addDataTranslatesItemLabelsFromPageTsConfig()
339 {
340 $input = [
341 'tableName' => 'aTable',
342 'processedTca' => [
343 'columns' => [
344 'aField' => [
345 'config' => [
346 'type' => 'check',
347 'items' => [
348 0 => [
349 0 => 'aLabel',
350 1 => 'aValue',
351 ],
352 ],
353 ],
354 ],
355 ],
356 ],
357 'pageTsConfig' => [
358 'TCEFORM.' => [
359 'aTable.' => [
360 'aField.' => [
361 'altLabels.' => [
362 0 => 'labelOverride',
363 ],
364 ]
365 ],
366 ],
367 ],
368 ];
369
370 /** @var LanguageService|ObjectProphecy $languageService */
371 $languageService = $this->prophesize(LanguageService::class);
372 $GLOBALS['LANG'] = $languageService->reveal();
373 $languageService->sL('aLabel')->willReturnArgument(0);
374
375 $languageService->sL('labelOverride')->shouldBeCalled()->willReturnArgument(0);
376
377 $expected = $input;
378 $expected['processedTca']['columns']['aField']['config']['items'][0][0] = 'labelOverride';
379
380 $this->assertSame($expected, $this->subject->addData($input));
381 $this->subject->addData($input);
382 }
383
384 }