TYPO3 CMS  TYPO3_7-6
ContentObjectRendererTest.php
Go to the documentation of this file.
1 <?php
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 
31 
36 {
40  protected $currentLocale;
41 
45  protected $singletonInstances = [];
46 
50  protected $subject = null;
51 
56 
60  protected $templateServiceMock = null;
61 
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 
94  protected function setUp()
95  {
96  $this->currentLocale = setlocale(LC_NUMERIC, 0);
97 
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';
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 
133  // Utility functions
135 
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 
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 
164  // Tests concerning the getImgResource hook
166 
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 
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 
208  // Tests related to getContentObject
210 
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 
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 
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 
275  {
276  $object = $this->subject->getContentObject('FOO');
277  $this->assertNull($object);
278  }
279 
286  {
287  $this->subject->registerContentObjectClass(\stdClass::class,
288  'STDCLASS');
289  $this->subject->getContentObject('STDCLASS');
290  }
291 
296  {
297  $dataProvider = [];
298  foreach ($this->contentObjectMap as $name => $className) {
299  $dataProvider[] = [$name, $className];
300  }
301  return $dataProvider;
302  }
303 
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 
324  // Tests concerning getQueryArguments()
326 
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 
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 
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 
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 
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 
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 
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 
553  private function rawUrlEncodeSquareBracketsInUrl($string)
554  {
555  return str_replace(['[', ']'], ['%5B', '%5D'], $string);
556  }
557 
559  // Tests concerning crop
561 
564  public function cropIsMultibyteSafe()
565  {
566  $this->assertEquals('бла', $this->subject->crop('бла', '3|...'));
567  }
568 
570  // Tests concerning cropHTML
572 
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 
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 
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 
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 
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 
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 
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 
1118  public function stdWrap_numberFormat($float, $conf, $expected)
1119  {
1120  $result = $this->subject->stdWrap_numberFormat($float, $conf);
1121  $this->assertEquals($expected, $result);
1122  }
1123 
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 
1154  public function stdWrap_expandList($content, $expected)
1155  {
1156  $result = $this->subject->stdWrap_expandList($content);
1157  $this->assertEquals($expected, $result);
1158  }
1159 
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 
1190  public function stdWrap_trim($content, $expected)
1191  {
1192  $result = $this->subject->stdWrap_trim($content);
1193  $this->assertEquals($expected, $result);
1194  }
1195 
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 
1246  public function stdWrap_intval($content, $expected)
1247  {
1248  $result = $this->subject->stdWrap_intval($content);
1249  $this->assertEquals($expected, $result);
1250  }
1251 
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 
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 
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 
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 
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 
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 
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 
1534  public function numberFormat($float, $formatConf, $expected)
1535  {
1536  $result = $this->subject->numberFormat($float, $formatConf);
1537  $this->assertEquals($expected, $result);
1538  }
1539 
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 
1607  public function replacement($input, $conf, $expected)
1608  {
1609  $result = $this->subject->stdWrap_replacement($input, $conf);
1610  $this->assertEquals($expected, $result);
1611  }
1612 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
2088  public function calcAgeCalculatesAgeOfTimestamp($timestamp, $labels, $expectation)
2089  {
2090  $result = $this->subject->calcAge($timestamp, $labels);
2091  $this->assertEquals($result, $expectation);
2092  }
2093 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
2696  public function stdWrap_encodeForJavaScriptValue($input, $conf, $expected)
2697  {
2698  $result = $this->subject->stdWrap_encodeForJavaScriptValue($input, $conf);
2699  $this->assertEquals($expected, $result);
2700  }
2701 
2703  // Tests concerning getData()
2705 
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 
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 
2742  public function getDataWithTypeTsfe()
2743  {
2744  $this->assertEquals($GLOBALS['TSFE']->renderCharset, $this->subject->getData('tsfe:renderCharset'));
2745  }
2746 
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 
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 
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 
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 
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 
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 
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 
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 
2865  public function getDataWithTypeGlobal()
2866  {
2867  $this->assertEquals($GLOBALS['TSFE']->renderCharset, $this->subject->getData('global:TSFE|renderCharset'));
2868  }
2869 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
3054  {
3055  $recordNumber = rand();
3056  $this->subject->parentRecordNumber = $recordNumber;
3057  $this->assertEquals($recordNumber, $this->subject->getData('cobj:parentRecordNumber'));
3058  }
3059 
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 
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 
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 
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 
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 
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 
3139  {
3140  $key = $this->getUniqueId('someKey');
3141  $value = $this->getUniqueId('someValue');
3142  $GLOBALS['TSFE']->register = [$key => $value];
3143 
3144  $expectedResult = 'array(1item)' . $key . '=>"' . $value . '"(' . strlen($value) . 'chars)';
3145 
3147  $result = $this->subject->getData('debug:register');
3148  $cleanedResult = str_replace("\r", '', $result);
3149  $cleanedResult = str_replace("\n", '', $cleanedResult);
3150  $cleanedResult = str_replace("\t", '', $cleanedResult);
3151  $cleanedResult = str_replace(' ', '', $cleanedResult);
3152 
3153  $this->assertEquals($expectedResult, $cleanedResult);
3154  }
3155 
3161  public function getDataWithTypeDebugPage()
3162  {
3163  $uid = rand();
3164  $GLOBALS['TSFE']->page = ['uid' => $uid];
3165 
3166  $expectedResult = 'array(1item)uid=>' . $uid . '(integer)';
3167 
3169  $result = $this->subject->getData('debug:page');
3170  $cleanedResult = str_replace("\r", '', $result);
3171  $cleanedResult = str_replace("\n", '', $cleanedResult);
3172  $cleanedResult = str_replace("\t", '', $cleanedResult);
3173  $cleanedResult = str_replace(' ', '', $cleanedResult);
3174 
3175  $this->assertEquals($expectedResult, $cleanedResult);
3176  }
3177 
3182  {
3183  $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetSingleRow')->with('treelist')->will($this->returnValue(null));
3184  $GLOBALS['TSFE']->sys_page
3185  ->expects($this->any())
3186  ->method('getRawRecord')
3187  ->will(
3188  $this->onConsecutiveCalls(
3189  ['uid' => 17],
3190  ['uid' => 321],
3191  ['uid' => 719],
3192  ['uid' => 42]
3193  )
3194  );
3195 
3196  $GLOBALS['TSFE']->sys_page->expects($this->any())->method('getMountPointInfo')->will($this->returnValue(null));
3197  $GLOBALS['TYPO3_DB']
3198  ->expects($this->any())
3199  ->method('exec_SELECTgetRows')
3200  ->will(
3201  $this->onConsecutiveCalls(
3202  [
3203  ['uid' => 321]
3204  ],
3205  [
3206  ['uid' => 719]
3207  ],
3208  [
3209  ['uid' => 42]
3210  ]
3211  )
3212  );
3213  // 17 = pageId, 5 = recursionLevel, 0 = begin (entry to recursion, internal), TRUE = do not check enable fields
3214  // 17 is positive, we expect 17 NOT to be included in result
3215  $result = $this->subject->getTreeList(17, 5, 0, true);
3216  $expectedResult = '42,719,321';
3217  $this->assertEquals($expectedResult, $result);
3218  }
3219 
3224  {
3225  $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetSingleRow')->with('treelist')->will($this->returnValue(null));
3226  $GLOBALS['TSFE']->sys_page
3227  ->expects($this->any())
3228  ->method('getRawRecord')
3229  ->will(
3230  $this->onConsecutiveCalls(
3231  ['uid' => 17],
3232  ['uid' => 321],
3233  ['uid' => 719],
3234  ['uid' => 42]
3235  )
3236  );
3237 
3238  $GLOBALS['TSFE']->sys_page->expects($this->any())->method('getMountPointInfo')->will($this->returnValue(null));
3239  $GLOBALS['TYPO3_DB']
3240  ->expects($this->any())
3241  ->method('exec_SELECTgetRows')
3242  ->will(
3243  $this->onConsecutiveCalls(
3244  [
3245  ['uid' => 321]
3246  ],
3247  [
3248  ['uid' => 719]
3249  ],
3250  [
3251  ['uid' => 42]
3252  ]
3253  )
3254  );
3255  // 17 = pageId, 5 = recursionLevel, 0 = begin (entry to recursion, internal), TRUE = do not check enable fields
3256  // 17 is negative, we expect 17 to be included in result
3257  $result = $this->subject->getTreeList(-17, 5, 0, true);
3258  $expectedResult = '42,719,321,17';
3259  $this->assertEquals($expectedResult, $result);
3260  }
3261 
3266  {
3267  $aTagParams = $this->subject->getATagParams(['ATagParams' => 'data-test="testdata"']);
3268  $this->assertEquals(' data-test="testdata"', $aTagParams);
3269  }
3270 
3275  {
3276  $GLOBALS['TSFE']->ATagParams = 'data-global="dataglobal"';
3277  $aTagParams = $this->subject->getATagParams(['ATagParams' => 'data-test="testdata"']);
3278  $this->assertEquals(' data-global="dataglobal" data-test="testdata"', $aTagParams);
3279  }
3280 
3285  {
3286  // make sure global ATagParams are empty
3287  $GLOBALS['TSFE']->ATagParams = '';
3288  $aTagParams = $this->subject->getATagParams(['ATagParams' => '']);
3289  $this->assertEquals('', $aTagParams);
3290  }
3291 
3296  {
3297  return [
3298  [null, null],
3299  ['', null],
3300  ['', []],
3301  ['fooo', ['foo' => 'bar']]
3302  ];
3303  }
3304 
3314  {
3315  $defaultImgTagTemplate = '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>';
3316  $result = $this->subject->getImageTagTemplate($key, $configuration);
3317  $this->assertEquals($result, $defaultImgTagTemplate);
3318  }
3319 
3324  {
3325  return [
3326  [
3327  'foo',
3328  [
3329  'layout.' => [
3330  'foo.' => [
3331  'element' => '<img src="###SRC###" srcset="###SOURCES###" ###PARAMS### ###ALTPARAMS### ###FOOBAR######SELFCLOSINGTAGSLASH###>'
3332  ]
3333  ]
3334  ],
3335  '<img src="###SRC###" srcset="###SOURCES###" ###PARAMS### ###ALTPARAMS### ###FOOBAR######SELFCLOSINGTAGSLASH###>'
3336  ]
3337 
3338  ];
3339  }
3340 
3350  public function getImageTagTemplateReturnTemplateElementIdentifiedByKey($key, $configuration, $expectation)
3351  {
3352  $result = $this->subject->getImageTagTemplate($key, $configuration);
3353  $this->assertEquals($result, $expectation);
3354  }
3355 
3360  {
3361  return [
3362  [null, null, null],
3363  ['foo', null, null],
3364  ['foo', ['sourceCollection.' => 1], 'bar']
3365  ];
3366  }
3367 
3377  public function getImageSourceCollectionReturnsEmptyStringIfNoSourcesAreDefined($layoutKey, $configuration, $file)
3378  {
3379  $result = $this->subject->getImageSourceCollection($layoutKey, $configuration, $file);
3380  $this->assertSame($result, '');
3381  }
3382 
3388  public function getImageSourceCollectionRendersDefinedSources()
3389  {
3391  $cObj = $this->getMock(
3392  \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
3393  ['stdWrap', 'getImgResource']
3394  );
3395  $cObj->start([], 'tt_content');
3396 
3397  $layoutKey = 'test';
3398 
3399  $configuration = [
3400  'layoutKey' => 'test',
3401  'layout.' => [
3402  'test.' => [
3403  'element' => '<img ###SRC### ###SRCCOLLECTION### ###SELFCLOSINGTAGSLASH###>',
3404  'source' => '---###SRC###---'
3405  ]
3406  ],
3407  'sourceCollection.' => [
3408  '1.' => [
3409  'width' => '200'
3410  ]
3411  ]
3412  ];
3413 
3414  $file = 'testImageName';
3415 
3416  // Avoid calling of stdWrap
3417  $cObj
3418  ->expects($this->any())
3419  ->method('stdWrap')
3420  ->will($this->returnArgument(0));
3421 
3422  // Avoid calling of imgResource
3423  $cObj
3424  ->expects($this->exactly(1))
3425  ->method('getImgResource')
3426  ->with($this->equalTo('testImageName'))
3427  ->will($this->returnValue([100, 100, null, 'bar']));
3428 
3429  $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
3430 
3431  $this->assertEquals('---bar---', $result);
3432  }
3433 
3441  {
3445  $sourceCollectionArray = [
3446  'small.' => [
3447  'width' => '200',
3448  'srcsetCandidate' => '600w',
3449  'mediaQuery' => '(max-device-width: 600px)',
3450  'dataKey' => 'small',
3451  ],
3452  'smallRetina.' => [
3453  'if.directReturn' => 0,
3454  'width' => '200',
3455  'pixelDensity' => '2',
3456  'srcsetCandidate' => '600w 2x',
3457  'mediaQuery' => '(max-device-width: 600px) AND (min-resolution: 192dpi)',
3458  'dataKey' => 'smallRetina',
3459  ]
3460  ];
3461  return [
3462  [
3463  'default',
3464  [
3465  'layoutKey' => 'default',
3466  'layout.' => [
3467  'default.' => [
3468  'element' => '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>',
3469  'source' => ''
3470  ]
3471  ],
3472  'sourceCollection.' => $sourceCollectionArray
3473  ]
3474  ],
3475  ];
3476  }
3477 
3486  public function getImageSourceCollectionRendersDefinedLayoutKeyDefault($layoutKey, $configuration)
3487  {
3489  $cObj = $this->getMock(
3490  \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
3491  ['stdWrap', 'getImgResource']
3492  );
3493  $cObj->start([], 'tt_content');
3494 
3495  $file = 'testImageName';
3496 
3497  // Avoid calling of stdWrap
3498  $cObj
3499  ->expects($this->any())
3500  ->method('stdWrap')
3501  ->will($this->returnArgument(0));
3502 
3503  $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
3504 
3505  $this->assertEmpty($result);
3506  }
3507 
3515  {
3519  $sourceCollectionArray = [
3520  'small.' => [
3521  'width' => '200',
3522  'srcsetCandidate' => '600w',
3523  'mediaQuery' => '(max-device-width: 600px)',
3524  'dataKey' => 'small',
3525  ],
3526  'smallRetina.' => [
3527  'if.directReturn' => 1,
3528  'width' => '200',
3529  'pixelDensity' => '2',
3530  'srcsetCandidate' => '600w 2x',
3531  'mediaQuery' => '(max-device-width: 600px) AND (min-resolution: 192dpi)',
3532  'dataKey' => 'smallRetina',
3533  ]
3534  ];
3535  return [
3536  [
3537  'srcset',
3538  [
3539  'layoutKey' => 'srcset',
3540  'layout.' => [
3541  'srcset.' => [
3542  'element' => '<img src="###SRC###" srcset="###SOURCECOLLECTION###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
3543  'source' => '|*|###SRC### ###SRCSETCANDIDATE###,|*|###SRC### ###SRCSETCANDIDATE###'
3544  ]
3545  ],
3546  'sourceCollection.' => $sourceCollectionArray
3547  ],
3548  'xhtml_strict',
3549  'bar-file.jpg 600w,bar-file.jpg 600w 2x',
3550  ],
3551  [
3552  'picture',
3553  [
3554  'layoutKey' => 'picture',
3555  'layout.' => [
3556  'picture.' => [
3557  'element' => '<picture>###SOURCECOLLECTION###<img src="###SRC###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###></picture>',
3558  'source' => '<source src="###SRC###" media="###MEDIAQUERY###"###SELFCLOSINGTAGSLASH###>'
3559  ]
3560  ],
3561  'sourceCollection.' => $sourceCollectionArray,
3562  ],
3563  'xhtml_strict',
3564  '<source src="bar-file.jpg" media="(max-device-width: 600px)" /><source src="bar-file.jpg" media="(max-device-width: 600px) AND (min-resolution: 192dpi)" />',
3565  ],
3566  [
3567  'picture',
3568  [
3569  'layoutKey' => 'picture',
3570  'layout.' => [
3571  'picture.' => [
3572  'element' => '<picture>###SOURCECOLLECTION###<img src="###SRC###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###></picture>',
3573  'source' => '<source src="###SRC###" media="###MEDIAQUERY###"###SELFCLOSINGTAGSLASH###>'
3574  ]
3575  ],
3576  'sourceCollection.' => $sourceCollectionArray,
3577  ],
3578  '',
3579  '<source src="bar-file.jpg" media="(max-device-width: 600px)"><source src="bar-file.jpg" media="(max-device-width: 600px) AND (min-resolution: 192dpi)">',
3580  ],
3581  [
3582  'data',
3583  [
3584  'layoutKey' => 'data',
3585  'layout.' => [
3586  'data.' => [
3587  'element' => '<img src="###SRC###" ###SOURCECOLLECTION### ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
3588  'source' => 'data-###DATAKEY###="###SRC###"'
3589  ]
3590  ],
3591  'sourceCollection.' => $sourceCollectionArray
3592  ],
3593  'xhtml_strict',
3594  'data-small="bar-file.jpg"data-smallRetina="bar-file.jpg"',
3595  ],
3596  ];
3597  }
3598 
3609  public function getImageSourceCollectionRendersDefinedLayoutKeyData($layoutKey, $configuration, $xhtmlDoctype, $expectedHtml)
3610  {
3612  $cObj = $this->getMock(
3613  \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
3614  ['stdWrap', 'getImgResource']
3615  );
3616  $cObj->start([], 'tt_content');
3617 
3618  $file = 'testImageName';
3619 
3620  $GLOBALS['TSFE']->xhtmlDoctype = $xhtmlDoctype;
3621 
3622  // Avoid calling of stdWrap
3623  $cObj
3624  ->expects($this->any())
3625  ->method('stdWrap')
3626  ->will($this->returnArgument(0));
3627 
3628  // Avoid calling of imgResource
3629  $cObj
3630  ->expects($this->exactly(2))
3631  ->method('getImgResource')
3632  ->with($this->equalTo('testImageName'))
3633  ->will($this->returnValue([100, 100, null, 'bar-file.jpg']));
3634 
3635  $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
3636 
3637  $this->assertEquals($expectedHtml, $result);
3638  }
3639 
3646  {
3647  $this->subject = $this->getAccessibleMock(
3648  \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
3649  ['getResourceFactory', 'stdWrap', 'getImgResource']
3650  );
3651  $this->subject->start([], 'tt_content');
3652 
3653  // Avoid calling stdwrap and getImgResource
3654  $this->subject->expects($this->any())
3655  ->method('stdWrap')
3656  ->will($this->returnArgument(0));
3657 
3658  $this->subject->expects($this->any())
3659  ->method('getImgResource')
3660  ->will($this->returnValue([100, 100, null, 'bar-file.jpg']));
3661 
3662  $resourceFactory = $this->getMock(\TYPO3\CMS\Core\Resource\ResourceFactory::class, [], [], '', false);
3663  $this->subject->expects($this->any())->method('getResourceFactory')->will($this->returnValue($resourceFactory));
3664 
3665  $className = $this->getUniqueId('tx_coretest_getImageSourceCollectionHookCalled');
3666  $getImageSourceCollectionHookMock = $this->getMock(\TYPO3\CMS\Frontend\ContentObject\ContentObjectOneSourceCollectionHookInterface::class, ['getOneSourceCollection'], [], $className);
3667  $GLOBALS['T3_VAR']['getUserObj'][$className] = $getImageSourceCollectionHookMock;
3668  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'][] = $className;
3669 
3670  $getImageSourceCollectionHookMock
3671  ->expects($this->exactly(1))
3672  ->method('getOneSourceCollection')
3673  ->will($this->returnCallback([$this, 'isGetOneSourceCollectionCalledCallback']));
3674 
3675  $configuration = [
3676  'layoutKey' => 'data',
3677  'layout.' => [
3678  'data.' => [
3679  'element' => '<img src="###SRC###" ###SOURCECOLLECTION### ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
3680  'source' => 'data-###DATAKEY###="###SRC###"'
3681  ]
3682  ],
3683  'sourceCollection.' => [
3684  'small.' => [
3685  'width' => '200',
3686  'srcsetCandidate' => '600w',
3687  'mediaQuery' => '(max-device-width: 600px)',
3688  'dataKey' => 'small',
3689  ],
3690  ],
3691  ];
3692 
3693  $result = $this->subject->getImageSourceCollection('data', $configuration, $this->getUniqueId('testImage-'));
3694 
3695  $this->assertSame($result, 'isGetOneSourceCollectionCalledCallback');
3696  }
3697 
3705  {
3706  list($sourceRenderConfiguration, $sourceConfiguration, $oneSourceCollection, $parent) = func_get_args();
3707  $this->assertTrue(is_array($sourceRenderConfiguration));
3708  $this->assertTrue(is_array($sourceConfiguration));
3709  return 'isGetOneSourceCollectionCalledCallback';
3710  }
3711 
3719  public function forceAbsoluteUrlReturnsCorrectAbsoluteUrl($expected, $url, array $configuration)
3720  {
3721  // Force hostname
3722  $this->subject->expects($this->any())->method('getEnvironmentVariable')->will($this->returnValueMap(
3723  [
3724  ['HTTP_HOST', 'localhost'],
3725  ['TYPO3_SITE_PATH', '/'],
3726  ]
3727  ));
3728  $GLOBALS['TSFE']->absRefPrefix = '';
3729 
3730  $this->assertEquals($expected, $this->subject->_call('forceAbsoluteUrl', $url, $configuration));
3731  }
3732 
3737  {
3738  return [
3739  'Missing forceAbsoluteUrl leaves URL untouched' => [
3740  'foo',
3741  'foo',
3742  []
3743  ],
3744  'Absolute URL stays unchanged' => [
3745  'http://example.org/',
3746  'http://example.org/',
3747  [
3748  'forceAbsoluteUrl' => '1'
3749  ]
3750  ],
3751  'Absolute URL stays unchanged 2' => [
3752  'http://example.org/resource.html',
3753  'http://example.org/resource.html',
3754  [
3755  'forceAbsoluteUrl' => '1'
3756  ]
3757  ],
3758  'Scheme and host w/o ending slash stays unchanged' => [
3759  'http://example.org',
3760  'http://example.org',
3761  [
3762  'forceAbsoluteUrl' => '1'
3763  ]
3764  ],
3765  'Scheme can be forced' => [
3766  'typo3://example.org',
3767  'http://example.org',
3768  [
3769  'forceAbsoluteUrl' => '1',
3770  'forceAbsoluteUrl.' => [
3771  'scheme' => 'typo3'
3772  ]
3773  ]
3774  ],
3775  'Relative path old-style' => [
3776  'http://localhost/fileadmin/dummy.txt',
3777  '/fileadmin/dummy.txt',
3778  [
3779  'forceAbsoluteUrl' => '1',
3780  ]
3781  ],
3782  'Relative path' => [
3783  'http://localhost/fileadmin/dummy.txt',
3784  'fileadmin/dummy.txt',
3785  [
3786  'forceAbsoluteUrl' => '1',
3787  ]
3788  ],
3789  'Scheme can be forced with pseudo-relative path' => [
3790  'typo3://localhost/fileadmin/dummy.txt',
3791  '/fileadmin/dummy.txt',
3792  [
3793  'forceAbsoluteUrl' => '1',
3794  'forceAbsoluteUrl.' => [
3795  'scheme' => 'typo3'
3796  ]
3797  ]
3798  ],
3799  'Hostname only is not treated as valid absolute URL' => [
3800  'http://localhost/example.org',
3801  'example.org',
3802  [
3803  'forceAbsoluteUrl' => '1'
3804  ]
3805  ],
3806  'Scheme and host is added to local file path' => [
3807  'typo3://localhost/fileadmin/my.pdf',
3808  'fileadmin/my.pdf',
3809  [
3810  'forceAbsoluteUrl' => '1',
3811  'forceAbsoluteUrl.' => [
3812  'scheme' => 'typo3'
3813  ]
3814  ]
3815  ]
3816  ];
3817  }
3818 
3825  {
3826  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
3827  $this->subject->render($contentObjectFixture, []);
3828  }
3829 
3834  {
3835  $backupApplicationContext = GeneralUtility::getApplicationContext();
3837 
3838  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
3839  $this->subject->render($contentObjectFixture, []);
3840 
3841  Fixtures\GeneralUtilityFixture::setApplicationContext($backupApplicationContext);
3842  }
3843 
3848  {
3849  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
3850 
3851  $configuration = [
3852  'exceptionHandler' => '1'
3853  ];
3854  $this->subject->render($contentObjectFixture, $configuration);
3855  }
3856 
3861  {
3862  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
3863 
3864  $this->typoScriptFrontendControllerMock->config['config']['contentObjectExceptionHandler'] = '1';
3865  $this->subject->render($contentObjectFixture, []);
3866  }
3867 
3874  {
3875  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
3876 
3877  $this->typoScriptFrontendControllerMock->config['config']['contentObjectExceptionHandler'] = '1';
3878  $configuration = [
3879  'exceptionHandler' => '0'
3880  ];
3881  $this->subject->render($contentObjectFixture, $configuration);
3882  }
3883 
3888  {
3889  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
3890 
3891  $configuration = [
3892  'exceptionHandler' => '1',
3893  'exceptionHandler.' => [
3894  'errorMessage' => 'New message for testing',
3895  ]
3896  ];
3897 
3898  $this->assertSame('New message for testing', $this->subject->render($contentObjectFixture, $configuration));
3899  }
3900 
3905  {
3906  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
3907 
3908  $this->typoScriptFrontendControllerMock
3909  ->config['config']['contentObjectExceptionHandler.'] = [
3910  'errorMessage' => 'Global message for testing',
3911  ];
3912  $configuration = [
3913  'exceptionHandler' => '1',
3914  'exceptionHandler.' => [
3915  'errorMessage' => 'New message for testing',
3916  ]
3917  ];
3918 
3919  $this->assertSame('New message for testing', $this->subject->render($contentObjectFixture, $configuration));
3920  }
3921 
3928  {
3929  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
3930 
3931  $configuration = [
3932  'exceptionHandler' => '1',
3933  'exceptionHandler.' => [
3934  'ignoreCodes.' => ['10.' => '1414513947'],
3935  ]
3936  ];
3937 
3938  $this->subject->render($contentObjectFixture, $configuration);
3939  }
3940 
3945  {
3946  $contentObjectFixture = $this->getMock(AbstractContentObject::class, [], [$this->subject]);
3947  $contentObjectFixture->expects($this->once())
3948  ->method('render')
3949  ->willReturnCallback(function () {
3950  throw new \LogicException('Exception during rendering', 1414513947);
3951  });
3952  return $contentObjectFixture;
3953  }
3954 
3959  {
3960  // Force hostname and subfolder
3961  $this->subject->expects($this->any())->method('getEnvironmentVariable')->will($this->returnValueMap(
3962  [
3963  ['HTTP_HOST', 'localhost'],
3964  ['TYPO3_SITE_PATH', '/subfolder/'],
3965  ]
3966  ));
3967 
3968  $expected = 'http://localhost/subfolder/fileadmin/my.pdf';
3969  $url = 'fileadmin/my.pdf';
3970  $configuration = [
3971  'forceAbsoluteUrl' => '1'
3972  ];
3973 
3974  $this->assertEquals($expected, $this->subject->_call('forceAbsoluteUrl', $url, $configuration));
3975  }
3976 
3980  protected function getLibParseTarget()
3981  {
3982  return [
3983  'override' => '',
3984  'override.' => [
3985  'if.' => [
3986  'isTrue.' => [
3987  'data' => 'TSFE:dtdAllowsFrames',
3988  ],
3989  ],
3990  ],
3991  ];
3992  }
3993 
3997  protected function getLibParseFunc()
3998  {
3999  return [
4000  'makelinks' => '1',
4001  'makelinks.' => [
4002  'http.' => [
4003  'keep' => '{$styles.content.links.keep}',
4004  'extTarget' => '',
4005  'extTarget.' => $this->getLibParseTarget(),
4006  'mailto.' => [
4007  'keep' => 'path',
4008  ],
4009  ],
4010  ],
4011  'tags' => [
4012  'link' => 'TEXT',
4013  'link.' => [
4014  'current' => '1',
4015  'typolink.' => [
4016  'parameter.' => [
4017  'data' => 'parameters : allParams',
4018  ],
4019  'extTarget.' => $this->getLibParseTarget(),
4020  'target.' => $this->getLibParseTarget(),
4021  ],
4022  'parseFunc.' => [
4023  'constants' => '1',
4024  ],
4025  ],
4026  ],
4027 
4028  'allowTags' => 'a, abbr, acronym, address, article, aside, b, bdo, big, blockquote, br, caption, center, cite, code, col, colgroup, dd, del, dfn, dl, div, dt, em, font, footer, header, h1, h2, h3, h4, h5, h6, hr, i, img, ins, kbd, label, li, link, meta, nav, ol, p, pre, q, samp, sdfield, section, small, span, strike, strong, style, sub, sup, table, thead, tbody, tfoot, td, th, tr, title, tt, u, ul, var',
4029  'denyTags' => '*',
4030  'sword' => '<span class="csc-sword">|</span>',
4031  'constants' => '1',
4032  'nonTypoTagStdWrap.' => [
4033  'HTMLparser' => '1',
4034  'HTMLparser.' => [
4035  'keepNonMatchedTags' => '1',
4036  'htmlSpecialChars' => '2',
4037  ],
4038  ],
4039  ];
4040  }
4041 
4045  protected function getLibParseFunc_RTE()
4046  {
4047  return [
4048  'parseFunc' => '',
4049  'parseFunc.' => [
4050  'allowTags' => 'a, abbr, acronym, address, article, aside, b, bdo, big, blockquote, br, caption, center, cite, code, col, colgroup, dd, del, dfn, dl, div, dt, em, font, footer, header, h1, h2, h3, h4, h5, h6, hr, i, img, ins, kbd, label, li, link, meta, nav, ol, p, pre, q, samp, sdfield, section, small, span, strike, strong, style, sub, sup, table, thead, tbody, tfoot, td, th, tr, title, tt, u, ul, var',
4051  'constants' => '1',
4052  'denyTags' => '*',
4053  'externalBlocks' => 'article, aside, blockquote, div, dd, dl, footer, header, nav, ol, section, table, ul, pre',
4054  'externalBlocks.' => [
4055  'article.' => [
4056  'callRecursive' => '1',
4057  'stripNL' => '1',
4058  ],
4059  'aside.' => [
4060  'callRecursive' => '1',
4061  'stripNL' => '1',
4062  ],
4063  'blockquote.' => [
4064  'callRecursive' => '1',
4065  'stripNL' => '1',
4066  ],
4067  'dd.' => [
4068  'callRecursive' => '1',
4069  'stripNL' => '1',
4070  ],
4071  'div.' => [
4072  'callRecursive' => '1',
4073  'stripNL' => '1',
4074  ],
4075  'dl.' => [
4076  'callRecursive' => '1',
4077  'stripNL' => '1',
4078  ],
4079  'footer.' => [
4080  'callRecursive' => '1',
4081  'stripNL' => '1',
4082  ],
4083  'header.' => [
4084  'callRecursive' => '1',
4085  'stripNL' => '1',
4086  ],
4087  'nav.' => [
4088  'callRecursive' => '1',
4089  'stripNL' => '1',
4090  ],
4091  'ol.' => [
4092  'callRecursive' => '1',
4093  'stripNL' => '1',
4094  ],
4095  'section.' => [
4096  'callRecursive' => '1',
4097  'stripNL' => '1',
4098  ],
4099  'table.' => [
4100  'HTMLtableCells' => '1',
4101  'HTMLtableCells.' => [
4102  'addChr10BetweenParagraphs' => '1',
4103  'default.' => [
4104  'stdWrap.' => [
4105  'parseFunc' => '=< lib.parseFunc_RTE',
4106  'parseFunc.' => [
4107  'nonTypoTagStdWrap.' => [
4108  'encapsLines.' => [
4109  'nonWrappedTag' => '',
4110  ],
4111  ],
4112  ],
4113  ],
4114  ],
4115  ],
4116  'stdWrap.' => [
4117  'HTMLparser' => '1',
4118  'HTMLparser.' => [
4119  'keepNonMatchedTags' => '1',
4120  'tags.' => [
4121  'table.' => [
4122  'fixAttrib.' => [
4123  'class.' => [
4124  'always' => '1',
4125  'default' => 'contenttable',
4126  'list' => 'contenttable',
4127  ],
4128  ],
4129  ],
4130  ],
4131  ],
4132  ],
4133  'stripNL' => '1',
4134  ],
4135  'ul.' => [
4136  'callRecursive' => '1',
4137  'stripNL' => '1',
4138  ],
4139  ],
4140  'makelinks' => '1',
4141  'makelinks.' => [
4142  'http.' => [
4143  'extTarget.' => [
4144  'override' => '_blank',
4145  'override.' => [
4146  'if.' => [
4147  'isTrue.' => [
4148  'data' => 'TSFE:dtdAllowsFrames',
4149  ],
4150  ],
4151  ],
4152  ],
4153  'keep' => 'path',
4154  ],
4155  ],
4156  'nonTypoTagStdWrap.' => [
4157  'encapsLines.' => [
4158  'addAttributes.' => [
4159  'P.' => [
4160  'class' => 'bodytext',
4161  'class.' => [
4162  'setOnly' => 'blank',
4163  ],
4164  ],
4165  ],
4166  'encapsTagList' => 'p,pre,h1,h2,h3,h4,h5,h6,hr,dt,li',
4167  'innerStdWrap_all.' => [
4168  'ifBlank' => '&nbsp;',
4169  ],
4170  'nonWrappedTag' => 'P',
4171  'remapTag.' => [
4172  'DIV' => 'P',
4173  ],
4174  ],
4175  'HTMLparser' => '1',
4176  'HTMLparser.' => [
4177  'htmlSpecialChars' => '2',
4178  'keepNonMatchedTags' => '1',
4179  ],
4180  ],
4181  'sword' => '<span class="csc-sword">|</span>',
4182  'tags.' => [
4183  'link' => 'TEXT',
4184  'link.' => [
4185  'current' => '1',
4186  'parseFunc.' => [
4187  'constants' => '1',
4188  ],
4189  'typolink.' => [
4190  'extTarget.' => [
4191  'override' => '',
4192  'override.' => [
4193  'if.' => [
4194  'isTrue.' => [
4195  'data' => 'TSFE:dtdAllowsFrames',
4196  ],
4197  ],
4198  ],
4199  ],
4200  'parameter.' => [
4201  'data' => 'parameters : allParams',
4202  ],
4203  'target.' => [
4204  'override' => '',
4205  'override.' => [
4206  'if.' => [
4207  'isTrue.' => [
4208  'data' => 'TSFE:dtdAllowsFrames',
4209  ],
4210  ],
4211  ],
4212  ],
4213  ],
4214  ],
4215  ],
4216  ],
4217  ];
4218  }
4219 
4224  {
4225  return [
4226  'Text without tag is wrapped with <p> tag' => [
4227  'Text without tag',
4228  $this->getLibParseFunc_RTE(),
4229  '<p class="bodytext">Text without tag</p>',
4230  ],
4231  'Text wrapped with <p> tag remains the same' => [
4232  '<p class="myclass">Text with &lt;p&gt; tag</p>',
4233  $this->getLibParseFunc_RTE(),
4234  '<p class="myclass">Text with &lt;p&gt; tag</p>',
4235  ],
4236  'Text with absolute external link' => [
4237  'Text with <link http://example.com/foo/>external link</link>',
4238  $this->getLibParseFunc_RTE(),
4239  '<p class="bodytext">Text with <a href="http://example.com/foo/">external link</a></p>',
4240  ],
4241  ];
4242  }
4243 
4251  public function stdWrap_parseFuncReturnsParsedHtml($value, $configuration, $expectedResult)
4252  {
4253  $this->assertEquals($expectedResult, $this->subject->stdWrap_parseFunc($value, $configuration));
4254  }
4255 
4260  {
4261  return [
4262  'Domain only' => [
4263  'example.com',
4264  'url'
4265  ],
4266  'URL without a file' => [
4267  'http://example.com',
4268  'url'
4269  ],
4270  'URL with schema and a file' => [
4271  'http://example.com/index.php',
4272  'url'
4273  ],
4274  'URL with a file but without a schema' => [
4275  'example.com/index.php',
4276  'url'
4277  ],
4278  'file' => [
4279  '/index.php',
4280  'file'
4281  ],
4282  ];
4283  }
4284 
4291  public function detectLinkTypeFromLinkParameter($linkParameter, $expectedResult)
4292  {
4294  $templateServiceObjectMock = $this->getMock(TemplateService::class, ['dummy']);
4295  $templateServiceObjectMock->setup = [
4296  'lib.' => [
4297  'parseFunc.' => $this->getLibParseFunc(),
4298  ],
4299  ];
4301  $typoScriptFrontendControllerMockObject = $this->getMock(TypoScriptFrontendController::class, [], [], '', false);
4302  $typoScriptFrontendControllerMockObject->config = [
4303  'config' => [],
4304  'mainScript' => 'index.php',
4305  ];
4306  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
4307  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
4308  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
4309 
4310  $this->assertEquals($expectedResult, $this->subject->_call('detectLinkTypeFromLinkParameter', $linkParameter));
4311  }
4312 
4317  {
4318  return [
4319  'URL encoded local' => [
4320  'phar%3a//some-file.jpg',
4321  ],
4322  'URL encoded absolute' => [
4323  'phar%3a///path/some-file.jpg',
4324  ],
4325  'not URL encoded local' => [
4326  'phar://some-file.jpg',
4327  ],
4328  'not URL encoded absolute' => [
4329  'phar:///path/some-file.jpg',
4330  ],
4331  ];
4332  }
4333 
4339  {
4340  $this->setExpectedException(\RuntimeException::class, '', 1530030673);
4341  $this->subject->_call('detectLinkTypeFromLinkParameter', $pharUrl);
4342  }
4343 
4348  {
4349  return [
4350  'Link to url' => [
4351  'TYPO3',
4352  [
4353  'parameter' => 'http://typo3.org',
4354  ],
4355  '<a href="http://typo3.org">TYPO3</a>',
4356  ],
4357  'Link to url without schema' => [
4358  'TYPO3',
4359  [
4360  'parameter' => 'typo3.org',
4361  ],
4362  '<a href="http://typo3.org">TYPO3</a>',
4363  ],
4364  'Link to url without link text' => [
4365  '',
4366  [
4367  'parameter' => 'http://typo3.org',
4368  ],
4369  '<a href="http://typo3.org">http://typo3.org</a>',
4370  ],
4371  'Link to url with attributes' => [
4372  'TYPO3',
4373  [
4374  'parameter' => 'http://typo3.org',
4375  'ATagParams' => 'class="url-class"',
4376  'extTarget' => '_blank',
4377  'title' => 'Open new window',
4378  ],
4379  '<a href="http://typo3.org" title="Open new window" target="_blank" class="url-class">TYPO3</a>',
4380  ],
4381  'Link to url with attributes in parameter' => [
4382  'TYPO3',
4383  [
4384  'parameter' => 'http://typo3.org _blank url-class "Open new window"',
4385  ],
4386  '<a href="http://typo3.org" title="Open new window" target="_blank" class="url-class">TYPO3</a>',
4387  ],
4388  'Link to url with script tag' => [
4389  '',
4390  [
4391  'parameter' => 'http://typo3.org<script>alert(123)</script>',
4392  ],
4393  '<a href="http://typo3.org&lt;script&gt;alert(123)&lt;/script&gt;">http://typo3.org&lt;script&gt;alert(123)&lt;/script&gt;</a>',
4394  ],
4395  'Link to email address' => [
4396  'Email address',
4397  [
4398  'parameter' => 'foo@bar.org',
4399  ],
4400  '<a href="mailto:foo@bar.org">Email address</a>',
4401  ],
4402  'Link to email address without link text' => [
4403  '',
4404  [
4405  'parameter' => 'foo@bar.org',
4406  ],
4407  '<a href="mailto:foo@bar.org">foo@bar.org</a>',
4408  ],
4409  'Link to email with attributes' => [
4410  'Email address',
4411  [
4412  'parameter' => 'foo@bar.org',
4413  'ATagParams' => 'class="email-class"',
4414  'title' => 'Write an email',
4415  ],
4416  '<a href="mailto:foo@bar.org" title="Write an email" class="email-class">Email address</a>',
4417  ],
4418  'Link to email with attributes in parameter' => [
4419  'Email address',
4420  [
4421  'parameter' => 'foo@bar.org - email-class "Write an email"',
4422  ],
4423  '<a href="mailto:foo@bar.org" title="Write an email" class="email-class">Email address</a>',
4424  ],
4425  ];
4426  }
4427 
4435  public function typolinkReturnsCorrectLinksForEmailsAndUrls($linkText, $configuration, $expectedResult)
4436  {
4437  $templateServiceObjectMock = $this->getMock(TemplateService::class, ['dummy']);
4438  $templateServiceObjectMock->setup = [
4439  'lib.' => [
4440  'parseFunc.' => $this->getLibParseFunc(),
4441  ],
4442  ];
4443  $typoScriptFrontendControllerMockObject = $this->getMock(TypoScriptFrontendController::class, [], [], '', false);
4444  $typoScriptFrontendControllerMockObject->config = [
4445  'config' => [],
4446  'mainScript' => 'index.php',
4447  ];
4448  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
4449  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
4450  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
4451 
4452  $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
4453  }
4454 
4459  {
4460  return [
4461  'Link to page' => [
4462  'My page',
4463  [
4464  'parameter' => 42,
4465  ],
4466  [
4467  'uid' => 42,
4468  'title' => 'Page title',
4469  ],
4470  '<a href="index.php?id=42">My page</a>',
4471  ],
4472  'Link to page without link text' => [
4473  '',
4474  [
4475  'parameter' => 42,
4476  ],
4477  [
4478  'uid' => 42,
4479  'title' => 'Page title',
4480  ],
4481  '<a href="index.php?id=42">Page title</a>',
4482  ],
4483  'Link to page with attributes' => [
4484  'My page',
4485  [
4486  'parameter' => '42',
4487  'ATagParams' => 'class="page-class"',
4488  'target' => '_self',
4489  'title' => 'Link to internal page',
4490  ],
4491  [
4492  'uid' => 42,
4493  'title' => 'Page title',
4494  ],
4495  '<a href="index.php?id=42" title="Link to internal page" target="_self" class="page-class">My page</a>',
4496  ],
4497  'Link to page with attributes in parameter' => [
4498  'My page',
4499  [
4500  'parameter' => '42 _self page-class "Link to internal page"',
4501  ],
4502  [
4503  'uid' => 42,
4504  'title' => 'Page title',
4505  ],
4506  '<a href="index.php?id=42" title="Link to internal page" target="_self" class="page-class">My page</a>',
4507  ],
4508  'Link to page with bold tag in title' => [
4509  '',
4510  [
4511  'parameter' => 42,
4512  ],
4513  [
4514  'uid' => 42,
4515  'title' => 'Page <b>title</b>',
4516  ],
4517  '<a href="index.php?id=42">Page <b>title</b></a>',
4518  ],
4519  'Link to page with script tag in title' => [
4520  '',
4521  [
4522  'parameter' => 42,
4523  ],
4524  [
4525  'uid' => 42,
4526  'title' => '<script>alert(123)</script>Page title',
4527  ],
4528  '<a href="index.php?id=42">&lt;script&gt;alert(123)&lt;/script&gt;Page title</a>',
4529  ],
4530  ];
4531  }
4532 
4541  public function typoLinkEncodesMailAddressForSpamProtection(array $settings, $linkText, $mailAddress, $expected)
4542  {
4543  $this->getFrontendController()->spamProtectEmailAddresses = $settings['spamProtectEmailAddresses'];
4544  $this->getFrontendController()->config['config'] = $settings;
4545  $typoScript = ['parameter' => $mailAddress];
4546 
4547  $this->assertEquals($expected, $this->subject->typoLink($linkText, $typoScript));
4548  }
4549 
4554  {
4555  return [
4556  'plain mail without mailto scheme' => [
4557  [
4558  'spamProtectEmailAddresses' => '',
4559  'spamProtectEmailAddresses_atSubst' => '',
4560  'spamProtectEmailAddresses_lastDotSubst' => '',
4561  ],
4562  'some.body@test.typo3.org',
4563  'some.body@test.typo3.org',
4564  '<a href="mailto:some.body@test.typo3.org">some.body@test.typo3.org</a>',
4565  ],
4566  'plain mail with mailto scheme' => [
4567  [
4568  'spamProtectEmailAddresses' => '',
4569  'spamProtectEmailAddresses_atSubst' => '',
4570  'spamProtectEmailAddresses_lastDotSubst' => '',
4571  ],
4572  'some.body@test.typo3.org',
4573  'mailto:some.body@test.typo3.org',
4574  '<a href="mailto:some.body@test.typo3.org">some.body@test.typo3.org</a>',
4575  ],
4576  'plain with at and dot substitution' => [
4577  [
4578  'spamProtectEmailAddresses' => '0',
4579  'spamProtectEmailAddresses_atSubst' => '(at)',
4580  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
4581  ],
4582  'some.body@test.typo3.org',
4583  'mailto:some.body@test.typo3.org',
4584  '<a href="mailto:some.body@test.typo3.org">some.body@test.typo3.org</a>',
4585  ],
4586  'mono-alphabetic substitution offset +1' => [
4587  [
4588  'spamProtectEmailAddresses' => '1',
4589  'spamProtectEmailAddresses_atSubst' => '',
4590  'spamProtectEmailAddresses_lastDotSubst' => '',
4591  ],
4592  'some.body@test.typo3.org',
4593  'mailto:some.body@test.typo3.org',
4594  '<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body(at)test.typo3.org</a>',
4595  ],
4596  'mono-alphabetic substitution offset +1 with at substitution' => [
4597  [
4598  'spamProtectEmailAddresses' => '1',
4599  'spamProtectEmailAddresses_atSubst' => '@',
4600  'spamProtectEmailAddresses_lastDotSubst' => '',
4601  ],
4602  'some.body@test.typo3.org',
4603  'mailto:some.body@test.typo3.org',
4604  '<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body@test.typo3.org</a>',
4605  ],
4606  'mono-alphabetic substitution offset +1 with at and dot substitution' => [
4607  [
4608  'spamProtectEmailAddresses' => '1',
4609  'spamProtectEmailAddresses_atSubst' => '(at)',
4610  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
4611  ],
4612  'some.body@test.typo3.org',
4613  'mailto:some.body@test.typo3.org',
4614  '<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body(at)test.typo3(dot)org</a>',
4615  ],
4616  'mono-alphabetic substitution offset -1 with at and dot substitution' => [
4617  [
4618  'spamProtectEmailAddresses' => '-1',
4619  'spamProtectEmailAddresses_atSubst' => '(at)',
4620  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
4621  ],
4622  'some.body@test.typo3.org',
4623  'mailto:some.body@test.typo3.org',
4624  '<a href="javascript:linkTo_UnCryptMailto(\'lzhksn9rnld-ancxZsdrs-sxon2-nqf\');">some.body(at)test.typo3(dot)org</a>',
4625  ],
4626  'entity substitution with at and dot substitution' => [
4627  [
4628  'spamProtectEmailAddresses' => 'ascii',
4629  'spamProtectEmailAddresses_atSubst' => '',
4630  'spamProtectEmailAddresses_lastDotSubst' => '',
4631  ],
4632  'some.body@test.typo3.org',
4633  'mailto:some.body@test.typo3.org',
4634  '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#111;&#109;&#101;&#46;&#98;&#111;&#100;&#121;&#64;&#116;&#101;&#115;&#116;&#46;&#116;&#121;&#112;&#111;&#51;&#46;&#111;&#114;&#103;">some.body(at)test.typo3.org</a>',
4635  ],
4636  'entity substitution with at and dot substitution with at and dot substitution' => [
4637  [
4638  'spamProtectEmailAddresses' => 'ascii',
4639  'spamProtectEmailAddresses_atSubst' => '(at)',
4640  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
4641  ],
4642  'some.body@test.typo3.org',
4643  'mailto:some.body@test.typo3.org',
4644  '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#111;&#109;&#101;&#46;&#98;&#111;&#100;&#121;&#64;&#116;&#101;&#115;&#116;&#46;&#116;&#121;&#112;&#111;&#51;&#46;&#111;&#114;&#103;">some.body(at)test.typo3(dot)org</a>',
4645  ],
4646  ];
4647  }
4648 
4657  public function typolinkReturnsCorrectLinksForPages($linkText, $configuration, $pageArray, $expectedResult)
4658  {
4659  $pageRepositoryMockObject = $this->getMock(\TYPO3\CMS\Frontend\Page\PageRepository::class, ['getPage']);
4660  $pageRepositoryMockObject->expects($this->any())->method('getPage')->willReturn($pageArray);
4661  $templateServiceObjectMock = $this->getMock(TemplateService::class, ['dummy']);
4662  $templateServiceObjectMock->setup = [
4663  'lib.' => [
4664  'parseFunc.' => $this->getLibParseFunc(),
4665  ],
4666  ];
4667  $typoScriptFrontendControllerMockObject = $this->getMock(TypoScriptFrontendController::class, [], [], '', false);
4668  $typoScriptFrontendControllerMockObject->config = [
4669  'config' => [],
4670  'mainScript' => 'index.php',
4671  ];
4672  $typoScriptFrontendControllerMockObject->sys_page = $pageRepositoryMockObject;
4673  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
4674  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
4675  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
4676 
4677  $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
4678  }
4679 
4684  {
4685  return [
4686  'Link to file' => [
4687  'My file',
4688  [
4689  'parameter' => 'fileadmin/foo.bar',
4690  ],
4691  '<a href="fileadmin/foo.bar">My file</a>',
4692  ],
4693  'Link to file without link text' => [
4694  '',
4695  [
4696  'parameter' => 'fileadmin/foo.bar',
4697  ],
4698  '<a href="fileadmin/foo.bar">fileadmin/foo.bar</a>',
4699  ],
4700  'Link to file with attributes' => [
4701  'My file',
4702  [
4703  'parameter' => 'fileadmin/foo.bar',
4704  'ATagParams' => 'class="file-class"',
4705  'fileTarget' => '_blank',
4706  'title' => 'Title of the file',
4707  ],
4708  '<a href="fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
4709  ],
4710  'Link to file with attributes in parameter' => [
4711  'My file',
4712  [
4713  'parameter' => 'fileadmin/foo.bar _blank file-class "Title of the file"',
4714  ],
4715  '<a href="fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
4716  ],
4717  'Link to file with script tag in name' => [
4718  '',
4719  [
4720  'parameter' => 'fileadmin/<script>alert(123)</script>',
4721  ],
4722  '<a href="fileadmin/&lt;script&gt;alert(123)&lt;/script&gt;">fileadmin/&lt;script&gt;alert(123)&lt;/script&gt;</a>',
4723  ],
4724  ];
4725  }
4726 
4734  public function typolinkReturnsCorrectLinksFiles($linkText, $configuration, $expectedResult)
4735  {
4736  $templateServiceObjectMock = $this->getMock(TemplateService::class, ['dummy']);
4737  $templateServiceObjectMock->setup = [
4738  'lib.' => [
4739  'parseFunc.' => $this->getLibParseFunc(),
4740  ],
4741  ];
4742  $typoScriptFrontendControllerMockObject = $this->getMock(TypoScriptFrontendController::class, [], [], '', false);
4743  $typoScriptFrontendControllerMockObject->config = [
4744  'config' => [],
4745  'mainScript' => 'index.php',
4746  ];
4747  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
4748  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
4749  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
4750 
4751  $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
4752  }
4753 
4758  {
4759  return [
4760  'Link to file' => [
4761  'My file',
4762  [
4763  'parameter' => 'fileadmin/foo.bar',
4764  ],
4765  '/',
4766  '<a href="/fileadmin/foo.bar">My file</a>',
4767  ],
4768  'Link to file with longer absRefPrefix' => [
4769  'My file',
4770  [
4771  'parameter' => 'fileadmin/foo.bar',
4772  ],
4773  '/sub/',
4774  '<a href="/sub/fileadmin/foo.bar">My file</a>',
4775  ],
4776  'Link to absolute file' => [
4777  'My file',
4778  [
4779  'parameter' => '/images/foo.bar',
4780  ],
4781  '/',
4782  '<a href="/images/foo.bar">My file</a>',
4783  ],
4784  'Link to absolute file with longer absRefPrefix' => [
4785  'My file',
4786  [
4787  'parameter' => '/images/foo.bar',
4788  ],
4789  '/sub/',
4790  '<a href="/images/foo.bar">My file</a>',
4791  ],
4792  'Link to absolute file with identical longer absRefPrefix' => [
4793  'My file',
4794  [
4795  'parameter' => '/sub/fileadmin/foo.bar',
4796  ],
4797  '/sub/',
4798  '<a href="/sub/fileadmin/foo.bar">My file</a>',
4799  ],
4800  'Link to file with empty absRefPrefix' => [
4801  'My file',
4802  [
4803  'parameter' => 'fileadmin/foo.bar',
4804  ],
4805  '',
4806  '<a href="fileadmin/foo.bar">My file</a>',
4807  ],
4808  'Link to absolute file with empty absRefPrefix' => [
4809  'My file',
4810  [
4811  'parameter' => '/fileadmin/foo.bar',
4812  ],
4813  '',
4814  '<a href="/fileadmin/foo.bar">My file</a>',
4815  ],
4816  'Link to file with attributes with absRefPrefix' => [
4817  'My file',
4818  [
4819  'parameter' => 'fileadmin/foo.bar',
4820  'ATagParams' => 'class="file-class"',
4821  'fileTarget' => '_blank',
4822  'title' => 'Title of the file',
4823  ],
4824  '/',
4825  '<a href="/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
4826  ],
4827  'Link to file with attributes with longer absRefPrefix' => [
4828  'My file',
4829  [
4830  'parameter' => 'fileadmin/foo.bar',
4831  'ATagParams' => 'class="file-class"',
4832  'fileTarget' => '_blank',
4833  'title' => 'Title of the file',
4834  ],
4835  '/sub/',
4836  '<a href="/sub/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
4837  ],
4838  'Link to absolute file with attributes with absRefPrefix' => [
4839  'My file',
4840  [
4841  'parameter' => '/images/foo.bar',
4842  'ATagParams' => 'class="file-class"',
4843  'fileTarget' => '_blank',
4844  'title' => 'Title of the file',
4845  ],
4846  '/',
4847  '<a href="/images/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
4848  ],
4849  'Link to absolute file with attributes with longer absRefPrefix' => [
4850  'My file',
4851  [
4852  'parameter' => '/images/foo.bar',
4853  'ATagParams' => 'class="file-class"',
4854  'fileTarget' => '_blank',
4855  'title' => 'Title of the file',
4856  ],
4857  '/sub/',
4858  '<a href="/images/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
4859  ],
4860  'Link to absolute file with attributes with identical longer absRefPrefix' => [
4861  'My file',
4862  [
4863  'parameter' => '/sub/fileadmin/foo.bar',
4864  'ATagParams' => 'class="file-class"',
4865  'fileTarget' => '_blank',
4866  'title' => 'Title of the file',
4867  ],
4868  '/sub/',
4869  '<a href="/sub/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
4870  ],
4871  ];
4872  }
4873 
4882  public function typolinkReturnsCorrectLinksForFilesWithAbsRefPrefix($linkText, $configuration, $absRefPrefix, $expectedResult)
4883  {
4884  $templateServiceObjectMock = $this->getMock(TemplateService::class, ['dummy']);
4885  $templateServiceObjectMock->setup = [
4886  'lib.' => [
4887  'parseFunc.' => $this->getLibParseFunc(),
4888  ],
4889  ];
4890  $typoScriptFrontendControllerMockObject = $this->getMock(TypoScriptFrontendController::class, [], [], '', false);
4891  $typoScriptFrontendControllerMockObject->config = [
4892  'config' => [],
4893  'mainScript' => 'index.php',
4894  ];
4895  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
4896  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
4897  $GLOBALS['TSFE']->absRefPrefix = $absRefPrefix;
4898  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
4899 
4900  $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
4901  }
4902 
4907  {
4908  $conf = [
4909  'token' => ',',
4910  'returnCount' => 1
4911  ];
4912  $expectedResult = 5;
4913  $amountOfEntries = $this->subject->splitObj('1, 2, 3, 4, 5', $conf);
4914  $this->assertSame(
4915  $expectedResult,
4916  $amountOfEntries
4917  );
4918  }
4919 
4924  {
4925  return [
4926  [
4927  [
4928  'tt_content' => [
4929  'ctrl' => [
4930  ],
4931  'columns' => [
4932  ]
4933  ],
4934  ],
4935  'tt_content',
4936  [
4937  'uidInList' => '42',
4938  'pidInList' => 43,
4939  'where' => 'tt_content.cruser_id=5',
4940  'andWhere' => 'tt_content.crdate>0',
4941  'groupBy' => 'tt_content.title',
4942  'orderBy' => 'tt_content.sorting',
4943  ],
4944  'WHERE tt_content.uid=42 AND tt_content.pid IN (43) AND tt_content.cruser_id=5 AND tt_content.crdate>0 GROUP BY tt_content.title ORDER BY tt_content.sorting',
4945  ],
4946  [
4947  [
4948  'tt_content' => [
4949  'ctrl' => [
4950  'delete' => 'deleted',
4951  'enablecolumns' => [
4952  'disabled' => 'hidden',
4953  'starttime' => 'startdate',
4954  'endtime' => 'enddate',
4955  ],
4956  'languageField' => 'sys_language_uid',
4957  'transOrigPointerField' => 'l18n_parent',
4958  ],
4959  'columns' => [
4960  ]
4961  ],
4962  ],
4963  'tt_content',
4964  [
4965  'uidInList' => 42,
4966  'pidInList' => 43,
4967  'where' => 'tt_content.cruser_id=5',
4968  'andWhere' => 'tt_content.crdate>0',
4969  'groupBy' => 'tt_content.title',
4970  'orderBy' => 'tt_content.sorting',
4971  ],
4972  'WHERE tt_content.uid=42 AND tt_content.pid IN (43) AND tt_content.cruser_id=5 AND (tt_content.sys_language_uid = 13) AND tt_content.crdate>0 AND tt_content.deleted=0 AND tt_content.hidden=0 AND tt_content.startdate<=4242 AND (tt_content.enddate=0 OR tt_content.enddate>4242) GROUP BY tt_content.title ORDER BY tt_content.sorting',
4973  ],
4974  [
4975  [
4976  'tt_content' => [
4977  'ctrl' => [
4978  'languageField' => 'sys_language_uid',
4979  'transOrigPointerField' => 'l18n_parent',
4980  ],
4981  'columns' => [
4982  ]
4983  ],
4984  ],
4985  'tt_content',
4986  [
4987  'uidInList' => 42,
4988  'pidInList' => 43,
4989  'where' => 'tt_content.cruser_id=5',
4990  'languageField' => 0,
4991  ],
4992  'WHERE tt_content.uid=42 AND tt_content.pid IN (43) AND tt_content.cruser_id=5',
4993  ],
4994  ];
4995  }
4996 
5005  public function getWhereReturnCorrectQuery($tca, $table, $configuration, $expectedResult)
5006  {
5007  $GLOBALS['TCA'] = $tca;
5008  $GLOBALS['SIM_ACCESS_TIME'] = '4242';
5009  $GLOBALS['TSFE']->sys_language_content = 13;
5011  $contentObjectRenderer = $this->getMock(ContentObjectRenderer::class, ['checkPidArray']);
5012  $contentObjectRenderer->expects($this->any())->method('checkPidArray')->willReturn(explode(',', $configuration['pidInList']));
5013  $this->assertEquals($expectedResult, $contentObjectRenderer->getWhere($table, $configuration));
5014  }
5015 
5017  // Test concerning link generation
5019 
5024  {
5025  $fileNameAndPath = PATH_site . 'typo3temp/phpunitJumpUrlTestFile with spaces & amps.txt';
5026  file_put_contents($fileNameAndPath, 'Some test data');
5027  $relativeFileNameAndPath = substr($fileNameAndPath, strlen(PATH_site));
5028  $fileName = substr($fileNameAndPath, strlen(PATH_site . 'typo3temp/'));
5029 
5030  $expectedLink = str_replace('%2F', '/', rawurlencode($relativeFileNameAndPath));
5031  $result = $this->subject->filelink($fileName, ['path' => 'typo3temp/']);
5032  $this->assertEquals('<a href="' . $expectedLink . '">' . $fileName . '</a>', $result);
5033 
5035  }
5036 
5041  {
5042  return [
5043  'no markers defined' => [
5044  'dummy content with ###UNREPLACED### marker',
5045  [],
5046  [],
5047  [],
5048  'dummy content with ###UNREPLACED### marker',
5049  false,
5050  false
5051  ],
5052  'no markers used' => [
5053  'dummy content with no marker',
5054  [
5055  '###REPLACED###' => '_replaced_'
5056  ],
5057  [],
5058  [],
5059  'dummy content with no marker',
5060  true,
5061  false
5062  ],
5063  'one marker' => [
5064  'dummy content with ###REPLACED### marker',
5065  [
5066  '###REPLACED###' => '_replaced_'
5067  ],
5068  [],
5069  [],
5070  'dummy content with _replaced_ marker'
5071  ],
5072  'one marker with lots of chars' => [
5073  'dummy content with ###RE.:##-=_()LACED### marker',
5074  [
5075  '###RE.:##-=_()LACED###' => '_replaced_'
5076  ],
5077  [],
5078  [],
5079  'dummy content with _replaced_ marker'
5080  ],
5081  'markers which are special' => [
5082  'dummy ###aa##.#######A### ######',
5083  [
5084  '###aa##.###' => 'content ',
5085  '###A###' => 'is',
5086  '######' => '-is not considered-'
5087  ],
5088  [],
5089  [],
5090  'dummy content #is ######'
5091  ],
5092  'two markers in content, but more defined' => [
5093  'dummy ###CONTENT### with ###REPLACED### marker',
5094  [
5095  '###REPLACED###' => '_replaced_',
5096  '###CONTENT###' => 'content',
5097  '###NEVERUSED###' => 'bar'
5098  ],
5099  [],
5100  [],
5101  'dummy content with _replaced_ marker'
5102  ],
5103  'one subpart' => [
5104  'dummy content with ###ASUBPART### around some text###ASUBPART###.',
5105  [],
5106  [
5107  '###ASUBPART###' => 'some other text'
5108  ],
5109  [],
5110  'dummy content with some other text.'
5111  ],
5112  'one wrapped subpart' => [
5113  'dummy content with ###AWRAPPEDSUBPART### around some text###AWRAPPEDSUBPART###.',
5114  [],
5115  [],
5116  [
5117  '###AWRAPPEDSUBPART###' => [
5118  'more content',
5119  'content'
5120  ]
5121  ],
5122  'dummy content with more content around some textcontent.'
5123  ],
5124  'one subpart with markers, not replaced recursively' => [
5125  'dummy ###CONTENT### with ###ASUBPART### around ###SOME### text###ASUBPART###.',
5126  [
5127  '###CONTENT###' => 'content',
5128  '###SOME###' => '-this should never make it into output-',
5129  '###OTHER_NOT_REPLACED###' => '-this should never make it into output-'
5130  ],
5131  [
5132  '###ASUBPART###' => 'some ###OTHER_NOT_REPLACED### text'
5133  ],
5134  [],
5135  'dummy content with some ###OTHER_NOT_REPLACED### text.'
5136  ],
5137  ];
5138  }
5139 
5152  public function substituteMarkerArrayCachedReturnsExpectedContent($content, array $markContentArray, array $subpartContentArray, array $wrappedSubpartContentArray, $expectedContent, $shouldQueryCache = true, $shouldStoreCache = true)
5153  {
5155  $pageRepo = $this->typoScriptFrontendControllerMock->sys_page;
5156  $pageRepo->resetCallCount();
5157 
5158  $resultContent = $this->subject->substituteMarkerArrayCached($content, $markContentArray, $subpartContentArray, $wrappedSubpartContentArray);
5159 
5160  $this->assertSame((int)$shouldQueryCache, $pageRepo::$getHashCallCount, 'getHash call count mismatch');
5161  $this->assertSame((int)$shouldStoreCache, $pageRepo::$storeHashCallCount, 'storeHash call count mismatch');
5162  $this->assertSame($expectedContent, $resultContent);
5163  }
5164 
5168  public function substituteMarkerArrayCachedRetrievesCachedValueFromRuntimeCache()
5169  {
5171  $pageRepo = $this->typoScriptFrontendControllerMock->sys_page;
5172  $pageRepo->resetCallCount();
5173 
5174  $content = 'Please tell me this ###FOO###.';
5175  $markContentArray = [
5176  '###FOO###' => 'foo',
5177  '###NOTUSED###' => 'blub'
5178  ];
5179  $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize([$content, array_keys($markContentArray)]));
5180  $this->subject->substMarkerCache[$storeKey] = [
5181  'c' => [
5182  'Please tell me this ',
5183  '.'
5184  ],
5185  'k' => [
5186  '###FOO###'
5187  ],
5188  ];
5189  $resultContent = $this->subject->substituteMarkerArrayCached($content, $markContentArray);
5190  $this->assertSame(0, $pageRepo::$getHashCallCount);
5191  $this->assertSame('Please tell me this foo.', $resultContent);
5192  }
5193 
5197  public function substituteMarkerArrayCachedRetrievesCachedValueFromDbCache()
5198  {
5200  $pageRepo = $this->typoScriptFrontendControllerMock->sys_page;
5201  $pageRepo->resetCallCount();
5202 
5203  $content = 'Please tell me this ###FOO###.';
5204  $markContentArray = [
5205  '###FOO###' => 'foo',
5206  '###NOTUSED###' => 'blub'
5207  ];
5208  $pageRepo::$dbCacheContent = [
5209  'c' => [
5210  'Please tell me this ',
5211  '.'
5212  ],
5213  'k' => [
5214  '###FOO###'
5215  ],
5216  ];
5217  $resultContent = $this->subject->substituteMarkerArrayCached($content, $markContentArray);
5218  $this->assertSame(1, $pageRepo::$getHashCallCount, 'getHash call count mismatch');
5219  $this->assertSame(0, $pageRepo::$storeHashCallCount, 'storeHash call count mismatch');
5220  $this->assertSame('Please tell me this foo.', $resultContent);
5221  }
5222 
5226  public function substituteMarkerArrayCachedStoresResultInCaches()
5227  {
5229  $pageRepo = $this->typoScriptFrontendControllerMock->sys_page;
5230  $pageRepo->resetCallCount();
5231 
5232  $content = 'Please tell me this ###FOO###.';
5233  $markContentArray = [
5234  '###FOO###' => 'foo',
5235  '###NOTUSED###' => 'blub'
5236  ];
5237  $resultContent = $this->subject->substituteMarkerArrayCached($content, $markContentArray);
5238 
5239  $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize([$content, array_keys($markContentArray)]));
5240  $storeArr = [
5241  'c' => [
5242  'Please tell me this ',
5243  '.'
5244  ],
5245  'k' => [
5246  '###FOO###'
5247  ],
5248  ];
5249  $this->assertSame(1, $pageRepo::$getHashCallCount);
5250  $this->assertSame('Please tell me this foo.', $resultContent);
5251  $this->assertSame($storeArr, $this->subject->substMarkerCache[$storeKey]);
5252  $this->assertSame(1, $pageRepo::$storeHashCallCount);
5253  }
5254 
5258  protected function getFrontendController()
5259  {
5260  return $GLOBALS['TSFE'];
5261  }
5262 }
static unlink_tempfile($uploadedTempFileName)
static useAnsiColor($ansiColorUsage)
static setSingletonInstance($className, SingletonInterface $instance)
typolinkReturnsCorrectLinksForPages($linkText, $configuration, $pageArray, $expectedResult)
typoLinkEncodesMailAddressForSpamProtection(array $settings, $linkText, $mailAddress, $expected)
typolinkReturnsCorrectLinksForFilesWithAbsRefPrefix($linkText, $configuration, $absRefPrefix, $expectedResult)
stdWrap_stdWrapValue($key, array $configuration, $defaultValue, $expected)
static resetSingletonInstances(array $newSingletonInstances)
getAccessibleMock( $originalClassName, $methods=[], array $arguments=[], $mockClassName='', $callOriginalConstructor=true, $callOriginalClone=true, $callAutoload=true)
typolinkReturnsCorrectLinksForEmailsAndUrls($linkText, $configuration, $expectedResult)
$uid
Definition: server.php:38
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']