[BUGFIX] Treat <pre> tags correctly in RTE
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Tests / Unit / ContentObject / ContentObjectRendererTest.php
1 <?php
2 namespace TYPO3\CMS\Frontend\Tests\Unit\ContentObject;
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 Psr\Log\LoggerInterface;
18 use TYPO3\CMS\Core\Charset\CharsetConverter;
19 use TYPO3\CMS\Core\Core\ApplicationContext;
20 use TYPO3\CMS\Core\Log\LogManager;
21 use TYPO3\CMS\Core\TimeTracker\NullTimeTracker;
22 use TYPO3\CMS\Core\TypoScript\TemplateService;
23 use TYPO3\CMS\Core\Utility\DebugUtility;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25 use TYPO3\CMS\Frontend\ContentObject\AbstractContentObject;
26 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
27 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
28 use TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Fixtures\PageRepositoryFixture;
29
30 /**
31 * Testcase for TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
32 */
33 class ContentObjectRendererTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
34 {
35 /**
36 * @var string
37 */
38 protected $currentLocale;
39
40 /**
41 * @var array A backup of registered singleton instances
42 */
43 protected $singletonInstances = [];
44
45 /**
46 * @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface|\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
47 */
48 protected $subject = null;
49
50 /**
51 * @var \PHPUnit_Framework_MockObject_MockObject|TypoScriptFrontendController|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface
52 */
53 protected $typoScriptFrontendControllerMock = null;
54
55 /**
56 * @var \PHPUnit_Framework_MockObject_MockObject|TemplateService
57 */
58 protected $templateServiceMock = null;
59
60 /**
61 * Default content object name -> class name map, shipped with TYPO3 CMS
62 *
63 * @var array
64 */
65 protected $contentObjectMap = [
66 'TEXT' => \TYPO3\CMS\Frontend\ContentObject\TextContentObject::class,
67 'CASE' => \TYPO3\CMS\Frontend\ContentObject\CaseContentObject::class,
68 'COBJ_ARRAY' => \TYPO3\CMS\Frontend\ContentObject\ContentObjectArrayContentObject::class,
69 'COA' => \TYPO3\CMS\Frontend\ContentObject\ContentObjectArrayContentObject::class,
70 'COA_INT' => \TYPO3\CMS\Frontend\ContentObject\ContentObjectArrayInternalContentObject::class,
71 'USER' => \TYPO3\CMS\Frontend\ContentObject\UserContentObject::class,
72 'USER_INT' => \TYPO3\CMS\Frontend\ContentObject\UserInternalContentObject::class,
73 'FILE' => \TYPO3\CMS\Frontend\ContentObject\FileContentObject::class,
74 'FILES' => \TYPO3\CMS\Frontend\ContentObject\FilesContentObject::class,
75 'IMAGE' => \TYPO3\CMS\Frontend\ContentObject\ImageContentObject::class,
76 'IMG_RESOURCE' => \TYPO3\CMS\Frontend\ContentObject\ImageResourceContentObject::class,
77 'CONTENT' => \TYPO3\CMS\Frontend\ContentObject\ContentContentObject::class,
78 'RECORDS' => \TYPO3\CMS\Frontend\ContentObject\RecordsContentObject::class,
79 'HMENU' => \TYPO3\CMS\Frontend\ContentObject\HierarchicalMenuContentObject::class,
80 'CASEFUNC' => \TYPO3\CMS\Frontend\ContentObject\CaseContentObject::class,
81 'LOAD_REGISTER' => \TYPO3\CMS\Frontend\ContentObject\LoadRegisterContentObject::class,
82 'RESTORE_REGISTER' => \TYPO3\CMS\Frontend\ContentObject\RestoreRegisterContentObject::class,
83 'TEMPLATE' => \TYPO3\CMS\Frontend\ContentObject\TemplateContentObject::class,
84 'FLUIDTEMPLATE' => \TYPO3\CMS\Frontend\ContentObject\FluidTemplateContentObject::class,
85 'SVG' => \TYPO3\CMS\Frontend\ContentObject\ScalableVectorGraphicsContentObject::class,
86 'EDITPANEL' => \TYPO3\CMS\Frontend\ContentObject\EditPanelContentObject::class
87 ];
88
89 /**
90 * Set up
91 */
92 protected function setUp()
93 {
94 $this->currentLocale = setlocale(LC_NUMERIC, 0);
95
96 $this->singletonInstances = \TYPO3\CMS\Core\Utility\GeneralUtility::getSingletonInstances();
97 $this->createMockedLoggerAndLogManager();
98
99 $this->templateServiceMock = $this->getMock(TemplateService::class, ['getFileName', 'linkData']);
100 $pageRepositoryMock = $this->getMock(PageRepositoryFixture::class, ['getRawRecord']);
101
102 $this->typoScriptFrontendControllerMock = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
103 $this->typoScriptFrontendControllerMock->tmpl = $this->templateServiceMock;
104 $this->typoScriptFrontendControllerMock->config = [];
105 $this->typoScriptFrontendControllerMock->page = [];
106 $this->typoScriptFrontendControllerMock->sys_page = $pageRepositoryMock;
107 $this->typoScriptFrontendControllerMock->csConvObj = new CharsetConverter();
108 $this->typoScriptFrontendControllerMock->renderCharset = 'utf-8';
109 $GLOBALS['TSFE'] = $this->typoScriptFrontendControllerMock;
110 $GLOBALS['TT'] = new NullTimeTracker();
111 $GLOBALS['TYPO3_DB'] = $this->getMock(\TYPO3\CMS\Core\Database\DatabaseConnection::class, []);
112 $GLOBALS['TYPO3_CONF_VARS']['SYS']['t3lib_cs_utils'] = 'mbstring';
113
114 $this->subject = $this->getAccessibleMock(
115 \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
116 ['getResourceFactory', 'getEnvironmentVariable'],
117 [$this->typoScriptFrontendControllerMock]
118 );
119 $this->subject->setContentObjectClassMap($this->contentObjectMap);
120 $this->subject->start([], 'tt_content');
121 }
122
123 protected function tearDown()
124 {
125 setlocale(LC_NUMERIC, $this->currentLocale);
126 GeneralUtility::resetSingletonInstances($this->singletonInstances);
127 parent::tearDown();
128 }
129
130 //////////////////////
131 // Utility functions
132 //////////////////////
133
134 /**
135 * Avoid logging to the file system (file writer is currently the only configured writer)
136 */
137 protected function createMockedLoggerAndLogManager()
138 {
139 $logManagerMock = $this->getMock(LogManager::class);
140 $loggerMock = $this->getMock(LoggerInterface::class);
141 $logManagerMock->expects($this->any())
142 ->method('getLogger')
143 ->willReturn($loggerMock);
144 GeneralUtility::setSingletonInstance(LogManager::class, $logManagerMock);
145 }
146
147 /**
148 * Converts the subject and the expected result into the target charset.
149 *
150 * @param string $charset the target charset
151 * @param string $subject the subject, will be modified
152 * @param string $expected the expected result, will be modified
153 */
154 protected function handleCharset($charset, &$subject, &$expected)
155 {
156 $GLOBALS['TSFE']->renderCharset = $charset;
157 $subject = $GLOBALS['TSFE']->csConvObj->conv($subject, 'iso-8859-1', $charset);
158 $expected = $GLOBALS['TSFE']->csConvObj->conv($expected, 'iso-8859-1', $charset);
159 }
160
161 /////////////////////////////////////////////
162 // Tests concerning the getImgResource hook
163 /////////////////////////////////////////////
164 /**
165 * @test
166 */
167 public function getImgResourceCallsGetImgResourcePostProcessHook()
168 {
169 $this->templateServiceMock
170 ->expects($this->atLeastOnce())
171 ->method('getFileName')
172 ->with('typo3/clear.gif')
173 ->will($this->returnValue('typo3/clear.gif'));
174
175 $resourceFactory = $this->getMock(\TYPO3\CMS\Core\Resource\ResourceFactory::class, [], [], '', false);
176 $this->subject->expects($this->any())->method('getResourceFactory')->will($this->returnValue($resourceFactory));
177
178 $className = $this->getUniqueId('tx_coretest');
179 $getImgResourceHookMock = $this->getMock(\TYPO3\CMS\Frontend\ContentObject\ContentObjectGetImageResourceHookInterface::class, ['getImgResourcePostProcess'], [], $className);
180 $getImgResourceHookMock
181 ->expects($this->once())
182 ->method('getImgResourcePostProcess')
183 ->will($this->returnCallback([$this, 'isGetImgResourceHookCalledCallback']));
184 $getImgResourceHookObjects = [$getImgResourceHookMock];
185 $this->subject->_setRef('getImgResourceHookObjects', $getImgResourceHookObjects);
186 $this->subject->getImgResource('typo3/clear.gif', []);
187 }
188
189 /**
190 * Handles the arguments that have been sent to the getImgResource hook.
191 *
192 * @return array
193 * @see getImgResourceHookGetsCalled
194 */
195 public function isGetImgResourceHookCalledCallback()
196 {
197 list($file, $fileArray, $imageResource, $parent) = func_get_args();
198 $this->assertEquals('typo3/clear.gif', $file);
199 $this->assertEquals('typo3/clear.gif', $imageResource['origFile']);
200 $this->assertTrue(is_array($fileArray));
201 $this->assertTrue($parent instanceof \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer);
202 return $imageResource;
203 }
204
205 //////////////////////////////////////
206 // Tests concerning getContentObject
207 //////////////////////////////////////
208
209 public function getContentObjectValidContentObjectsDataProvider()
210 {
211 $dataProvider = [];
212 foreach ($this->contentObjectMap as $name => $className) {
213 $dataProvider[] = [$name, $className];
214 }
215 return $dataProvider;
216 }
217
218 /**
219 * @test
220 * @dataProvider getContentObjectValidContentObjectsDataProvider
221 * @param string $name TypoScript name of content object
222 * @param string $fullClassName Expected class name
223 */
224 public function getContentObjectCallsMakeInstanceForNewContentObjectInstance($name, $fullClassName)
225 {
226 $contentObjectInstance = $this->getMock($fullClassName, [], [], '', false);
227 \TYPO3\CMS\Core\Utility\GeneralUtility::addInstance($fullClassName, $contentObjectInstance);
228 $this->assertSame($contentObjectInstance, $this->subject->getContentObject($name));
229 }
230
231 /////////////////////////////////////////
232 // Tests concerning getQueryArguments()
233 /////////////////////////////////////////
234 /**
235 * @test
236 */
237 public function getQueryArgumentsExcludesParameters()
238 {
239 $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
240 $this->returnValue('key1=value1&key2=value2&key3[key31]=value31&key3[key32][key321]=value321&key3[key32][key322]=value322')
241 );
242 $getQueryArgumentsConfiguration = [];
243 $getQueryArgumentsConfiguration['exclude'] = [];
244 $getQueryArgumentsConfiguration['exclude'][] = 'key1';
245 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
246 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
247 $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
248 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2&key3[key32][key322]=value322');
249 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
250 $this->assertEquals($expectedResult, $actualResult);
251 }
252
253 /**
254 * @test
255 */
256 public function getQueryArgumentsExcludesGetParameters()
257 {
258 $_GET = [
259 'key1' => 'value1',
260 'key2' => 'value2',
261 'key3' => [
262 'key31' => 'value31',
263 'key32' => [
264 'key321' => 'value321',
265 'key322' => 'value322'
266 ]
267 ]
268 ];
269 $getQueryArgumentsConfiguration = [];
270 $getQueryArgumentsConfiguration['method'] = 'GET';
271 $getQueryArgumentsConfiguration['exclude'] = [];
272 $getQueryArgumentsConfiguration['exclude'][] = 'key1';
273 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
274 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
275 $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
276 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2&key3[key32][key322]=value322');
277 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
278 $this->assertEquals($expectedResult, $actualResult);
279 }
280
281 /**
282 * @test
283 */
284 public function getQueryArgumentsOverrulesSingleParameter()
285 {
286 $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
287 $this->returnValue('key1=value1')
288 );
289 $getQueryArgumentsConfiguration = [];
290 $overruleArguments = [
291 // Should be overridden
292 'key1' => 'value1Overruled',
293 // Shouldn't be set: Parameter doesn't exist in source array and is not forced
294 'key2' => 'value2Overruled'
295 ];
296 $expectedResult = '&key1=value1Overruled';
297 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments);
298 $this->assertEquals($expectedResult, $actualResult);
299 }
300
301 /**
302 * @test
303 */
304 public function getQueryArgumentsOverrulesMultiDimensionalParameters()
305 {
306 $_POST = [
307 'key1' => 'value1',
308 'key2' => 'value2',
309 'key3' => [
310 'key31' => 'value31',
311 'key32' => [
312 'key321' => 'value321',
313 'key322' => 'value322'
314 ]
315 ]
316 ];
317 $getQueryArgumentsConfiguration = [];
318 $getQueryArgumentsConfiguration['method'] = 'POST';
319 $getQueryArgumentsConfiguration['exclude'] = [];
320 $getQueryArgumentsConfiguration['exclude'][] = 'key1';
321 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
322 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
323 $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
324 $overruleArguments = [
325 // Should be overriden
326 'key2' => 'value2Overruled',
327 'key3' => [
328 'key32' => [
329 // Shouldn't be set: Parameter is excluded and not forced
330 'key321' => 'value321Overruled',
331 // Should be overriden: Parameter is not excluded
332 'key322' => 'value322Overruled',
333 // Shouldn't be set: Parameter doesn't exist in source array and is not forced
334 'key323' => 'value323Overruled'
335 ]
336 ]
337 ];
338 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2Overruled&key3[key32][key322]=value322Overruled');
339 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments);
340 $this->assertEquals($expectedResult, $actualResult);
341 }
342
343 /**
344 * @test
345 */
346 public function getQueryArgumentsOverrulesMultiDimensionalForcedParameters()
347 {
348 $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
349 $this->returnValue('key1=value1&key2=value2&key3[key31]=value31&key3[key32][key321]=value321&key3[key32][key322]=value322')
350 );
351 $_POST = [
352 'key1' => 'value1',
353 'key2' => 'value2',
354 'key3' => [
355 'key31' => 'value31',
356 'key32' => [
357 'key321' => 'value321',
358 'key322' => 'value322'
359 ]
360 ]
361 ];
362 $getQueryArgumentsConfiguration = [];
363 $getQueryArgumentsConfiguration['exclude'] = [];
364 $getQueryArgumentsConfiguration['exclude'][] = 'key1';
365 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
366 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
367 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key322]';
368 $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
369 $overruleArguments = [
370 // Should be overriden
371 'key2' => 'value2Overruled',
372 'key3' => [
373 'key32' => [
374 // Should be set: Parameter is excluded but forced
375 'key321' => 'value321Overruled',
376 // Should be set: Parameter doesn't exist in source array but is forced
377 'key323' => 'value323Overruled'
378 ]
379 ]
380 ];
381 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2Overruled&key3[key32][key321]=value321Overruled&key3[key32][key323]=value323Overruled');
382 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments, true);
383 $this->assertEquals($expectedResult, $actualResult);
384 $getQueryArgumentsConfiguration['method'] = 'POST';
385 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments, true);
386 $this->assertEquals($expectedResult, $actualResult);
387 }
388
389 /**
390 * @test
391 */
392 public function getQueryArgumentsWithMethodPostGetMergesParameters()
393 {
394 $_POST = [
395 'key1' => 'POST1',
396 'key2' => 'POST2',
397 'key3' => [
398 'key31' => 'POST31',
399 'key32' => 'POST32',
400 'key33' => [
401 'key331' => 'POST331',
402 'key332' => 'POST332',
403 ]
404 ]
405 ];
406 $_GET = [
407 'key2' => 'GET2',
408 'key3' => [
409 'key32' => 'GET32',
410 'key33' => [
411 'key331' => 'GET331',
412 ]
413 ]
414 ];
415 $getQueryArgumentsConfiguration = [];
416 $getQueryArgumentsConfiguration['method'] = 'POST,GET';
417 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key1=POST1&key2=GET2&key3[key31]=POST31&key3[key32]=GET32&key3[key33][key331]=GET331&key3[key33][key332]=POST332');
418 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
419 $this->assertEquals($expectedResult, $actualResult);
420 }
421
422 /**
423 * @test
424 */
425 public function getQueryArgumentsWithMethodGetPostMergesParameters()
426 {
427 $_GET = [
428 'key1' => 'GET1',
429 'key2' => 'GET2',
430 'key3' => [
431 'key31' => 'GET31',
432 'key32' => 'GET32',
433 'key33' => [
434 'key331' => 'GET331',
435 'key332' => 'GET332',
436 ]
437 ]
438 ];
439 $_POST = [
440 'key2' => 'POST2',
441 'key3' => [
442 'key32' => 'POST32',
443 'key33' => [
444 'key331' => 'POST331',
445 ]
446 ]
447 ];
448 $getQueryArgumentsConfiguration = [];
449 $getQueryArgumentsConfiguration['method'] = 'GET,POST';
450 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key1=GET1&key2=POST2&key3[key31]=GET31&key3[key32]=POST32&key3[key33][key331]=POST331&key3[key33][key332]=GET332');
451 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
452 $this->assertEquals($expectedResult, $actualResult);
453 }
454
455 /**
456 * Encodes square brackets in URL.
457 *
458 * @param string $string
459 * @return string
460 */
461 private function rawUrlEncodeSquareBracketsInUrl($string)
462 {
463 return str_replace(['[', ']'], ['%5B', '%5D'], $string);
464 }
465
466 //////////////////////////
467 // Tests concerning crop
468 //////////////////////////
469 /**
470 * @test
471 */
472 public function cropIsMultibyteSafe()
473 {
474 $this->assertEquals('бла', $this->subject->crop('бла', '3|...'));
475 }
476
477 //////////////////////////////
478 // Tests concerning cropHTML
479 //////////////////////////////
480 /**
481 * This is the data provider for the tests of crop and cropHTML below. It provides all combinations
482 * of charset, text type, and configuration options to be tested.
483 *
484 * @return array two-dimensional array with the second level like this:
485 * @see cropHtmlWithDataProvider
486 */
487 public function cropHtmlDataProvider()
488 {
489 $plainText = 'Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j implemented the original version of the crop function.';
490 $textWithMarkup = '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a>' . ' implemented</strong> the original version of the crop function.';
491 $textWithEntities = 'Kasper Sk&aring;rh&oslash;j implemented the; original ' . 'version of the crop function.';
492 $charsets = ['iso-8859-1', 'utf-8', 'ascii', 'big5'];
493 $data = [];
494 foreach ($charsets as $charset) {
495 $data = array_merge($data, [
496 $charset . ' plain text; 11|...' => [
497 '11|...',
498 $plainText,
499 'Kasper Sk' . chr(229) . 'r...',
500 $charset
501 ],
502 $charset . ' plain text; -58|...' => [
503 '-58|...',
504 $plainText,
505 '...h' . chr(248) . 'j implemented the original version of the crop function.',
506 $charset
507 ],
508 $charset . ' plain text; 4|...|1' => [
509 '4|...|1',
510 $plainText,
511 'Kasp...',
512 $charset
513 ],
514 $charset . ' plain text; 20|...|1' => [
515 '20|...|1',
516 $plainText,
517 'Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j...',
518 $charset
519 ],
520 $charset . ' plain text; -5|...|1' => [
521 '-5|...|1',
522 $plainText,
523 '...tion.',
524 $charset
525 ],
526 $charset . ' plain text; -49|...|1' => [
527 '-49|...|1',
528 $plainText,
529 '...the original version of the crop function.',
530 $charset
531 ],
532 $charset . ' text with markup; 11|...' => [
533 '11|...',
534 $textWithMarkup,
535 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'r...</a></strong>',
536 $charset
537 ],
538 $charset . ' text with markup; 13|...' => [
539 '13|...',
540 $textWithMarkup,
541 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . '...</a></strong>',
542 $charset
543 ],
544 $charset . ' text with markup; 14|...' => [
545 '14|...',
546 $textWithMarkup,
547 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>',
548 $charset
549 ],
550 $charset . ' text with markup; 15|...' => [
551 '15|...',
552 $textWithMarkup,
553 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a> ...</strong>',
554 $charset
555 ],
556 $charset . ' text with markup; 29|...' => [
557 '29|...',
558 $textWithMarkup,
559 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong> th...',
560 $charset
561 ],
562 $charset . ' text with markup; -58|...' => [
563 '-58|...',
564 $textWithMarkup,
565 '<strong><a href="mailto:kasper@typo3.org">...h' . chr(248) . 'j</a> implemented</strong> the original version of the crop function.',
566 $charset
567 ],
568 $charset . ' text with markup 4|...|1' => [
569 '4|...|1',
570 $textWithMarkup,
571 '<strong><a href="mailto:kasper@typo3.org">Kasp...</a></strong>',
572 $charset
573 ],
574 $charset . ' text with markup; 11|...|1' => [
575 '11|...|1',
576 $textWithMarkup,
577 '<strong><a href="mailto:kasper@typo3.org">Kasper...</a></strong>',
578 $charset
579 ],
580 $charset . ' text with markup; 13|...|1' => [
581 '13|...|1',
582 $textWithMarkup,
583 '<strong><a href="mailto:kasper@typo3.org">Kasper...</a></strong>',
584 $charset
585 ],
586 $charset . ' text with markup; 14|...|1' => [
587 '14|...|1',
588 $textWithMarkup,
589 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>',
590 $charset
591 ],
592 $charset . ' text with markup; 15|...|1' => [
593 '15|...|1',
594 $textWithMarkup,
595 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>',
596 $charset
597 ],
598 $charset . ' text with markup; 29|...|1' => [
599 '29|...|1',
600 $textWithMarkup,
601 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong>...',
602 $charset
603 ],
604 $charset . ' text with markup; -66|...|1' => [
605 '-66|...|1',
606 $textWithMarkup,
607 '<strong><a href="mailto:kasper@typo3.org">...Sk' . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong> the original version of the crop function.',
608 $charset
609 ],
610 $charset . ' text with entities 9|...' => [
611 '9|...',
612 $textWithEntities,
613 'Kasper Sk...',
614 $charset
615 ],
616 $charset . ' text with entities 10|...' => [
617 '10|...',
618 $textWithEntities,
619 'Kasper Sk&aring;...',
620 $charset
621 ],
622 $charset . ' text with entities 11|...' => [
623 '11|...',
624 $textWithEntities,
625 'Kasper Sk&aring;r...',
626 $charset
627 ],
628 $charset . ' text with entities 13|...' => [
629 '13|...',
630 $textWithEntities,
631 'Kasper Sk&aring;rh&oslash;...',
632 $charset
633 ],
634 $charset . ' text with entities 14|...' => [
635 '14|...',
636 $textWithEntities,
637 'Kasper Sk&aring;rh&oslash;j...',
638 $charset
639 ],
640 $charset . ' text with entities 15|...' => [
641 '15|...',
642 $textWithEntities,
643 'Kasper Sk&aring;rh&oslash;j ...',
644 $charset
645 ],
646 $charset . ' text with entities 16|...' => [
647 '16|...',
648 $textWithEntities,
649 'Kasper Sk&aring;rh&oslash;j i...',
650 $charset
651 ],
652 $charset . ' text with entities -57|...' => [
653 '-57|...',
654 $textWithEntities,
655 '...j implemented the; original version of the crop function.',
656 $charset
657 ],
658 $charset . ' text with entities -58|...' => [
659 '-58|...',
660 $textWithEntities,
661 '...&oslash;j implemented the; original version of the crop function.',
662 $charset
663 ],
664 $charset . ' text with entities -59|...' => [
665 '-59|...',
666 $textWithEntities,
667 '...h&oslash;j implemented the; original version of the crop function.',
668 $charset
669 ],
670 $charset . ' text with entities 4|...|1' => [
671 '4|...|1',
672 $textWithEntities,
673 'Kasp...',
674 $charset
675 ],
676 $charset . ' text with entities 9|...|1' => [
677 '9|...|1',
678 $textWithEntities,
679 'Kasper...',
680 $charset
681 ],
682 $charset . ' text with entities 10|...|1' => [
683 '10|...|1',
684 $textWithEntities,
685 'Kasper...',
686 $charset
687 ],
688 $charset . ' text with entities 11|...|1' => [
689 '11|...|1',
690 $textWithEntities,
691 'Kasper...',
692 $charset
693 ],
694 $charset . ' text with entities 13|...|1' => [
695 '13|...|1',
696 $textWithEntities,
697 'Kasper...',
698 $charset
699 ],
700 $charset . ' text with entities 14|...|1' => [
701 '14|...|1',
702 $textWithEntities,
703 'Kasper Sk&aring;rh&oslash;j...',
704 $charset
705 ],
706 $charset . ' text with entities 15|...|1' => [
707 '15|...|1',
708 $textWithEntities,
709 'Kasper Sk&aring;rh&oslash;j...',
710 $charset
711 ],
712 $charset . ' text with entities 16|...|1' => [
713 '16|...|1',
714 $textWithEntities,
715 'Kasper Sk&aring;rh&oslash;j...',
716 $charset
717 ],
718 $charset . ' text with entities -57|...|1' => [
719 '-57|...|1',
720 $textWithEntities,
721 '...implemented the; original version of the crop function.',
722 $charset
723 ],
724 $charset . ' text with entities -58|...|1' => [
725 '-58|...|1',
726 $textWithEntities,
727 '...implemented the; original version of the crop function.',
728 $charset
729 ],
730 $charset . ' text with entities -59|...|1' => [
731 '-59|...|1',
732 $textWithEntities,
733 '...implemented the; original version of the crop function.',
734 $charset
735 ],
736 $charset . ' text with dash in html-element 28|...|1' => [
737 '28|...|1',
738 'Some text with a link to <link email.address@example.org - mail "Open email window">my email.address@example.org</link> and text after it',
739 'Some text with a link to <link email.address@example.org - mail "Open email window">my...</link>',
740 $charset
741 ],
742 $charset . ' html elements with dashes in attributes' => [
743 '9',
744 '<em data-foo="x">foobar</em>foobaz',
745 '<em data-foo="x">foobar</em>foo',
746 $charset
747 ],
748 $charset . ' html elements with iframe embedded 24|...|1' => [
749 '24|...|1',
750 'Text with iframe <iframe src="//what.ever/"></iframe> and text after it',
751 'Text with iframe <iframe src="//what.ever/"></iframe> and...',
752 $charset
753 ],
754 $charset . ' html elements with script tag embedded 24|...|1' => [
755 '24|...|1',
756 'Text with script <script>alert(\'foo\');</script> and text after it',
757 'Text with script <script>alert(\'foo\');</script> and...',
758 $charset
759 ],
760 ]);
761 }
762 return $data;
763 }
764
765 /**
766 * Checks if stdWrap.cropHTML works with plain text cropping from left
767 *
768 * @test
769 * @dataProvider cropHtmlDataProvider
770 * @param string $settings
771 * @param string $subject the string to crop
772 * @param string $expected the expected cropped result
773 * @param string $charset the charset that will be set as renderCharset
774 */
775 public function cropHtmlWithDataProvider($settings, $subject, $expected, $charset)
776 {
777 $this->handleCharset($charset, $subject, $expected);
778 $this->assertEquals($expected, $this->subject->cropHTML($subject, $settings), 'cropHTML failed with settings: "' . $settings . '" and charset "' . $charset . '"');
779 }
780
781 /**
782 * Checks if stdWrap.cropHTML works with a complex content with many tags. Currently cropHTML
783 * counts multiple invisible characters not as one (as the browser will output the content).
784 *
785 * @test
786 */
787 public function cropHtmlWorksWithComplexContent()
788 {
789 $GLOBALS['TSFE']->renderCharset = 'iso-8859-1';
790 $input =
791 '<h1>Blog Example</h1>' . LF .
792 '<hr>' . LF .
793 '<div class="csc-header csc-header-n1">' . LF .
794 ' <h2 class="csc-firstHeader">Welcome to Blog #1</h2>' . LF .
795 '</div>' . LF .
796 '<p class="bodytext">' . LF .
797 ' A blog about TYPO3 extension development. In order to start blogging, read the <a href="#">Help section</a>. If you have any further questions, feel free to contact the administrator John Doe (<a href="mailto:john.doe@example.com">john.doe@example.com)</a>.' . LF .
798 '</p>' . LF .
799 '<div class="tx-blogexample-list-container">' . LF .
800 ' <p class="bodytext">' . LF .
801 ' Below are the most recent posts:' . LF .
802 ' </p>' . LF .
803 ' <ul>' . LF .
804 ' <li data-element="someId">' . LF .
805 ' <h3>' . LF .
806 ' <a href="index.php?id=99&amp;tx_blogexample_pi1[post][uid]=211&amp;tx_blogexample_pi1[blog]=&amp;tx_blogexample_pi1[action]=show&amp;tx_blogexample_pi1[controller]=Post&amp;cHash=003b0131ed">The Post #1</a>' . LF .
807 ' </h3>' . LF .
808 ' <p class="bodytext">' . LF .
809 ' Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut...' . LF .
810 ' </p>' . LF .
811 ' <p class="metadata">' . LF .
812 ' Published on 26.08.2009 by Jochen Rau' . LF .
813 ' </p>' . LF .
814 ' <p>' . LF .
815 ' Tags: [MVC]&nbsp;[Domain Driven Design]&nbsp;<br>' . LF .
816 ' <a href="index.php?id=99&amp;tx_blogexample_pi1[post][uid]=211&amp;tx_blogexample_pi1[action]=show&amp;tx_blogexample_pi1[controller]=Post&amp;cHash=f982643bc3">read more &gt;&gt;</a><br>' . LF .
817 ' <a href="index.php?id=99&amp;tx_blogexample_pi1[post][uid]=211&amp;tx_blogexample_pi1[blog][uid]=70&amp;tx_blogexample_pi1[action]=edit&amp;tx_blogexample_pi1[controller]=Post&amp;cHash=5b481bc8f0">Edit</a>&nbsp;<a href="index.php?id=99&amp;tx_blogexample_pi1[post][uid]=211&amp;tx_blogexample_pi1[blog][uid]=70&amp;tx_blogexample_pi1[action]=delete&amp;tx_blogexample_pi1[controller]=Post&amp;cHash=4e52879656">Delete</a>' . LF .
818 ' </p>' . LF .
819 ' </li>' . LF .
820 ' </ul>' . LF .
821 ' <p>' . LF .
822 ' <a href="index.php?id=99&amp;tx_blogexample_pi1[blog][uid]=70&amp;tx_blogexample_pi1[action]=new&amp;tx_blogexample_pi1[controller]=Post&amp;cHash=2718a4b1a0">Create a new Post</a>' . LF .
823 ' </p>' . LF .
824 '</div>' . LF .
825 '<hr>' . LF .
826 '<p>' . LF .
827 ' ? TYPO3 Association' . LF .
828 '</p>';
829
830 $result = $this->subject->cropHTML($input, '300');
831
832 $expected =
833 '<h1>Blog Example</h1>' . LF .
834 '<hr>' . LF .
835 '<div class="csc-header csc-header-n1">' . LF .
836 ' <h2 class="csc-firstHeader">Welcome to Blog #1</h2>' . LF .
837 '</div>' . LF .
838 '<p class="bodytext">' . LF .
839 ' A blog about TYPO3 extension development. In order to start blogging, read the <a href="#">Help section</a>. If you have any further questions, feel free to contact the administrator John Doe (<a href="mailto:john.doe@example.com">john.doe@example.com)</a>.' . LF .
840 '</p>' . LF .
841 '<div class="tx-blogexample-list-container">' . LF .
842 ' <p class="bodytext">' . LF .
843 ' Below are the most recent posts:' . LF .
844 ' </p>' . LF .
845 ' <ul>' . LF .
846 ' <li data-element="someId">' . LF .
847 ' <h3>' . LF .
848 ' <a href="index.php?id=99&amp;tx_blogexample_pi1[post][uid]=211&amp;tx_blogexample_pi1[blog]=&amp;tx_blogexample_pi1[action]=show&amp;tx_blogexample_pi1[controller]=Post&amp;cHash=003b0131ed">The Post</a></h3></li></ul></div>';
849
850 $this->assertEquals($expected, $result);
851
852 $result = $this->subject->cropHTML($input, '-100');
853
854 $expected =
855 '<div class="tx-blogexample-list-container"><ul><li data-element="someId"><p> Design]&nbsp;<br>' . LF .
856 ' <a href="index.php?id=99&amp;tx_blogexample_pi1[post][uid]=211&amp;tx_blogexample_pi1[action]=show&amp;tx_blogexample_pi1[controller]=Post&amp;cHash=f982643bc3">read more &gt;&gt;</a><br>' . LF .
857 ' <a href="index.php?id=99&amp;tx_blogexample_pi1[post][uid]=211&amp;tx_blogexample_pi1[blog][uid]=70&amp;tx_blogexample_pi1[action]=edit&amp;tx_blogexample_pi1[controller]=Post&amp;cHash=5b481bc8f0">Edit</a>&nbsp;<a href="index.php?id=99&amp;tx_blogexample_pi1[post][uid]=211&amp;tx_blogexample_pi1[blog][uid]=70&amp;tx_blogexample_pi1[action]=delete&amp;tx_blogexample_pi1[controller]=Post&amp;cHash=4e52879656">Delete</a>' . LF .
858 ' </p>' . LF .
859 ' </li>' . LF .
860 ' </ul>' . LF .
861 ' <p>' . LF .
862 ' <a href="index.php?id=99&amp;tx_blogexample_pi1[blog][uid]=70&amp;tx_blogexample_pi1[action]=new&amp;tx_blogexample_pi1[controller]=Post&amp;cHash=2718a4b1a0">Create a new Post</a>' . LF .
863 ' </p>' . LF .
864 '</div>' . LF .
865 '<hr>' . LF .
866 '<p>' . LF .
867 ' ? TYPO3 Association' . LF .
868 '</p>';
869
870 $this->assertEquals($expected, $result);
871 }
872
873 /**
874 * Checks if stdWrap.cropHTML handles linebreaks correctly (by ignoring them)
875 *
876 * @test
877 */
878 public function cropHtmlWorksWithLinebreaks()
879 {
880 $subject = "Lorem ipsum dolor sit amet,\nconsetetur sadipscing elitr,\nsed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam";
881 $expected = "Lorem ipsum dolor sit amet,\nconsetetur sadipscing elitr,\nsed diam nonumy eirmod tempor invidunt ut labore et dolore magna";
882 $result = $this->subject->cropHTML($subject, '121');
883 $this->assertEquals($expected, $result);
884 }
885
886 /**
887 * @return array
888 */
889 public function stdWrap_roundDataProvider()
890 {
891 return [
892 'rounding off without any configuration' => [
893 1.123456789,
894 [],
895 1
896 ],
897 'rounding up without any configuration' => [
898 1.523456789,
899 [],
900 2
901 ],
902 'regular rounding (off) to two decimals' => [
903 0.123456789,
904 [
905 'decimals' => 2
906 ],
907 0.12
908 ],
909 'regular rounding (up) to two decimals' => [
910 0.1256789,
911 [
912 'decimals' => 2
913 ],
914 0.13
915 ],
916 'rounding up to integer with type ceil' => [
917 0.123456789,
918 [
919 'roundType' => 'ceil'
920 ],
921 1
922 ],
923 'rounding down to integer with type floor' => [
924 2.3481,
925 [
926 'roundType' => 'floor'
927 ],
928 2
929 ]
930 ];
931 }
932
933 /**
934 * Test for the stdWrap function "round"
935 *
936 * @param float $float
937 * @param array $conf
938 * @param float $expected
939 * @return void
940 * @dataProvider stdWrap_roundDataProvider
941 * @test
942 */
943 public function stdWrap_round($float, $conf, $expected)
944 {
945 $conf = [
946 'round.' => $conf
947 ];
948 $result = $this->subject->stdWrap_round($float, $conf);
949 $this->assertEquals($expected, $result);
950 }
951
952 /**
953 * @return array
954 */
955 public function stdWrap_numberFormatDataProvider()
956 {
957 return [
958 'testing decimals' => [
959 0.8,
960 [
961 'numberFormat.' => [
962 'decimals' => 2
963 ],
964 ],
965 '0.80'
966 ],
967 'testing decimals with input as string' => [
968 '0.8',
969 [
970 'numberFormat.' => [
971 'decimals' => 2
972 ],
973 ],
974 '0.80'
975 ],
976 'testing dec_point' => [
977 0.8,
978 [
979 'numberFormat.' => [
980 'decimals' => 1,
981 'dec_point' => ','
982 ],
983 ],
984 '0,8'
985 ],
986 'testing thousands_sep' => [
987 999.99,
988 [
989 'numberFormat.' => [
990 'decimals' => 0,
991 'thousands_sep.' => [
992 'char' => 46
993 ],
994 ],
995 ],
996 '1.000'
997 ],
998 'testing mixture' => [
999 1281731.45,
1000 [
1001 'numberFormat.' => [
1002 'decimals' => 1,
1003 'dec_point.' => [
1004 'char' => 44
1005 ],
1006 'thousands_sep.' => [
1007 'char' => 46
1008 ],
1009 ],
1010 ],
1011 '1.281.731,5'
1012 ]
1013 ];
1014 }
1015
1016 /**
1017 * Test for the stdWrap function "round"
1018 *
1019 * @param float $float
1020 * @param array $conf
1021 * @param string $expected
1022 * @return void
1023 * @dataProvider stdWrap_numberFormatDataProvider
1024 * @test
1025 */
1026 public function stdWrap_numberFormat($float, $conf, $expected)
1027 {
1028 $result = $this->subject->stdWrap_numberFormat($float, $conf);
1029 $this->assertEquals($expected, $result);
1030 }
1031
1032 /**
1033 * @return array
1034 */
1035 public function stdWrap_expandListDataProvider()
1036 {
1037 return [
1038 'numbers' => [
1039 '1,2,3',
1040 '1,2,3',
1041 ],
1042 'range' => [
1043 '3-5',
1044 '3,4,5',
1045 ],
1046 'numbers and range' => [
1047 '1,3-5,7',
1048 '1,3,4,5,7',
1049 ],
1050 ];
1051 }
1052
1053 /**
1054 * Test for the stdWrap function "expandList"
1055 *
1056 * @param string $content
1057 * @param string $expected
1058 *
1059 * @dataProvider stdWrap_expandListDataProvider
1060 * @test
1061 */
1062 public function stdWrap_expandList($content, $expected)
1063 {
1064 $result = $this->subject->stdWrap_expandList($content);
1065 $this->assertEquals($expected, $result);
1066 }
1067
1068 /**
1069 * @return array
1070 */
1071 public function stdWrap_trimDataProvider()
1072 {
1073 return [
1074 'trimstring' => [
1075 'trimstring',
1076 'trimstring',
1077 ],
1078 'trim string with space inside' => [
1079 'trim string',
1080 'trim string',
1081 ],
1082 'trim string with space at the begin and end' => [
1083 ' trim string ',
1084 'trim string',
1085 ],
1086 ];
1087 }
1088
1089 /**
1090 * Test for the stdWrap function "trim"
1091 *
1092 * @param string $content
1093 * @param string $expected
1094 *
1095 * @dataProvider stdWrap_trimDataProvider
1096 * @test
1097 */
1098 public function stdWrap_trim($content, $expected)
1099 {
1100 $result = $this->subject->stdWrap_trim($content);
1101 $this->assertEquals($expected, $result);
1102 }
1103
1104 /**
1105 * @return array
1106 */
1107 public function stdWrap_intvalDataProvider()
1108 {
1109 return [
1110 'number' => [
1111 '123',
1112 123,
1113 ],
1114 'float' => [
1115 '123.45',
1116 123,
1117 ],
1118 'string' => [
1119 'string',
1120 0,
1121 ],
1122 'zero' => [
1123 '0',
1124 0,
1125 ],
1126 'empty' => [
1127 '',
1128 0,
1129 ],
1130 'NULL' => [
1131 null,
1132 0,
1133 ],
1134 'bool TRUE' => [
1135 true,
1136 1,
1137 ],
1138 'bool FALSE' => [
1139 false,
1140 0,
1141 ],
1142 ];
1143 }
1144
1145 /**
1146 * Test for the stdWrap function "intval"
1147 *
1148 * @param string $content
1149 * @param int $expected
1150 *
1151 * @dataProvider stdWrap_intvalDataProvider
1152 * @test
1153 */
1154 public function stdWrap_intval($content, $expected)
1155 {
1156 $result = $this->subject->stdWrap_intval($content);
1157 $this->assertEquals($expected, $result);
1158 }
1159
1160 /**
1161 * @return array
1162 */
1163 public function stdWrap_strPadDataProvider()
1164 {
1165 return [
1166 'pad string with default settings and length 10' => [
1167 'Alien',
1168 [
1169 'length' => '10',
1170 ],
1171 'Alien ',
1172 ],
1173 'pad string with padWith -= and type left and length 10' => [
1174 'Alien',
1175 [
1176 'length' => '10',
1177 'padWith' => '-=',
1178 'type' => 'left',
1179 ],
1180 '-=-=-Alien',
1181 ],
1182 'pad string with padWith _ and type both and length 10' => [
1183 'Alien',
1184 [
1185 'length' => '10',
1186 'padWith' => '_',
1187 'type' => 'both',
1188 ],
1189 '__Alien___',
1190 ],
1191 'pad string with padWith 0 and type both and length 10' => [
1192 'Alien',
1193 [
1194 'length' => '10',
1195 'padWith' => '0',
1196 'type' => 'both',
1197 ],
1198 '00Alien000',
1199 ],
1200 'pad string with padWith ___ and type both and length 6' => [
1201 'Alien',
1202 [
1203 'length' => '6',
1204 'padWith' => '___',
1205 'type' => 'both',
1206 ],
1207 'Alien_',
1208 ],
1209 'pad string with padWith _ and type both and length 12, using stdWrap for length' => [
1210 'Alien',
1211 [
1212 'length' => '1',
1213 'length.' => [
1214 'wrap' => '|2',
1215 ],
1216 'padWith' => '_',
1217 'type' => 'both',
1218 ],
1219 '___Alien____',
1220 ],
1221 'pad string with padWith _ and type both and length 12, using stdWrap for padWidth' => [
1222 'Alien',
1223 [
1224 'length' => '12',
1225 'padWith' => '_',
1226 'padWith.' => [
1227 'wrap' => '-|=',
1228 ],
1229 'type' => 'both',
1230 ],
1231 '-_=Alien-_=-',
1232 ],
1233 'pad string with padWith _ and type both and length 12, using stdWrap for type' => [
1234 'Alien',
1235 [
1236 'length' => '12',
1237 'padWith' => '_',
1238 'type' => 'both',
1239 // make type become "left"
1240 'type.' => [
1241 'substring' => '2,1',
1242 'wrap' => 'lef|',
1243 ],
1244 ],
1245 '_______Alien',
1246 ],
1247 ];
1248 }
1249
1250 /**
1251 * Test for the stdWrap function "strPad"
1252 *
1253 * @param string $content
1254 * @param array $conf
1255 * @param string $expected
1256 *
1257 * @dataProvider stdWrap_strPadDataProvider
1258 * @test
1259 */
1260 public function stdWrap_strPad($content, $conf, $expected)
1261 {
1262 $conf = [
1263 'strPad.' => $conf
1264 ];
1265 $result = $this->subject->stdWrap_strPad($content, $conf);
1266 $this->assertEquals($expected, $result);
1267 }
1268
1269 /**
1270 * Data provider for the hash test
1271 *
1272 * @return array multi-dimensional array with the second level like this:
1273 * @see hash
1274 */
1275 public function hashDataProvider()
1276 {
1277 $data = [
1278 'testing md5' => [
1279 'joh316',
1280 [
1281 'hash' => 'md5'
1282 ],
1283 'bacb98acf97e0b6112b1d1b650b84971'
1284 ],
1285 'testing sha1' => [
1286 'joh316',
1287 [
1288 'hash' => 'sha1'
1289 ],
1290 '063b3d108bed9f88fa618c6046de0dccadcf3158'
1291 ],
1292 'testing non-existing hashing algorithm' => [
1293 'joh316',
1294 [
1295 'hash' => 'non-existing'
1296 ],
1297 ''
1298 ],
1299 'testing stdWrap capability' => [
1300 'joh316',
1301 [
1302 'hash.' => [
1303 'cObject' => 'TEXT',
1304 'cObject.' => [
1305 'value' => 'md5'
1306 ]
1307 ]
1308 ],
1309 'bacb98acf97e0b6112b1d1b650b84971'
1310 ]
1311 ];
1312 return $data;
1313 }
1314
1315 /**
1316 * Test for the stdWrap function "hash"
1317 *
1318 * @param string $text
1319 * @param array $conf
1320 * @param string $expected
1321 * @return void
1322 * @dataProvider hashDataProvider
1323 * @test
1324 */
1325 public function stdWrap_hash($text, array $conf, $expected)
1326 {
1327 $result = $this->subject->stdWrap_hash($text, $conf);
1328 $this->assertEquals($expected, $result);
1329 }
1330
1331 /**
1332 * @test
1333 */
1334 public function recursiveStdWrapProperlyRendersBasicString()
1335 {
1336 $stdWrapConfiguration = [
1337 'noTrimWrap' => '|| 123|',
1338 'stdWrap.' => [
1339 'wrap' => '<b>|</b>'
1340 ]
1341 ];
1342 $this->assertSame(
1343 '<b>Test</b> 123',
1344 $this->subject->stdWrap('Test', $stdWrapConfiguration)
1345 );
1346 }
1347
1348 /**
1349 * @test
1350 */
1351 public function recursiveStdWrapIsOnlyCalledOnce()
1352 {
1353 $stdWrapConfiguration = [
1354 'append' => 'TEXT',
1355 'append.' => [
1356 'data' => 'register:Counter'
1357 ],
1358 'stdWrap.' => [
1359 'append' => 'LOAD_REGISTER',
1360 'append.' => [
1361 'Counter.' => [
1362 'prioriCalc' => 'intval',
1363 'cObject' => 'TEXT',
1364 'cObject.' => [
1365 'data' => 'register:Counter',
1366 'wrap' => '|+1',
1367 ]
1368 ]
1369 ]
1370 ]
1371 ];
1372 $this->assertSame(
1373 'Counter:1',
1374 $this->subject->stdWrap('Counter:', $stdWrapConfiguration)
1375 );
1376 }
1377
1378 /**
1379 * Data provider for the numberFormat test
1380 *
1381 * @return array multi-dimensional array with the second level like this:
1382 * @see numberFormat
1383 */
1384 public function numberFormatDataProvider()
1385 {
1386 $data = [
1387 'testing decimals' => [
1388 0.8,
1389 [
1390 'decimals' => 2
1391 ],
1392 '0.80'
1393 ],
1394 'testing decimals with input as string' => [
1395 '0.8',
1396 [
1397 'decimals' => 2
1398 ],
1399 '0.80'
1400 ],
1401 'testing dec_point' => [
1402 0.8,
1403 [
1404 'decimals' => 1,
1405 'dec_point' => ','
1406 ],
1407 '0,8'
1408 ],
1409 'testing thousands_sep' => [
1410 999.99,
1411 [
1412 'decimals' => 0,
1413 'thousands_sep.' => [
1414 'char' => 46
1415 ]
1416 ],
1417 '1.000'
1418 ],
1419 'testing mixture' => [
1420 1281731.45,
1421 [
1422 'decimals' => 1,
1423 'dec_point.' => [
1424 'char' => 44
1425 ],
1426 'thousands_sep.' => [
1427 'char' => 46
1428 ]
1429 ],
1430 '1.281.731,5'
1431 ]
1432 ];
1433 return $data;
1434 }
1435
1436 /**
1437 * Check if stdWrap.numberFormat and all of its properties work properly
1438 *
1439 * @dataProvider numberFormatDataProvider
1440 * @test
1441 */
1442 public function numberFormat($float, $formatConf, $expected)
1443 {
1444 $result = $this->subject->numberFormat($float, $formatConf);
1445 $this->assertEquals($expected, $result);
1446 }
1447
1448 /**
1449 * Data provider for the replacement test
1450 *
1451 * @return array multi-dimensional array with the second level like this:
1452 * @see replacement
1453 */
1454 public function replacementDataProvider()
1455 {
1456 $data = [
1457 'multiple replacements, including regex' => [
1458 'There_is_a_cat,_a_dog_and_a_tiger_in_da_hood!_Yeah!',
1459 [
1460 'replacement.' => [
1461 '120.' => [
1462 'search' => 'in da hood',
1463 'replace' => 'around the block'
1464 ],
1465 '20.' => [
1466 'search' => '_',
1467 'replace.' => ['char' => '32']
1468 ],
1469 '130.' => [
1470 'search' => '#a (Cat|Dog|Tiger)#i',
1471 'replace' => 'an animal',
1472 'useRegExp' => '1'
1473 ]
1474 ]
1475 ],
1476 'There is an animal, an animal and an animal around the block! Yeah!'
1477 ],
1478 'replacement with optionSplit, normal pattern' => [
1479 'There_is_a_cat,_a_dog_and_a_tiger_in_da_hood!_Yeah!',
1480 [
1481 'replacement.' => [
1482 '10.' => [
1483 'search' => '_',
1484 'replace' => '1 || 2 || 3',
1485 'useOptionSplitReplace' => '1'
1486 ],
1487 ]
1488 ],
1489 'There1is2a3cat,3a3dog3and3a3tiger3in3da3hood!3Yeah!'
1490 ],
1491 'replacement with optionSplit, using regex' => [
1492 'There is a cat, a dog and a tiger in da hood! Yeah!',
1493 [
1494 'replacement.' => [
1495 '10.' => [
1496 'search' => '#(a) (Cat|Dog|Tiger)#i',
1497 'replace' => '${1} tiny ${2} || ${1} midsized ${2} || ${1} big ${2}',
1498 'useOptionSplitReplace' => '1',
1499 'useRegExp' => '1'
1500 ]
1501 ]
1502 ],
1503 'There is a tiny cat, a midsized dog and a big tiger in da hood! Yeah!'
1504 ],
1505 ];
1506 return $data;
1507 }
1508
1509 /**
1510 * Check if stdWrap.replacement and all of its properties work properly
1511 *
1512 * @dataProvider replacementDataProvider
1513 * @test
1514 */
1515 public function replacement($input, $conf, $expected)
1516 {
1517 $result = $this->subject->stdWrap_replacement($input, $conf);
1518 $this->assertEquals($expected, $result);
1519 }
1520
1521 /**
1522 * Data provider for the getQuery test
1523 *
1524 * @return array multi-dimensional array with the second level like this:
1525 * @see getQuery
1526 */
1527 public function getQueryDataProvider()
1528 {
1529 $data = [
1530 'testing empty conf' => [
1531 'tt_content',
1532 [],
1533 [
1534 'SELECT' => '*'
1535 ]
1536 ],
1537 'testing #17284: adding uid/pid for workspaces' => [
1538 'tt_content',
1539 [
1540 'selectFields' => 'header,bodytext'
1541 ],
1542 [
1543 'SELECT' => 'header,bodytext, tt_content.uid as uid, tt_content.pid as pid, tt_content.t3ver_state as t3ver_state'
1544 ]
1545 ],
1546 'testing #17284: no need to add' => [
1547 'tt_content',
1548 [
1549 'selectFields' => 'tt_content.*'
1550 ],
1551 [
1552 'SELECT' => 'tt_content.*'
1553 ]
1554 ],
1555 'testing #17284: no need to add #2' => [
1556 'tt_content',
1557 [
1558 'selectFields' => '*'
1559 ],
1560 [
1561 'SELECT' => '*'
1562 ]
1563 ],
1564 'testing #29783: joined tables, prefix tablename' => [
1565 'tt_content',
1566 [
1567 'selectFields' => 'tt_content.header,be_users.username',
1568 'join' => 'be_users ON tt_content.cruser_id = be_users.uid'
1569 ],
1570 [
1571 'SELECT' => 'tt_content.header,be_users.username, tt_content.uid as uid, tt_content.pid as pid, tt_content.t3ver_state as t3ver_state'
1572 ]
1573 ],
1574 'testing #34152: single count(*), add nothing' => [
1575 'tt_content',
1576 [
1577 'selectFields' => 'count(*)'
1578 ],
1579 [
1580 'SELECT' => 'count(*)'
1581 ]
1582 ],
1583 'testing #34152: single max(crdate), add nothing' => [
1584 'tt_content',
1585 [
1586 'selectFields' => 'max(crdate)'
1587 ],
1588 [
1589 'SELECT' => 'max(crdate)'
1590 ]
1591 ],
1592 'testing #34152: single min(crdate), add nothing' => [
1593 'tt_content',
1594 [
1595 'selectFields' => 'min(crdate)'
1596 ],
1597 [
1598 'SELECT' => 'min(crdate)'
1599 ]
1600 ],
1601 'testing #34152: single sum(is_siteroot), add nothing' => [
1602 'tt_content',
1603 [
1604 'selectFields' => 'sum(is_siteroot)'
1605 ],
1606 [
1607 'SELECT' => 'sum(is_siteroot)'
1608 ]
1609 ],
1610 'testing #34152: single avg(crdate), add nothing' => [
1611 'tt_content',
1612 [
1613 'selectFields' => 'avg(crdate)'
1614 ],
1615 [
1616 'SELECT' => 'avg(crdate)'
1617 ]
1618 ]
1619 ];
1620 return $data;
1621 }
1622
1623 /**
1624 * Check if sanitizeSelectPart works as expected
1625 *
1626 * @dataProvider getQueryDataProvider
1627 * @test
1628 */
1629 public function getQuery($table, $conf, $expected)
1630 {
1631 $GLOBALS['TCA'] = [
1632 'pages' => [
1633 'ctrl' => [
1634 'enablecolumns' => [
1635 'disabled' => 'hidden'
1636 ]
1637 ]
1638 ],
1639 'tt_content' => [
1640 'ctrl' => [
1641 'enablecolumns' => [
1642 'disabled' => 'hidden'
1643 ],
1644 'versioningWS' => true
1645 ]
1646 ],
1647 ];
1648 $result = $this->subject->getQuery($table, $conf, true);
1649 foreach ($expected as $field => $value) {
1650 $this->assertEquals($value, $result[$field]);
1651 }
1652 }
1653
1654 /**
1655 * @test
1656 */
1657 public function getQueryCallsGetTreeListWithNegativeValuesIfRecursiveIsSet()
1658 {
1659 $GLOBALS['TCA'] = [
1660 'pages' => [
1661 'ctrl' => [
1662 'enablecolumns' => [
1663 'disabled' => 'hidden'
1664 ]
1665 ]
1666 ],
1667 'tt_content' => [
1668 'ctrl' => [
1669 'enablecolumns' => [
1670 'disabled' => 'hidden'
1671 ]
1672 ]
1673 ],
1674 ];
1675 $this->subject = $this->getAccessibleMock(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class, ['getTreeList']);
1676 $this->subject->start([], 'tt_content');
1677 $conf = [
1678 'recursive' => '15',
1679 'pidInList' => '16, -35'
1680 ];
1681 $this->subject->expects($this->at(0))
1682 ->method('getTreeList')
1683 ->with(-16, 15)
1684 ->will($this->returnValue('15,16'));
1685 $this->subject->expects($this->at(1))
1686 ->method('getTreeList')
1687 ->with(-35, 15)
1688 ->will($this->returnValue('15,35'));
1689 $this->subject->getQuery('tt_content', $conf, true);
1690 }
1691
1692 /**
1693 * @test
1694 */
1695 public function getQueryCallsGetTreeListWithCurrentPageIfThisIsSet()
1696 {
1697 $GLOBALS['TCA'] = [
1698 'pages' => [
1699 'ctrl' => [
1700 'enablecolumns' => [
1701 'disabled' => 'hidden'
1702 ]
1703 ]
1704 ],
1705 'tt_content' => [
1706 'ctrl' => [
1707 'enablecolumns' => [
1708 'disabled' => 'hidden'
1709 ]
1710 ]
1711 ],
1712 ];
1713 $this->subject = $this->getAccessibleMock(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class, ['getTreeList']);
1714 $GLOBALS['TSFE']->id = 27;
1715 $this->subject->start([], 'tt_content');
1716 $conf = [
1717 'pidInList' => 'this',
1718 'recursive' => '4'
1719 ];
1720 $this->subject->expects($this->once())
1721 ->method('getTreeList')
1722 ->with(-27)
1723 ->will($this->returnValue('27'));
1724 $this->subject->getQuery('tt_content', $conf, true);
1725 }
1726
1727 /**
1728 * Data provider for the stdWrap_date test
1729 *
1730 * @return array multi-dimensional array with the second level like this:
1731 * @see stdWrap_date
1732 */
1733 public function stdWrap_dateDataProvider()
1734 {
1735 return [
1736 'given timestamp' => [
1737 1443780000, // This is 2015-10-02 12:00
1738 [
1739 'date' => 'd.m.Y',
1740 ],
1741 '02.10.2015',
1742 ],
1743 'empty string' => [
1744 '',
1745 [
1746 'date' => 'd.m.Y',
1747 ],
1748 '02.10.2015',
1749 ],
1750 'testing null' => [
1751 null,
1752 [
1753 'date' => 'd.m.Y',
1754 ],
1755 '02.10.2015',
1756 ],
1757 'given timestamp return GMT' => [
1758 1443780000, // This is 2015-10-02 12:00
1759 [
1760 'date' => 'd.m.Y H:i:s',
1761 'date.' => [
1762 'GMT' => true,
1763 ]
1764 ],
1765 '02.10.2015 10:00:00',
1766 ],
1767 ];
1768 }
1769
1770 /**
1771 * @test
1772 * @dataProvider stdWrap_dateDataProvider
1773 * @param string|int|NULL $content
1774 * @param array $conf
1775 * @param string $expected
1776 */
1777 public function stdWrap_date($content, $conf, $expected)
1778 {
1779 // Set exec_time to a hard timestamp
1780 $GLOBALS['EXEC_TIME'] = 1443780000;
1781
1782 $result = $this->subject->stdWrap_date($content, $conf);
1783
1784 $this->assertEquals($expected, $result);
1785 }
1786
1787 /**
1788 * Data provider for the stdWrap_strftime test
1789 *
1790 * @return array multi-dimensional array with the second level like this:
1791 * @see stdWrap_strftime
1792 */
1793 public function stdWrap_strftimeReturnsFormattedStringDataProvider()
1794 {
1795 $data = [
1796 'given timestamp' => [
1797 1346500800, // This is 2012-09-01 12:00 in UTC/GMT
1798 [
1799 'strftime' => '%d-%m-%Y',
1800 ],
1801 ],
1802 'empty string' => [
1803 '',
1804 [
1805 'strftime' => '%d-%m-%Y',
1806 ],
1807 ],
1808 'testing null' => [
1809 null,
1810 [
1811 'strftime' => '%d-%m-%Y',
1812 ],
1813 ],
1814 ];
1815 return $data;
1816 }
1817
1818 /**
1819 * @test
1820 * @dataProvider stdWrap_strftimeReturnsFormattedStringDataProvider
1821 */
1822 public function stdWrap_strftimeReturnsFormattedString($content, $conf)
1823 {
1824 // Set exec_time to a hard timestamp
1825 $GLOBALS['EXEC_TIME'] = 1346500800;
1826 // Save current timezone and set to UTC to make the system under test behave
1827 // the same in all server timezone settings
1828 $timezoneBackup = date_default_timezone_get();
1829 date_default_timezone_set('UTC');
1830
1831 $result = $this->subject->stdWrap_strftime($content, $conf);
1832
1833 // Reset timezone
1834 date_default_timezone_set($timezoneBackup);
1835
1836 $this->assertEquals('01-09-2012', $result);
1837 }
1838
1839 /**
1840 * Data provider for the stdWrap_strtotime test
1841 *
1842 * @return array
1843 * @see stdWrap_strtotime
1844 */
1845 public function stdWrap_strtotimeReturnsTimestampDataProvider()
1846 {
1847 return [
1848 'date from content' => [
1849 '2014-12-04',
1850 [
1851 'strtotime' => '1',
1852 ],
1853 1417651200,
1854 ],
1855 'manipulation of date from content' => [
1856 '2014-12-04',
1857 [
1858 'strtotime' => '+ 2 weekdays',
1859 ],
1860 1417996800,
1861 ],
1862 'date from configuration' => [
1863 '',
1864 [
1865 'strtotime' => '2014-12-04',
1866 ],
1867 1417651200,
1868 ],
1869 'manipulation of date from configuration' => [
1870 '',
1871 [
1872 'strtotime' => '2014-12-04 + 2 weekdays',
1873 ],
1874 1417996800,
1875 ],
1876 'empty input' => [
1877 '',
1878 [
1879 'strtotime' => '1',
1880 ],
1881 false,
1882 ],
1883 'date from content and configuration' => [
1884 '2014-12-04',
1885 [
1886 'strtotime' => '2014-12-05',
1887 ],
1888 false,
1889 ],
1890 ];
1891 }
1892
1893 /**
1894 * @param string|NULL $content
1895 * @param array $configuration
1896 * @param int $expected
1897 * @dataProvider stdWrap_strtotimeReturnsTimestampDataProvider
1898 * @test
1899 */
1900 public function stdWrap_strtotimeReturnsTimestamp($content, $configuration, $expected)
1901 {
1902 // Set exec_time to a hard timestamp
1903 $GLOBALS['EXEC_TIME'] = 1417392000;
1904 // Save current timezone and set to UTC to make the system under test behave
1905 // the same in all server timezone settings
1906 $timezoneBackup = date_default_timezone_get();
1907 date_default_timezone_set('UTC');
1908
1909 $result = $this->subject->stdWrap_strtotime($content, $configuration);
1910
1911 // Reset timezone
1912 date_default_timezone_set($timezoneBackup);
1913
1914 $this->assertEquals($expected, $result);
1915 }
1916
1917 /**
1918 * @test
1919 */
1920 public function stdWrap_ageCallsCalcAgeWithSubtractedTimestampAndSubPartOfArray()
1921 {
1922 $subject = $this->getMock(
1923 \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
1924 ['calcAge']
1925 );
1926 // Set exec_time to a hard timestamp
1927 $GLOBALS['EXEC_TIME'] = 10;
1928 $subject->expects($this->once())->method('calcAge')->with(1, 'Min| Hrs| Days| Yrs');
1929 $subject->stdWrap_age(9, ['age' => 'Min| Hrs| Days| Yrs']);
1930 }
1931
1932 /**
1933 * Data provider for calcAgeCalculatesAgeOfTimestamp
1934 *
1935 * @return array
1936 * @see calcAge
1937 */
1938 public function calcAgeCalculatesAgeOfTimestampDataProvider()
1939 {
1940 return [
1941 'minutes' => [
1942 120,
1943 ' min| hrs| days| yrs',
1944 '2 min',
1945 ],
1946 'hours' => [
1947 7200,
1948 ' min| hrs| days| yrs',
1949 '2 hrs',
1950 ],
1951 'days' => [
1952 604800,
1953 ' min| hrs| days| yrs',
1954 '7 days',
1955 ],
1956 'day with provided singular labels' => [
1957 86400,
1958 ' min| hrs| days| yrs| min| hour| day| year',
1959 '1 day',
1960 ],
1961 'years' => [
1962 1417997800,
1963 ' min| hrs| days| yrs',
1964 '45 yrs',
1965 ],
1966 'different labels' => [
1967 120,
1968 ' Minutes| Hrs| Days| Yrs',
1969 '2 Minutes',
1970 ],
1971 'negative values' => [
1972 -604800,
1973 ' min| hrs| days| yrs',
1974 '-7 days',
1975 ],
1976 'default label values for wrong label input' => [
1977 121,
1978 10,
1979 '2 min',
1980 ],
1981 'default singular label values for wrong label input' => [
1982 31536000,
1983 10,
1984 '1 year',
1985 ]
1986 ];
1987 }
1988
1989 /**
1990 * @param int $timestamp
1991 * @param string $labels
1992 * @param int $expectation
1993 * @dataProvider calcAgeCalculatesAgeOfTimestampDataProvider
1994 * @test
1995 */
1996 public function calcAgeCalculatesAgeOfTimestamp($timestamp, $labels, $expectation)
1997 {
1998 $result = $this->subject->calcAge($timestamp, $labels);
1999 $this->assertEquals($result, $expectation);
2000 }
2001
2002 /**
2003 * Data provider for stdWrap_case test
2004 *
2005 * @return array
2006 */
2007 public function stdWrap_caseDataProvider()
2008 {
2009 return [
2010 'lower case text to upper' => [
2011 '<span>text</span>',
2012 [
2013 'case' => 'upper',
2014 ],
2015 '<span>TEXT</span>',
2016 ],
2017 'upper case text to lower' => [
2018 '<span>TEXT</span>',
2019 [
2020 'case' => 'lower',
2021 ],
2022 '<span>text</span>',
2023 ],
2024 'capitalize text' => [
2025 '<span>this is a text</span>',
2026 [
2027 'case' => 'capitalize',
2028 ],
2029 '<span>This Is A Text</span>',
2030 ],
2031 'ucfirst text' => [
2032 '<span>this is a text</span>',
2033 [
2034 'case' => 'ucfirst',
2035 ],
2036 '<span>This is a text</span>',
2037 ],
2038 'lcfirst text' => [
2039 '<span>This is a Text</span>',
2040 [
2041 'case' => 'lcfirst',
2042 ],
2043 '<span>this is a Text</span>',
2044 ],
2045 'uppercamelcase text' => [
2046 '<span>this_is_a_text</span>',
2047 [
2048 'case' => 'uppercamelcase',
2049 ],
2050 '<span>ThisIsAText</span>',
2051 ],
2052 'lowercamelcase text' => [
2053 '<span>this_is_a_text</span>',
2054 [
2055 'case' => 'lowercamelcase',
2056 ],
2057 '<span>thisIsAText</span>',
2058 ],
2059 ];
2060 }
2061
2062 /**
2063 * @param string|NULL $content
2064 * @param array $configuration
2065 * @param string $expected
2066 * @dataProvider stdWrap_caseDataProvider
2067 * @test
2068 */
2069 public function stdWrap_case($content, array $configuration, $expected)
2070 {
2071 $result = $this->subject->stdWrap_case($content, $configuration);
2072 $this->assertEquals($expected, $result);
2073 }
2074
2075 /**
2076 * Data provider for stdWrap_bytes test
2077 *
2078 * @return array
2079 */
2080 public function stdWrap_bytesDataProvider()
2081 {
2082 return [
2083 'value 1234 default' => [
2084 '1234',
2085 [
2086 'bytes.' => [
2087 'labels' => '',
2088 'base' => 0,
2089 ],
2090 ],
2091 '1.21 Ki',
2092 'en_US.UTF-8'
2093 ],
2094 'value 1234 si' => [
2095 '1234',
2096 [
2097 'bytes.' => [
2098 'labels' => 'si',
2099 'base' => 0,
2100 ],
2101 ],
2102 '1.23 k',
2103 'en_US.UTF-8'
2104 ],
2105 'value 1234 iec' => [
2106 '1234',
2107 [
2108 'bytes.' => [
2109 'labels' => 'iec',
2110 'base' => 0,
2111 ],
2112 ],
2113 '1.21 Ki',
2114 'en_US.UTF-8'
2115 ],
2116 'value 1234 a-i' => [
2117 '1234',
2118 [
2119 'bytes.' => [
2120 'labels' => 'a|b|c|d|e|f|g|h|i',
2121 'base' => 1000,
2122 ],
2123 ],
2124 '1.23b',
2125 'en_US.UTF-8'
2126 ],
2127 'value 1234 a-i invalid base' => [
2128 '1234',
2129 [
2130 'bytes.' => [
2131 'labels' => 'a|b|c|d|e|f|g|h|i',
2132 'base' => 54,
2133 ],
2134 ],
2135 '1.21b',
2136 'en_US.UTF-8'
2137 ],
2138 'value 1234567890 default' => [
2139 '1234567890',
2140 [
2141 'bytes.' => [
2142 'labels' => '',
2143 'base' => 0,
2144 ],
2145 ],
2146 '1.15 Gi',
2147 'en_US.UTF-8'
2148 ],
2149 ];
2150 }
2151
2152 /**
2153 * @param string|NULL $content
2154 * @param array $configuration
2155 * @param string $expected
2156 * @dataProvider stdWrap_bytesDataProvider
2157 * @test
2158 */
2159 public function stdWrap_bytes($content, array $configuration, $expected, $locale)
2160 {
2161 if (!setlocale(LC_NUMERIC, $locale)) {
2162 $this->markTestSkipped('Locale ' . $locale . ' is not available.');
2163 }
2164 $result = $this->subject->stdWrap_bytes($content, $configuration);
2165 $this->assertSame($expected, $result);
2166 }
2167
2168 /**
2169 * Data provider for stdWrap_substring test
2170 *
2171 * @return array
2172 */
2173 public function stdWrap_substringDataProvider()
2174 {
2175 return [
2176 'sub -1' => [
2177 'substring',
2178 [
2179 'substring' => '-1',
2180 ],
2181 'g',
2182 ],
2183 'sub -1,0' => [
2184 'substring',
2185 [
2186 'substring' => '-1,0',
2187 ],
2188 'g',
2189 ],
2190 'sub -1,-1' => [
2191 'substring',
2192 [
2193 'substring' => '-1,-1',
2194 ],
2195 '',
2196 ],
2197 'sub -1,1' => [
2198 'substring',
2199 [
2200 'substring' => '-1,1',
2201 ],
2202 'g',
2203 ],
2204 'sub 0' => [
2205 'substring',
2206 [
2207 'substring' => '0',
2208 ],
2209 'substring',
2210 ],
2211 'sub 0,0' => [
2212 'substring',
2213 [
2214 'substring' => '0,0',
2215 ],
2216 'substring',
2217 ],
2218 'sub 0,-1' => [
2219 'substring',
2220 [
2221 'substring' => '0,-1',
2222 ],
2223 'substrin',
2224 ],
2225 'sub 0,1' => [
2226 'substring',
2227 [
2228 'substring' => '0,1',
2229 ],
2230 's',
2231 ],
2232 'sub 1' => [
2233 'substring',
2234 [
2235 'substring' => '1',
2236 ],
2237 'ubstring',
2238 ],
2239 'sub 1,0' => [
2240 'substring',
2241 [
2242 'substring' => '1,0',
2243 ],
2244 'ubstring',
2245 ],
2246 'sub 1,-1' => [
2247 'substring',
2248 [
2249 'substring' => '1,-1',
2250 ],
2251 'ubstrin',
2252 ],
2253 'sub 1,1' => [
2254 'substring',
2255 [
2256 'substring' => '1,1',
2257 ],
2258 'u',
2259 ],
2260 'sub' => [
2261 'substring',
2262 [
2263 'substring' => '',
2264 ],
2265 'substring',
2266 ],
2267 ];
2268 }
2269
2270 /**
2271 * @param string $content
2272 * @param array $configuration
2273 * @param string $expected
2274 * @dataProvider stdWrap_substringDataProvider
2275 * @test
2276 */
2277 public function stdWrap_substring($content, array $configuration, $expected)
2278 {
2279 $result = $this->subject->stdWrap_substring($content, $configuration);
2280 $this->assertSame($expected, $result);
2281 }
2282
2283 /**
2284 * Data provider for stdWrap_stdWrapValue test
2285 *
2286 * @return array
2287 */
2288 public function stdWrap_stdWrapValueDataProvider()
2289 {
2290 return [
2291 'only key returns value' => [
2292 'ifNull',
2293 [
2294 'ifNull' => '1',
2295 ],
2296 '',
2297 '1',
2298 ],
2299 'array without key returns empty string' => [
2300 'ifNull',
2301 [
2302 'ifNull.' => '1',
2303 ],
2304 '',
2305 '',
2306 ],
2307 'array without key returns default' => [
2308 'ifNull',
2309 [
2310 'ifNull.' => '1',
2311 ],
2312 'default',
2313 'default',
2314 ],
2315 'non existing key returns default' => [
2316 'ifNull',
2317 [
2318 'noTrimWrap' => 'test',
2319 'noTrimWrap.' => '1',
2320 ],
2321 'default',
2322 'default',
2323 ],
2324 'existing key and array returns stdWrap' => [
2325 'test',
2326 [
2327 'test' => 'value',
2328 'test.' => ['case' => 'upper'],
2329 ],
2330 'default',
2331 'VALUE'
2332 ],
2333 ];
2334 }
2335
2336 /**
2337 * @param string $key
2338 * @param array $configuration
2339 * @param string $defaultValue
2340 * @param string $expected
2341 * @dataProvider stdWrap_stdWrapValueDataProvider
2342 * @test
2343 */
2344 public function stdWrap_stdWrapValue($key, array $configuration, $defaultValue, $expected)
2345 {
2346 $result = $this->subject->stdWrapValue($key, $configuration, $defaultValue);
2347 $this->assertEquals($expected, $result);
2348 }
2349
2350 /**
2351 * @param string|NULL $content
2352 * @param array $configuration
2353 * @param string $expected
2354 * @dataProvider stdWrap_ifNullDeterminesNullValuesDataProvider
2355 * @test
2356 */
2357 public function stdWrap_ifNullDeterminesNullValues($content, array $configuration, $expected)
2358 {
2359 $result = $this->subject->stdWrap_ifNull($content, $configuration);
2360 $this->assertEquals($expected, $result);
2361 }
2362
2363 /**
2364 * Data provider for stdWrap_ifNullDeterminesNullValues test
2365 *
2366 * @return array
2367 */
2368 public function stdWrap_ifNullDeterminesNullValuesDataProvider()
2369 {
2370 return [
2371 'null value' => [
2372 null,
2373 [
2374 'ifNull' => '1',
2375 ],
2376 '1',
2377 ],
2378 'zero value' => [
2379 '0',
2380 [
2381 'ifNull' => '1',
2382 ],
2383 '0',
2384 ],
2385 ];
2386 }
2387
2388 /**
2389 * Data provider for stdWrap_ifEmptyDeterminesEmptyValues test
2390 *
2391 * @return array
2392 */
2393 public function stdWrap_ifEmptyDeterminesEmptyValuesDataProvider()
2394 {
2395 return [
2396 'null value' => [
2397 null,
2398 [
2399 'ifEmpty' => '1',
2400 ],
2401 '1',
2402 ],
2403 'empty value' => [
2404 '',
2405 [
2406 'ifEmpty' => '1',
2407 ],
2408 '1',
2409 ],
2410 'string value' => [
2411 'string',
2412 [
2413 'ifEmpty' => '1',
2414 ],
2415 'string',
2416 ],
2417 'empty string value' => [
2418 ' ',
2419 [
2420 'ifEmpty' => '1',
2421 ],
2422 '1',
2423 ],
2424 ];
2425 }
2426
2427 /**
2428 * @param string|NULL $content
2429 * @param array $configuration
2430 * @param string $expected
2431 * @dataProvider stdWrap_ifEmptyDeterminesEmptyValuesDataProvider
2432 * @test
2433 */
2434 public function stdWrap_ifEmptyDeterminesEmptyValues($content, array $configuration, $expected)
2435 {
2436 $result = $this->subject->stdWrap_ifEmpty($content, $configuration);
2437 $this->assertEquals($expected, $result);
2438 }
2439
2440 /**
2441 * @param $content
2442 * @param array $configuration
2443 * @param $expected
2444 * @dataProvider stdWrap_noTrimWrapAcceptsSplitCharDataProvider
2445 * @test
2446 */
2447 public function stdWrap_noTrimWrapAcceptsSplitChar($content, array $configuration, $expected)
2448 {
2449 $result = $this->subject->stdWrap_noTrimWrap($content, $configuration);
2450 $this->assertEquals($expected, $result);
2451 }
2452
2453 /**
2454 * Data provider for stdWrap_noTrimWrapAcceptsSplitChar test
2455 *
2456 * @return array
2457 */
2458 public function stdWrap_noTrimWrapAcceptsSplitCharDataProvider()
2459 {
2460 return [
2461 'No char given' => [
2462 'middle',
2463 [
2464 'noTrimWrap' => '| left | right |',
2465 ],
2466 ' left middle right '
2467 ],
2468 'Zero char given' => [
2469 'middle',
2470 [
2471 'noTrimWrap' => '0 left 0 right 0',
2472 'noTrimWrap.' => ['splitChar' => '0'],
2473
2474 ],
2475 ' left middle right '
2476 ],
2477 'Default char given' => [
2478 'middle',
2479 [
2480 'noTrimWrap' => '| left | right |',
2481 'noTrimWrap.' => ['splitChar' => '|'],
2482 ],
2483 ' left middle right '
2484 ],
2485 'Split char is a' => [
2486 'middle',
2487 [
2488 'noTrimWrap' => 'a left a right a',
2489 'noTrimWrap.' => ['splitChar' => 'a'],
2490 ],
2491 ' left middle right '
2492 ],
2493 'Split char is multi-char (ab)' => [
2494 'middle',
2495 [
2496 'noTrimWrap' => 'ab left ab right ab',
2497 'noTrimWrap.' => ['splitChar' => 'ab'],
2498 ],
2499 ' left middle right '
2500 ],
2501 'Split char accepts stdWrap' => [
2502 'middle',
2503 [
2504 'noTrimWrap' => 'abc left abc right abc',
2505 'noTrimWrap.' => [
2506 'splitChar' => 'b',
2507 'splitChar.' => ['wrap' => 'a|c'],
2508 ],
2509 ],
2510 ' left middle right '
2511 ],
2512 ];
2513 }
2514
2515 /**
2516 * @param array $expectedTags
2517 * @param array $configuration
2518 * @test
2519 * @dataProvider stdWrap_addPageCacheTagsAddsPageTagsDataProvider
2520 */
2521 public function stdWrap_addPageCacheTagsAddsPageTags(array $expectedTags, array $configuration)
2522 {
2523 $this->subject->stdWrap_addPageCacheTags('', $configuration);
2524 $this->assertEquals($expectedTags, $this->typoScriptFrontendControllerMock->_get('pageCacheTags'));
2525 }
2526
2527 /**
2528 * @return array
2529 */
2530 public function stdWrap_addPageCacheTagsAddsPageTagsDataProvider()
2531 {
2532 return [
2533 'No Tag' => [
2534 [],
2535 ['addPageCacheTags' => ''],
2536 ],
2537 'Two expectedTags' => [
2538 ['tag1', 'tag2'],
2539 ['addPageCacheTags' => 'tag1,tag2'],
2540 ],
2541 'Two expectedTags plus one with stdWrap' => [
2542 ['tag1', 'tag2', 'tag3'],
2543 [
2544 'addPageCacheTags' => 'tag1,tag2',
2545 'addPageCacheTags.' => ['wrap' => '|,tag3']
2546 ],
2547 ],
2548 ];
2549 }
2550
2551 /**
2552 * Data provider for stdWrap_encodeForJavaScriptValue test
2553 *
2554 * @return array multi-dimensional array with the second level like this:
2555 * @see encodeForJavaScriptValue
2556 */
2557 public function stdWrap_encodeForJavaScriptValueDataProvider()
2558 {
2559 return [
2560 'double quote in string' => [
2561 'double quote"',
2562 [],
2563 '\'double\u0020quote\u0022\''
2564 ],
2565 'backslash in string' => [
2566 'backslash \\',
2567 [],
2568 '\'backslash\u0020\u005C\''
2569 ],
2570 'exclamation mark' => [
2571 'exclamation!',
2572 [],
2573 '\'exclamation\u0021\''
2574 ],
2575 'whitespace tab, newline and carriage return' => [
2576 "white\tspace\ns\r",
2577 [],
2578 '\'white\u0009space\u000As\u000D\''
2579 ],
2580 'single quote in string' => [
2581 'single quote \'',
2582 [],
2583 '\'single\u0020quote\u0020\u0027\''
2584 ],
2585 'tag' => [
2586 '<tag>',
2587 [],
2588 '\'\u003Ctag\u003E\''
2589 ],
2590 'ampersand in string' => [
2591 'amper&sand',
2592 [],
2593 '\'amper\u0026sand\''
2594 ],
2595 ];
2596 }
2597
2598 /**
2599 * Check if encodeForJavaScriptValue works properly
2600 *
2601 * @dataProvider stdWrap_encodeForJavaScriptValueDataProvider
2602 * @test
2603 */
2604 public function stdWrap_encodeForJavaScriptValue($input, $conf, $expected)
2605 {
2606 $result = $this->subject->stdWrap_encodeForJavaScriptValue($input, $conf);
2607 $this->assertEquals($expected, $result);
2608 }
2609
2610 ///////////////////////////////
2611 // Tests concerning getData()
2612 ///////////////////////////////
2613
2614 /**
2615 * @return array
2616 */
2617 public function getDataWithTypeGpDataProvider()
2618 {
2619 return [
2620 'Value in get-data' => ['onlyInGet', 'GetValue'],
2621 'Value in post-data' => ['onlyInPost', 'PostValue'],
2622 'Value in post-data overriding get-data' => ['inGetAndPost', 'ValueInPost'],
2623 ];
2624 }
2625
2626 /**
2627 * Checks if getData() works with type "gp"
2628 *
2629 * @test
2630 * @dataProvider getDataWithTypeGpDataProvider
2631 */
2632 public function getDataWithTypeGp($key, $expectedValue)
2633 {
2634 $_GET = [
2635 'onlyInGet' => 'GetValue',
2636 'inGetAndPost' => 'ValueInGet',
2637 ];
2638 $_POST = [
2639 'onlyInPost' => 'PostValue',
2640 'inGetAndPost' => 'ValueInPost',
2641 ];
2642 $this->assertEquals($expectedValue, $this->subject->getData('gp:' . $key));
2643 }
2644
2645 /**
2646 * Checks if getData() works with type "tsfe"
2647 *
2648 * @test
2649 */
2650 public function getDataWithTypeTsfe()
2651 {
2652 $this->assertEquals($GLOBALS['TSFE']->renderCharset, $this->subject->getData('tsfe:renderCharset'));
2653 }
2654
2655 /**
2656 * Checks if getData() works with type "getenv"
2657 *
2658 * @test
2659 */
2660 public function getDataWithTypeGetenv()
2661 {
2662 $envName = $this->getUniqueId('frontendtest');
2663 $value = $this->getUniqueId('someValue');
2664 putenv($envName . '=' . $value);
2665 $this->assertEquals($value, $this->subject->getData('getenv:' . $envName));
2666 }
2667
2668 /**
2669 * Checks if getData() works with type "getindpenv"
2670 *
2671 * @test
2672 */
2673 public function getDataWithTypeGetindpenv()
2674 {
2675 $this->subject->expects($this->once())->method('getEnvironmentVariable')
2676 ->with($this->equalTo('SCRIPT_FILENAME'))->will($this->returnValue('dummyPath'));
2677 $this->assertEquals('dummyPath', $this->subject->getData('getindpenv:SCRIPT_FILENAME'));
2678 }
2679
2680 /**
2681 * Checks if getData() works with type "field"
2682 *
2683 * @test
2684 */
2685 public function getDataWithTypeField()
2686 {
2687 $key = 'someKey';
2688 $value = 'someValue';
2689 $field = [$key => $value];
2690
2691 $this->assertEquals($value, $this->subject->getData('field:' . $key, $field));
2692 }
2693
2694 /**
2695 * Checks if getData() works with type "field" of the field content
2696 * is multi-dimensional (e.g. an array)
2697 *
2698 * @test
2699 */
2700 public function getDataWithTypeFieldAndFieldIsMultiDimensional()
2701 {
2702 $key = 'somekey|level1|level2';
2703 $value = 'somevalue';
2704 $field = ['somekey' => ['level1' => ['level2' => 'somevalue']]];
2705
2706 $this->assertEquals($value, $this->subject->getData('field:' . $key, $field));
2707 }
2708
2709 /**
2710 * Basic check if getData gets the uid of a file object
2711 *
2712 * @test
2713 */
2714 public function getDataWithTypeFileReturnsUidOfFileObject()
2715 {
2716 $uid = $this->getUniqueId();
2717 $file = $this->getMock(\TYPO3\CMS\Core\Resource\File::class, [], [], '', false);
2718 $file->expects($this->once())->method('getUid')->will($this->returnValue($uid));
2719 $this->subject->setCurrentFile($file);
2720 $this->assertEquals($uid, $this->subject->getData('file:current:uid'));
2721 }
2722
2723 /**
2724 * Checks if getData() works with type "parameters"
2725 *
2726 * @test
2727 */
2728 public function getDataWithTypeParameters()
2729 {
2730 $key = $this->getUniqueId('someKey');
2731 $value = $this->getUniqueId('someValue');
2732 $this->subject->parameters[$key] = $value;
2733
2734 $this->assertEquals($value, $this->subject->getData('parameters:' . $key));
2735 }
2736
2737 /**
2738 * Checks if getData() works with type "register"
2739 *
2740 * @test
2741 */
2742 public function getDataWithTypeRegister()
2743 {
2744 $key = $this->getUniqueId('someKey');
2745 $value = $this->getUniqueId('someValue');
2746 $GLOBALS['TSFE']->register[$key] = $value;
2747
2748 $this->assertEquals($value, $this->subject->getData('register:' . $key));
2749 }
2750
2751 /**
2752 * Checks if getData() works with type "level"
2753 *
2754 * @test
2755 */
2756 public function getDataWithTypeLevel()
2757 {
2758 $rootline = [
2759 0 => ['uid' => 1, 'title' => 'title1'],
2760 1 => ['uid' => 2, 'title' => 'title2'],
2761 2 => ['uid' => 3, 'title' => 'title3'],
2762 ];
2763
2764 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
2765 $this->assertEquals(2, $this->subject->getData('level'));
2766 }
2767
2768 /**
2769 * Checks if getData() works with type "global"
2770 *
2771 * @test
2772 */
2773 public function getDataWithTypeGlobal()
2774 {
2775 $this->assertEquals($GLOBALS['TSFE']->renderCharset, $this->subject->getData('global:TSFE|renderCharset'));
2776 }
2777
2778 /**
2779 * Checks if getData() works with type "leveltitle"
2780 *
2781 * @test
2782 */
2783 public function getDataWithTypeLeveltitle()
2784 {
2785 $rootline = [
2786 0 => ['uid' => 1, 'title' => 'title1'],
2787 1 => ['uid' => 2, 'title' => 'title2'],
2788 2 => ['uid' => 3, 'title' => ''],
2789 ];
2790
2791 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
2792 $this->assertEquals('', $this->subject->getData('leveltitle:-1'));
2793 // since "title3" is not set, it will slide to "title2"
2794 $this->assertEquals('title2', $this->subject->getData('leveltitle:-1,slide'));
2795 }
2796
2797 /**
2798 * Checks if getData() works with type "levelmedia"
2799 *
2800 * @test
2801 */
2802 public function getDataWithTypeLevelmedia()
2803 {
2804 $rootline = [
2805 0 => ['uid' => 1, 'title' => 'title1', 'media' => 'media1'],
2806 1 => ['uid' => 2, 'title' => 'title2', 'media' => 'media2'],
2807 2 => ['uid' => 3, 'title' => 'title3', 'media' => ''],
2808 ];
2809
2810 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
2811 $this->assertEquals('', $this->subject->getData('levelmedia:-1'));
2812 // since "title3" is not set, it will slide to "title2"
2813 $this->assertEquals('media2', $this->subject->getData('levelmedia:-1,slide'));
2814 }
2815
2816 /**
2817 * Checks if getData() works with type "leveluid"
2818 *
2819 * @test
2820 */
2821 public function getDataWithTypeLeveluid()
2822 {
2823 $rootline = [
2824 0 => ['uid' => 1, 'title' => 'title1'],
2825 1 => ['uid' => 2, 'title' => 'title2'],
2826 2 => ['uid' => 3, 'title' => 'title3'],
2827 ];
2828
2829 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
2830 $this->assertEquals(3, $this->subject->getData('leveluid:-1'));
2831 // every element will have a uid - so adding slide doesn't really make sense, just for completeness
2832 $this->assertEquals(3, $this->subject->getData('leveluid:-1,slide'));
2833 }
2834
2835 /**
2836 * Checks if getData() works with type "levelfield"
2837 *
2838 * @test
2839 */
2840 public function getDataWithTypeLevelfield()
2841 {
2842 $rootline = [
2843 0 => ['uid' => 1, 'title' => 'title1', 'testfield' => 'field1'],
2844 1 => ['uid' => 2, 'title' => 'title2', 'testfield' => 'field2'],
2845 2 => ['uid' => 3, 'title' => 'title3', 'testfield' => ''],
2846 ];
2847
2848 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
2849 $this->assertEquals('', $this->subject->getData('levelfield:-1,testfield'));
2850 $this->assertEquals('field2', $this->subject->getData('levelfield:-1,testfield,slide'));
2851 }
2852
2853 /**
2854 * Checks if getData() works with type "fullrootline"
2855 *
2856 * @test
2857 */
2858 public function getDataWithTypeFullrootline()
2859 {
2860 $rootline1 = [
2861 0 => ['uid' => 1, 'title' => 'title1', 'testfield' => 'field1'],
2862 ];
2863 $rootline2 = [
2864 0 => ['uid' => 1, 'title' => 'title1', 'testfield' => 'field1'],
2865 1 => ['uid' => 2, 'title' => 'title2', 'testfield' => 'field2'],
2866 2 => ['uid' => 3, 'title' => 'title3', 'testfield' => 'field3'],
2867 ];
2868
2869 $GLOBALS['TSFE']->tmpl->rootLine = $rootline1;
2870 $GLOBALS['TSFE']->rootLine = $rootline2;
2871 $this->assertEquals('field2', $this->subject->getData('fullrootline:-1,testfield'));
2872 }
2873
2874 /**
2875 * Checks if getData() works with type "date"
2876 *
2877 * @test
2878 */
2879 public function getDataWithTypeDate()
2880 {
2881 $format = 'Y-M-D';
2882 $defaultFormat = 'd/m Y';
2883
2884 $this->assertEquals(date($format, $GLOBALS['EXEC_TIME']), $this->subject->getData('date:' . $format));
2885 $this->assertEquals(date($defaultFormat, $GLOBALS['EXEC_TIME']), $this->subject->getData('date'));
2886 }
2887
2888 /**
2889 * Checks if getData() works with type "page"
2890 *
2891 * @test
2892 */
2893 public function getDataWithTypePage()
2894 {
2895 $uid = rand();
2896 $GLOBALS['TSFE']->page['uid'] = $uid;
2897 $this->assertEquals($uid, $this->subject->getData('page:uid'));
2898 }
2899
2900 /**
2901 * Checks if getData() works with type "current"
2902 *
2903 * @test
2904 */
2905 public function getDataWithTypeCurrent()
2906 {
2907 $key = $this->getUniqueId('someKey');
2908 $value = $this->getUniqueId('someValue');
2909 $this->subject->data[$key] = $value;
2910 $this->subject->currentValKey = $key;
2911 $this->assertEquals($value, $this->subject->getData('current'));
2912 }
2913
2914 /**
2915 * Checks if getData() works with type "db"
2916 *
2917 * @test
2918 */
2919 public function getDataWithTypeDb()
2920 {
2921 $dummyRecord = ['uid' => 5, 'title' => 'someTitle'];
2922
2923 $GLOBALS['TSFE']->sys_page->expects($this->atLeastOnce())->method('getRawRecord')->with('tt_content', '106')->will($this->returnValue($dummyRecord));
2924 $this->assertEquals($dummyRecord['title'], $this->subject->getData('db:tt_content:106:title'));
2925 }
2926
2927 /**
2928 * Checks if getData() works with type "lll"
2929 *
2930 * @test
2931 */
2932 public function getDataWithTypeLll()
2933 {
2934 $key = $this->getUniqueId('someKey');
2935 $value = $this->getUniqueId('someValue');
2936 $language = $this->getUniqueId('someLanguage');
2937 $GLOBALS['TSFE']->LL_labels_cache[$language]['LLL:' . $key] = $value;
2938 $GLOBALS['TSFE']->lang = $language;
2939
2940 $this->assertEquals($value, $this->subject->getData('lll:' . $key));
2941 }
2942
2943 /**
2944 * Checks if getData() works with type "path"
2945 *
2946 * @test
2947 */
2948 public function getDataWithTypePath()
2949 {
2950 $filenameIn = $this->getUniqueId('someValue');
2951 $filenameOut = $this->getUniqueId('someValue');
2952 $this->templateServiceMock->expects($this->atLeastOnce())->method('getFileName')->with($filenameIn)->will($this->returnValue($filenameOut));
2953 $this->assertEquals($filenameOut, $this->subject->getData('path:' . $filenameIn));
2954 }
2955
2956 /**
2957 * Checks if getData() works with type "parentRecordNumber"
2958 *
2959 * @test
2960 */
2961 public function getDataWithTypeParentRecordNumber()
2962 {
2963 $recordNumber = rand();
2964 $this->subject->parentRecordNumber = $recordNumber;
2965 $this->assertEquals($recordNumber, $this->subject->getData('cobj:parentRecordNumber'));
2966 }
2967
2968 /**
2969 * Checks if getData() works with type "debug:rootLine"
2970 *
2971 * @test
2972 */
2973 public function getDataWithTypeDebugRootline()
2974 {
2975 $rootline = [
2976 0 => ['uid' => 1, 'title' => 'title1'],
2977 1 => ['uid' => 2, 'title' => 'title2'],
2978 2 => ['uid' => 3, 'title' => ''],
2979 ];
2980 $expectedResult = 'array(3items)0=>array(2items)uid=>1(integer)title=>"title1"(6chars)1=>array(2items)uid=>2(integer)title=>"title2"(6chars)2=>array(2items)uid=>3(integer)title=>""(0chars)';
2981 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
2982
2983 DebugUtility::useAnsiColor(false);
2984 $result = $this->subject->getData('debug:rootLine');
2985 $cleanedResult = str_replace("\r", '', $result);
2986 $cleanedResult = str_replace("\n", '', $cleanedResult);
2987 $cleanedResult = str_replace("\t", '', $cleanedResult);
2988 $cleanedResult = str_replace(' ', '', $cleanedResult);
2989
2990 $this->assertEquals($expectedResult, $cleanedResult);
2991 }
2992
2993 /**
2994 * Checks if getData() works with type "debug:fullRootLine"
2995 *
2996 * @test
2997 */
2998 public function getDataWithTypeDebugFullRootline()
2999 {
3000 $rootline = [
3001 0 => ['uid' => 1, 'title' => 'title1'],
3002 1 => ['uid' => 2, 'title' => 'title2'],
3003 2 => ['uid' => 3, 'title' => ''],
3004 ];
3005 $expectedResult = 'array(3items)0=>array(2items)uid=>1(integer)title=>"title1"(6chars)1=>array(2items)uid=>2(integer)title=>"title2"(6chars)2=>array(2items)uid=>3(integer)title=>""(0chars)';
3006 $GLOBALS['TSFE']->rootLine = $rootline;
3007
3008 DebugUtility::useAnsiColor(false);
3009 $result = $this->subject->getData('debug:fullRootLine');
3010 $cleanedResult = str_replace("\r", '', $result);
3011 $cleanedResult = str_replace("\n", '', $cleanedResult);
3012 $cleanedResult = str_replace("\t", '', $cleanedResult);
3013 $cleanedResult = str_replace(' ', '', $cleanedResult);
3014
3015 $this->assertEquals($expectedResult, $cleanedResult);
3016 }
3017
3018 /**
3019 * Checks if getData() works with type "debug:data"
3020 *
3021 * @test
3022 */
3023 public function getDataWithTypeDebugData()
3024 {
3025 $key = $this->getUniqueId('someKey');
3026 $value = $this->getUniqueId('someValue');
3027 $this->subject->data = [$key => $value];
3028
3029 $expectedResult = 'array(1item)' . $key . '=>"' . $value . '"(' . strlen($value) . 'chars)';
3030
3031 DebugUtility::useAnsiColor(false);
3032 $result = $this->subject->getData('debug:data');
3033 $cleanedResult = str_replace("\r", '', $result);
3034 $cleanedResult = str_replace("\n", '', $cleanedResult);
3035 $cleanedResult = str_replace("\t", '', $cleanedResult);
3036 $cleanedResult = str_replace(' ', '', $cleanedResult);
3037
3038 $this->assertEquals($expectedResult, $cleanedResult);
3039 }
3040
3041 /**
3042 * Checks if getData() works with type "debug:register"
3043 *
3044 * @test
3045 */
3046 public function getDataWithTypeDebugRegister()
3047 {
3048 $key = $this->getUniqueId('someKey');
3049 $value = $this->getUniqueId('someValue');
3050 $GLOBALS['TSFE']->register = [$key => $value];
3051
3052 $expectedResult = 'array(1item)' . $key . '=>"' . $value . '"(' . strlen($value) . 'chars)';
3053
3054 DebugUtility::useAnsiColor(false);
3055 $result = $this->subject->getData('debug:register');
3056 $cleanedResult = str_replace("\r", '', $result);
3057 $cleanedResult = str_replace("\n", '', $cleanedResult);
3058 $cleanedResult = str_replace("\t", '', $cleanedResult);
3059 $cleanedResult = str_replace(' ', '', $cleanedResult);
3060
3061 $this->assertEquals($expectedResult, $cleanedResult);
3062 }
3063
3064 /**
3065 * Checks if getData() works with type "data:page"
3066 *
3067 * @test
3068 */
3069 public function getDataWithTypeDebugPage()
3070 {
3071 $uid = rand();
3072 $GLOBALS['TSFE']->page = ['uid' => $uid];
3073
3074 $expectedResult = 'array(1item)uid=>' . $uid . '(integer)';
3075
3076 DebugUtility::useAnsiColor(false);
3077 $result = $this->subject->getData('debug:page');
3078 $cleanedResult = str_replace("\r", '', $result);
3079 $cleanedResult = str_replace("\n", '', $cleanedResult);
3080 $cleanedResult = str_replace("\t", '', $cleanedResult);
3081 $cleanedResult = str_replace(' ', '', $cleanedResult);
3082
3083 $this->assertEquals($expectedResult, $cleanedResult);
3084 }
3085
3086 /**
3087 * @test
3088 */
3089 public function getTreeListReturnsChildPageUids()
3090 {
3091 $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetSingleRow')->with('treelist')->will($this->returnValue(null));
3092 $GLOBALS['TSFE']->sys_page
3093 ->expects($this->any())
3094 ->method('getRawRecord')
3095 ->will(
3096 $this->onConsecutiveCalls(
3097 ['uid' => 17],
3098 ['uid' => 321],
3099 ['uid' => 719],
3100 ['uid' => 42]
3101 )
3102 );
3103
3104 $GLOBALS['TSFE']->sys_page->expects($this->any())->method('getMountPointInfo')->will($this->returnValue(null));
3105 $GLOBALS['TYPO3_DB']
3106 ->expects($this->any())
3107 ->method('exec_SELECTgetRows')
3108 ->will(
3109 $this->onConsecutiveCalls(
3110 [
3111 ['uid' => 321]
3112 ],
3113 [
3114 ['uid' => 719]
3115 ],
3116 [
3117 ['uid' => 42]
3118 ]
3119 )
3120 );
3121 // 17 = pageId, 5 = recursionLevel, 0 = begin (entry to recursion, internal), TRUE = do not check enable fields
3122 // 17 is positive, we expect 17 NOT to be included in result
3123 $result = $this->subject->getTreeList(17, 5, 0, true);
3124 $expectedResult = '42,719,321';
3125 $this->assertEquals($expectedResult, $result);
3126 }
3127