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