TYPO3 CMS  TYPO3_8-7
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 
59 
63 class ContentObjectRendererTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
64 {
65 
69  protected $singletonInstances = [];
70 
74  protected $subject = null;
75 
79  protected $frontendControllerMock = null;
80 
84  protected $cacheFrontendMock = null;
85 
89  protected $templateServiceMock = null;
90 
96  protected $contentObjectMap = [
97  'TEXT' => TextContentObject::class,
98  'CASE' => CaseContentObject::class,
99  'COBJ_ARRAY' => ContentObjectArrayContentObject::class,
100  'COA' => ContentObjectArrayContentObject::class,
101  'COA_INT' => ContentObjectArrayInternalContentObject::class,
102  'USER' => UserContentObject::class,
103  'USER_INT' => UserInternalContentObject::class,
104  'FILE' => FileContentObject::class,
105  'FILES' => FilesContentObject::class,
106  'IMAGE' => ImageContentObject::class,
107  'IMG_RESOURCE' => ImageResourceContentObject::class,
108  'CONTENT' => ContentContentObject::class,
109  'RECORDS' => RecordsContentObject::class,
110  'HMENU' => HierarchicalMenuContentObject::class,
111  'CASEFUNC' => CaseContentObject::class,
112  'LOAD_REGISTER' => LoadRegisterContentObject::class,
113  'RESTORE_REGISTER' => RestoreRegisterContentObject::class,
114  'TEMPLATE' => TemplateContentObject::class,
115  'FLUIDTEMPLATE' => FluidTemplateContentObject::class,
116  'SVG' => ScalableVectorGraphicsContentObject::class,
117  'EDITPANEL' => EditPanelContentObject::class
118  ];
119 
123  protected function setUp()
124  {
125  $this->singletonInstances = GeneralUtility::getSingletonInstances();
127 
128  $this->templateServiceMock =
129  $this->getMockBuilder(TemplateService::class)
130  ->setMethods(['getFileName', 'linkData'])->getMock();
131  $pageRepositoryMock =
132  $this->getAccessibleMock(PageRepository::class, ['getRawRecord', 'getMountPointInfo']);
133  $this->frontendControllerMock =
134  $this->getAccessibleMock(
135  TypoScriptFrontendController::class,
136  ['dummy'],
137  [],
138  '',
139  false
140  );
141  $this->frontendControllerMock->tmpl = $this->templateServiceMock;
142  $this->frontendControllerMock->config = [];
143  $this->frontendControllerMock->page = [];
144  $this->frontendControllerMock->sys_page = $pageRepositoryMock;
146 
147  $this->subject = $this->getAccessibleMock(
148  ContentObjectRenderer::class,
149  ['getResourceFactory', 'getEnvironmentVariable'],
150  [$this->frontendControllerMock]
151  );
152  $this->subject->setContentObjectClassMap($this->contentObjectMap);
153  $this->subject->start([], 'tt_content');
154  }
155 
156  protected function tearDown()
157  {
158  GeneralUtility::resetSingletonInstances($this->singletonInstances);
159  parent::tearDown();
160  }
161 
163  // Utility functions
165 
169  protected function getFrontendController()
170  {
171  return $GLOBALS['TSFE'];
172  }
173 
177  protected function createMockedLoggerAndLogManager()
178  {
179  $logManagerMock = $this->getMockBuilder(LogManager::class)->getMock();
180  $loggerMock = $this->getMockBuilder(LoggerInterface::class)->getMock();
181  $logManagerMock->expects($this->any())
182  ->method('getLogger')
183  ->willReturn($loggerMock);
184  GeneralUtility::setSingletonInstance(LogManager::class, $logManagerMock);
185  }
186 
193  protected function handleCharset(&$subject, &$expected)
194  {
195  $subject = mb_convert_encoding($subject, 'utf-8', 'iso-8859-1');
196  $expected = mb_convert_encoding($expected, 'utf-8', 'iso-8859-1');
197  }
198 
200  // Tests concerning the getImgResource hook
202 
206  {
207  $this->templateServiceMock
208  ->expects($this->atLeastOnce())
209  ->method('getFileName')
210  ->with('typo3/clear.gif')
211  ->will($this->returnValue('typo3/clear.gif'));
212 
213  $resourceFactory = $this->createMock(ResourceFactory::class);
214  $this->subject->expects($this->any())->method('getResourceFactory')->will($this->returnValue($resourceFactory));
215 
216  $className = $this->getUniqueId('tx_coretest');
217  $getImgResourceHookMock = $this->getMockBuilder(\TYPO3\CMS\Frontend\ContentObject\ContentObjectGetImageResourceHookInterface::class)
218  ->setMethods(['getImgResourcePostProcess'])
219  ->setMockClassName($className)
220  ->getMock();
221  $getImgResourceHookMock
222  ->expects($this->once())
223  ->method('getImgResourcePostProcess')
224  ->will($this->returnCallback([$this, 'isGetImgResourceHookCalledCallback']));
225  $getImgResourceHookObjects = [$getImgResourceHookMock];
226  $this->subject->_setRef('getImgResourceHookObjects', $getImgResourceHookObjects);
227  $this->subject->getImgResource('typo3/clear.gif', []);
228  }
229 
240  public function isGetImgResourceHookCalledCallback($file, $fileArray, $imageResource, $parent)
241  {
242  $this->assertEquals('typo3/clear.gif', $file);
243  $this->assertEquals('typo3/clear.gif', $imageResource['origFile']);
244  $this->assertTrue(is_array($fileArray));
245  $this->assertTrue($parent instanceof ContentObjectRenderer);
246  return $imageResource;
247  }
248 
250  // Tests related to getContentObject
252 
267  {
268  $className = TextContentObject::class;
269  $contentObjectName = 'TEST_TEXT';
270  $this->subject->registerContentObjectClass(
271  $className,
272  $contentObjectName
273  );
274  $object = $this->subject->getContentObject($contentObjectName);
275  $this->assertInstanceOf($className, $object);
276  }
277 
286  {
287  $className = TextContentObject::class;
288  $contentObjectName = 'TEST_TEXT';
289  $classMap = [$contentObjectName => $className];
290  $this->subject->setContentObjectClassMap($classMap);
291  $object = $this->subject->getContentObject($contentObjectName);
292  $this->assertInstanceOf($className, $object);
293  }
294 
304  {
305  $className = TextContentObject::class;
306  $contentObjectName = 'TEST_TEXT';
307  $classMap = [];
308  $this->subject->setContentObjectClassMap($classMap);
309  $classMap[$contentObjectName] = $className;
310  $object = $this->subject->getContentObject($contentObjectName);
311  $this->assertNull($object);
312  }
313 
319  {
320  $object = $this->subject->getContentObject('FOO');
321  $this->assertNull($object);
322  }
323 
329  {
330  $this->expectException(ContentRenderingException::class);
331  $this->subject->registerContentObjectClass(
332  \stdClass::class,
333  'STDCLASS'
334  );
335  $this->subject->getContentObject('STDCLASS');
336  }
337 
342  {
343  $dataProvider = [];
344  foreach ($this->contentObjectMap as $name => $className) {
345  $dataProvider[] = [$name, $className];
346  }
347  return $dataProvider;
348  }
349 
360  string $objectName,
361  string $className
362  ) {
363  $this->assertTrue(
364  is_subclass_of($className, AbstractContentObject::class)
365  );
366  $object = $this->subject->getContentObject($objectName);
367  $this->assertInstanceOf($className, $object);
368  }
369 
371  // Tests concerning getQueryArguments()
373 
377  {
378  $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
379  $this->returnValue('key1=value1&key2=value2&key3[key31]=value31&key3[key32][key321]=value321&key3[key32][key322]=value322')
380  );
381  $getQueryArgumentsConfiguration = [];
382  $getQueryArgumentsConfiguration['exclude'] = [];
383  $getQueryArgumentsConfiguration['exclude'][] = 'key1';
384  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
385  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
386  $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
387  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2&key3[key32][key322]=value322');
388  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
389  $this->assertEquals($expectedResult, $actualResult);
390  }
391 
396  {
397  $_GET = [
398  'key1' => 'value1',
399  'key2' => 'value2',
400  'key3' => [
401  'key31' => 'value31',
402  'key32' => [
403  'key321' => 'value321',
404  'key322' => 'value322'
405  ]
406  ]
407  ];
408  $getQueryArgumentsConfiguration = [];
409  $getQueryArgumentsConfiguration['method'] = 'GET';
410  $getQueryArgumentsConfiguration['exclude'] = [];
411  $getQueryArgumentsConfiguration['exclude'][] = 'key1';
412  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
413  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
414  $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
415  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2&key3[key32][key322]=value322');
416  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
417  $this->assertEquals($expectedResult, $actualResult);
418  }
419 
424  {
425  $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
426  $this->returnValue('key1=value1')
427  );
428  $getQueryArgumentsConfiguration = [];
429  $overruleArguments = [
430  // Should be overridden
431  'key1' => 'value1Overruled',
432  // Shouldn't be set: Parameter doesn't exist in source array and is not forced
433  'key2' => 'value2Overruled'
434  ];
435  $expectedResult = '&key1=value1Overruled';
436  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments);
437  $this->assertEquals($expectedResult, $actualResult);
438  }
439 
444  {
445  $_POST = [
446  'key1' => 'value1',
447  'key2' => 'value2',
448  'key3' => [
449  'key31' => 'value31',
450  'key32' => [
451  'key321' => 'value321',
452  'key322' => 'value322'
453  ]
454  ]
455  ];
456  $getQueryArgumentsConfiguration = [];
457  $getQueryArgumentsConfiguration['method'] = 'POST';
458  $getQueryArgumentsConfiguration['exclude'] = [];
459  $getQueryArgumentsConfiguration['exclude'][] = 'key1';
460  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
461  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
462  $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
463  $overruleArguments = [
464  // Should be overridden
465  'key2' => 'value2Overruled',
466  'key3' => [
467  'key32' => [
468  // Shouldn't be set: Parameter is excluded and not forced
469  'key321' => 'value321Overruled',
470  // Should be overridden: Parameter is not excluded
471  'key322' => 'value322Overruled',
472  // Shouldn't be set: Parameter doesn't exist in source array and is not forced
473  'key323' => 'value323Overruled'
474  ]
475  ]
476  ];
477  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2Overruled&key3[key32][key322]=value322Overruled');
478  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments);
479  $this->assertEquals($expectedResult, $actualResult);
480  }
481 
486  {
487  $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
488  $this->returnValue('key1=value1&key2=value2&key3[key31]=value31&key3[key32][key321]=value321&key3[key32][key322]=value322')
489  );
490  $_POST = [
491  'key1' => 'value1',
492  'key2' => 'value2',
493  'key3' => [
494  'key31' => 'value31',
495  'key32' => [
496  'key321' => 'value321',
497  'key322' => 'value322'
498  ]
499  ]
500  ];
501  $getQueryArgumentsConfiguration = [];
502  $getQueryArgumentsConfiguration['exclude'] = [];
503  $getQueryArgumentsConfiguration['exclude'][] = 'key1';
504  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
505  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
506  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key322]';
507  $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
508  $overruleArguments = [
509  // Should be overridden
510  'key2' => 'value2Overruled',
511  'key3' => [
512  'key32' => [
513  // Should be set: Parameter is excluded but forced
514  'key321' => 'value321Overruled',
515  // Should be set: Parameter doesn't exist in source array but is forced
516  'key323' => 'value323Overruled'
517  ]
518  ]
519  ];
520  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2Overruled&key3[key32][key321]=value321Overruled&key3[key32][key323]=value323Overruled');
521  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments, true);
522  $this->assertEquals($expectedResult, $actualResult);
523  $getQueryArgumentsConfiguration['method'] = 'POST';
524  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments, true);
525  $this->assertEquals($expectedResult, $actualResult);
526  }
527 
532  {
533  $_POST = [
534  'key1' => 'POST1',
535  'key2' => 'POST2',
536  'key3' => [
537  'key31' => 'POST31',
538  'key32' => 'POST32',
539  'key33' => [
540  'key331' => 'POST331',
541  'key332' => 'POST332',
542  ]
543  ]
544  ];
545  $_GET = [
546  'key2' => 'GET2',
547  'key3' => [
548  'key32' => 'GET32',
549  'key33' => [
550  'key331' => 'GET331',
551  ]
552  ]
553  ];
554  $getQueryArgumentsConfiguration = [];
555  $getQueryArgumentsConfiguration['method'] = 'POST,GET';
556  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key1=POST1&key2=GET2&key3[key31]=POST31&key3[key32]=GET32&key3[key33][key331]=GET331&key3[key33][key332]=POST332');
557  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
558  $this->assertEquals($expectedResult, $actualResult);
559  }
560 
565  {
566  $_GET = [
567  'key1' => 'GET1',
568  'key2' => 'GET2',
569  'key3' => [
570  'key31' => 'GET31',
571  'key32' => 'GET32',
572  'key33' => [
573  'key331' => 'GET331',
574  'key332' => 'GET332',
575  ]
576  ]
577  ];
578  $_POST = [
579  'key2' => 'POST2',
580  'key3' => [
581  'key32' => 'POST32',
582  'key33' => [
583  'key331' => 'POST331',
584  ]
585  ]
586  ];
587  $getQueryArgumentsConfiguration = [];
588  $getQueryArgumentsConfiguration['method'] = 'GET,POST';
589  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key1=GET1&key2=POST2&key3[key31]=GET31&key3[key32]=POST32&key3[key33][key331]=POST331&key3[key33][key332]=GET332');
590  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
591  $this->assertEquals($expectedResult, $actualResult);
592  }
593 
600  private function rawUrlEncodeSquareBracketsInUrl($string)
601  {
602  return str_replace(['[', ']'], ['%5B', '%5D'], $string);
603  }
604 
606  // Tests concerning crop
608 
611  public function cropIsMultibyteSafe()
612  {
613  $this->assertEquals('бла', $this->subject->crop('бла', '3|...'));
614  }
615 
617 
619  // Tests concerning cropHTML
621 
629  public function cropHTMLDataProvider()
630  {
631  $plainText = 'Kasper Sk' . chr(229) . 'rh' . chr(248)
632  . 'j implemented the original version of the crop function.';
633  $textWithMarkup = '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
634  . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong> the '
635  . 'original version of the crop function.';
636  $textWithEntities = 'Kasper Sk&aring;rh&oslash;j implemented the; '
637  . 'original ' . 'version of the crop function.';
638  $textWithLinebreaks = "Lorem ipsum dolor sit amet,\n"
639  . "consetetur sadipscing elitr,\n"
640  . 'sed diam nonumy eirmod tempor invidunt ut labore e'
641  . 't dolore magna aliquyam';
642 
643  return [
644  'plain text; 11|...' => [
645  'Kasper Sk' . chr(229) . 'r...',
646  $plainText, '11|...',
647  ],
648  'plain text; -58|...' => [
649  '...h' . chr(248) . 'j implemented the original version of '
650  . 'the crop function.',
651  $plainText, '-58|...',
652  ],
653  'plain text; 4|...|1' => [
654  'Kasp...',
655  $plainText, '4|...|1',
656  ],
657  'plain text; 20|...|1' => [
658  'Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j...',
659  $plainText, '20|...|1',
660  ],
661  'plain text; -5|...|1' => [
662  '...tion.',
663  $plainText, '-5|...|1',
664  ],
665  'plain text; -49|...|1' => [
666  '...the original version of the crop function.',
667  $plainText, '-49|...|1',
668  ],
669  'text with markup; 11|...' => [
670  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
671  . chr(229) . 'r...</a></strong>',
672  $textWithMarkup, '11|...',
673  ],
674  'text with markup; 13|...' => [
675  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
676  . chr(229) . 'rh' . chr(248) . '...</a></strong>',
677  $textWithMarkup, '13|...',
678  ],
679  'text with markup; 14|...' => [
680  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
681  . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>',
682  $textWithMarkup, '14|...',
683  ],
684  'text with markup; 15|...' => [
685  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
686  . chr(229) . 'rh' . chr(248) . 'j</a> ...</strong>',
687  $textWithMarkup, '15|...',
688  ],
689  'text with markup; 29|...' => [
690  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
691  . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong> '
692  . 'th...',
693  $textWithMarkup, '29|...',
694  ],
695  'text with markup; -58|...' => [
696  '<strong><a href="mailto:kasper@typo3.org">...h' . chr(248)
697  . 'j</a> implemented</strong> the original version of the crop '
698  . 'function.',
699  $textWithMarkup, '-58|...',
700  ],
701  'text with markup 4|...|1' => [
702  '<strong><a href="mailto:kasper@typo3.org">Kasp...</a>'
703  . '</strong>',
704  $textWithMarkup, '4|...|1',
705  ],
706  'text with markup; 11|...|1' => [
707  '<strong><a href="mailto:kasper@typo3.org">Kasper...</a>'
708  . '</strong>',
709  $textWithMarkup, '11|...|1',
710  ],
711  'text with markup; 13|...|1' => [
712  '<strong><a href="mailto:kasper@typo3.org">Kasper...</a>'
713  . '</strong>',
714  $textWithMarkup, '13|...|1',
715  ],
716  'text with markup; 14|...|1' => [
717  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
718  . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>',
719  $textWithMarkup, '14|...|1',
720  ],
721  'text with markup; 15|...|1' => [
722  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
723  . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>',
724  $textWithMarkup, '15|...|1',
725  ],
726  'text with markup; 29|...|1' => [
727  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
728  . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong>...',
729  $textWithMarkup, '29|...|1',
730  ],
731  'text with markup; -66|...|1' => [
732  '<strong><a href="mailto:kasper@typo3.org">...Sk' . chr(229)
733  . 'rh' . chr(248) . 'j</a> implemented</strong> the original v'
734  . 'ersion of the crop function.',
735  $textWithMarkup, '-66|...|1',
736  ],
737  'text with entities 9|...' => [
738  'Kasper Sk...',
739  $textWithEntities, '9|...',
740  ],
741  'text with entities 10|...' => [
742  'Kasper Sk&aring;...',
743  $textWithEntities, '10|...',
744  ],
745  'text with entities 11|...' => [
746  'Kasper Sk&aring;r...',
747  $textWithEntities, '11|...',
748  ],
749  'text with entities 13|...' => [
750  'Kasper Sk&aring;rh&oslash;...',
751  $textWithEntities, '13|...',
752  ],
753  'text with entities 14|...' => [
754  'Kasper Sk&aring;rh&oslash;j...',
755  $textWithEntities, '14|...',
756  ],
757  'text with entities 15|...' => [
758  'Kasper Sk&aring;rh&oslash;j ...',
759  $textWithEntities, '15|...',
760  ],
761  'text with entities 16|...' => [
762  'Kasper Sk&aring;rh&oslash;j i...',
763  $textWithEntities, '16|...',
764  ],
765  'text with entities -57|...' => [
766  '...j implemented the; original version of the crop function.',
767  $textWithEntities, '-57|...',
768  ],
769  'text with entities -58|...' => [
770  '...&oslash;j implemented the; original version of the crop '
771  . 'function.',
772  $textWithEntities, '-58|...',
773  ],
774  'text with entities -59|...' => [
775  '...h&oslash;j implemented the; original version of the crop '
776  . 'function.',
777  $textWithEntities, '-59|...',
778  ],
779  'text with entities 4|...|1' => [
780  'Kasp...',
781  $textWithEntities, '4|...|1',
782  ],
783  'text with entities 9|...|1' => [
784  'Kasper...',
785  $textWithEntities, '9|...|1',
786  ],
787  'text with entities 10|...|1' => [
788  'Kasper...',
789  $textWithEntities, '10|...|1',
790  ],
791  'text with entities 11|...|1' => [
792  'Kasper...',
793  $textWithEntities, '11|...|1',
794  ],
795  'text with entities 13|...|1' => [
796  'Kasper...',
797  $textWithEntities, '13|...|1',
798  ],
799  'text with entities 14|...|1' => [
800  'Kasper Sk&aring;rh&oslash;j...',
801  $textWithEntities, '14|...|1',
802  ],
803  'text with entities 15|...|1' => [
804  'Kasper Sk&aring;rh&oslash;j...',
805  $textWithEntities, '15|...|1',
806  ],
807  'text with entities 16|...|1' => [
808  'Kasper Sk&aring;rh&oslash;j...',
809  $textWithEntities, '16|...|1',
810  ],
811  'text with entities -57|...|1' => [
812  '...implemented the; original version of the crop function.',
813  $textWithEntities, '-57|...|1',
814  ],
815  'text with entities -58|...|1' => [
816  '...implemented the; original version of the crop function.',
817  $textWithEntities, '-58|...|1',
818  ],
819  'text with entities -59|...|1' => [
820  '...implemented the; original version of the crop function.',
821  $textWithEntities, '-59|...|1',
822  ],
823  'text with dash in html-element 28|...|1' => [
824  'Some text with a link to <link email.address@example.org - '
825  . 'mail "Open email window">my...</link>',
826  'Some text with a link to <link email.address@example.org - m'
827  . 'ail "Open email window">my email.address@example.org<'
828  . '/link> and text after it',
829  '28|...|1',
830  ],
831  'html elements with dashes in attributes' => [
832  '<em data-foo="x">foobar</em>foo',
833  '<em data-foo="x">foobar</em>foobaz',
834  '9',
835  ],
836  'html elements with iframe embedded 24|...|1' => [
837  'Text with iframe <iframe src="//what.ever/"></iframe> and...',
838  'Text with iframe <iframe src="//what.ever/">'
839  . '</iframe> and text after it',
840  '24|...|1',
841  ],
842  'html elements with script tag embedded 24|...|1' => [
843  'Text with script <script>alert(\'foo\');</script> and...',
844  'Text with script <script>alert(\'foo\');</script> '
845  . 'and text after it',
846  '24|...|1',
847  ],
848  'text with linebreaks' => [
849  "Lorem ipsum dolor sit amet,\nconsetetur sadipscing elitr,\ns"
850  . 'ed diam nonumy eirmod tempor invidunt ut labore e'
851  . 't dolore magna',
852  $textWithLinebreaks, '121',
853  ],
854  ];
855  }
856 
866  public function cropHTML($expect, $content, $conf)
867  {
868  $this->handleCharset($content, $expect);
869  $this->assertSame(
870  $expect,
871  $this->subject->cropHTML($content, $conf)
872  );
873  }
874 
880  public function roundDataProvider()
881  {
882  return [
883  // floats
884  'down' => [1.0, 1.11, []],
885  'up' => [2.0, 1.51, []],
886  'rounds up from x.50' => [2.0, 1.50, []],
887  'down with decimals' => [0.12, 0.1231, ['decimals' => 2]],
888  'up with decimals' => [0.13, 0.1251, ['decimals' => 2]],
889  'ceil' => [1.0, 0.11, ['roundType' => 'ceil']],
890  'ceil does not accept decimals' => [
891  1.0, 0.111, [
892  'roundType' => 'ceil',
893  'decimals' => 2,
894  ],
895  ],
896  'floor' => [2.0, 2.99, ['roundType' => 'floor']],
897  'floor does not accept decimals' => [
898  2.0, 2.999, [
899  'roundType' => 'floor',
900  'decimals' => 2,
901  ],
902  ],
903  'round, down' => [1.0, 1.11, ['roundType' => 'round']],
904  'round, up' => [2.0, 1.55, ['roundType' => 'round']],
905  'round does accept decimals' => [
906  5.56, 5.5555, [
907  'roundType' => 'round',
908  'decimals' => 2,
909  ],
910  ],
911  // strings
912  'emtpy string' => [0.0, '', []],
913  'word string' => [0.0, 'word', []],
914  'float string' => [1.0, '1.123456789', []],
915  // other types
916  'null' => [0.0, null, []],
917  'false' => [0.0, false, []],
918  'true' => [1.0, true, []]
919  ];
920  }
921 
939  public function round($expect, $content, $conf)
940  {
941  $this->assertSame(
942  $expect,
943  $this->subject->_call('round', $content, $conf)
944  );
945  }
946 
951  {
952  $stdWrapConfiguration = [
953  'noTrimWrap' => '|| 123|',
954  'stdWrap.' => [
955  'wrap' => '<b>|</b>'
956  ]
957  ];
958  $this->assertSame(
959  '<b>Test</b> 123',
960  $this->subject->stdWrap('Test', $stdWrapConfiguration)
961  );
962  }
963 
968  {
969  $stdWrapConfiguration = [
970  'append' => 'TEXT',
971  'append.' => [
972  'data' => 'register:Counter'
973  ],
974  'stdWrap.' => [
975  'append' => 'LOAD_REGISTER',
976  'append.' => [
977  'Counter.' => [
978  'prioriCalc' => 'intval',
979  'cObject' => 'TEXT',
980  'cObject.' => [
981  'data' => 'register:Counter',
982  'wrap' => '|+1',
983  ]
984  ]
985  ]
986  ]
987  ];
988  $this->assertSame(
989  'Counter:1',
990  $this->subject->stdWrap('Counter:', $stdWrapConfiguration)
991  );
992  }
993 
999  public function numberFormatDataProvider()
1000  {
1001  return [
1002  'testing decimals' => [
1003  '0.80', 0.8,
1004  ['decimals' => 2]
1005  ],
1006  'testing decimals with input as string' => [
1007  '0.80', '0.8',
1008  ['decimals' => 2]
1009  ],
1010  'testing dec_point' => [
1011  '0,8', 0.8,
1012  ['decimals' => 1, 'dec_point' => ',']
1013  ],
1014  'testing thousands_sep' => [
1015  '1.000', 999.99,
1016  [
1017  'decimals' => 0,
1018  'thousands_sep.' => ['char' => 46]
1019  ]
1020  ],
1021  'testing mixture' => [
1022  '1.281.731,5', 1281731.45,
1023  [
1024  'decimals' => 1,
1025  'dec_point.' => ['char' => 44],
1026  'thousands_sep.' => ['char' => 46]
1027  ]
1028  ]
1029  ];
1030  }
1031 
1038  public function numberFormat($expects, $content, $conf)
1039  {
1040  $this->assertSame(
1041  $expects,
1042  $this->subject->numberFormat($content, $conf)
1043  );
1044  }
1045 
1051  public function replacementDataProvider()
1052  {
1053  return [
1054  'multiple replacements, including regex' => [
1055  'There is an animal, an animal and an animal around the block! Yeah!',
1056  'There_is_a_cat,_a_dog_and_a_tiger_in_da_hood!_Yeah!',
1057  [
1058  '20.' => [
1059  'search' => '_',
1060  'replace.' => ['char' => '32']
1061  ],
1062  '120.' => [
1063  'search' => 'in da hood',
1064  'replace' => 'around the block'
1065  ],
1066  '130.' => [
1067  'search' => '#a (Cat|Dog|Tiger)#i',
1068  'replace' => 'an animal',
1069  'useRegExp' => '1'
1070  ]
1071  ]
1072  ],
1073  'replacement with optionSplit, normal pattern' => [
1074  'There1is2a3cat,3a3dog3and3a3tiger3in3da3hood!3Yeah!',
1075  'There_is_a_cat,_a_dog_and_a_tiger_in_da_hood!_Yeah!',
1076  [
1077  '10.' => [
1078  'search' => '_',
1079  'replace' => '1 || 2 || 3',
1080  'useOptionSplitReplace' => '1'
1081  ]
1082  ]
1083  ],
1084  'replacement with optionSplit, using regex' => [
1085  'There is a tiny cat, a midsized dog and a big tiger in da hood! Yeah!',
1086  'There is a cat, a dog and a tiger in da hood! Yeah!',
1087  [
1088  '10.' => [
1089  'search' => '#(a) (Cat|Dog|Tiger)#i',
1090  'replace' => '${1} tiny ${2} || ${1} midsized ${2} || ${1} big ${2}',
1091  'useOptionSplitReplace' => '1',
1092  'useRegExp' => '1'
1093  ]
1094  ]
1095  ]
1096  ];
1097  }
1098 
1108  public function replacement($expects, $content, $conf)
1109  {
1110  $this->assertSame(
1111  $expects,
1112  $this->subject->_call('replacement', $content, $conf)
1113  );
1114  }
1115 
1121  public function calcAgeDataProvider()
1122  {
1123  return [
1124  'minutes' => [
1125  '2 min', 120, ' min| hrs| days| yrs',
1126  ],
1127  'hours' => [
1128  '2 hrs', 7200, ' min| hrs| days| yrs',
1129  ],
1130  'days' => [
1131  '7 days', 604800, ' min| hrs| days| yrs',
1132  ],
1133  'day with provided singular labels' => [
1134  '1 day', 86400, ' min| hrs| days| yrs| min| hour| day| year',
1135  ],
1136  'years' => [
1137  '45 yrs', 1417997800, ' min| hrs| days| yrs',
1138  ],
1139  'different labels' => [
1140  '2 Minutes', 120, ' Minutes| Hrs| Days| Yrs',
1141  ],
1142  'negative values' => [
1143  '-7 days', -604800, ' min| hrs| days| yrs',
1144  ],
1145  'default label values for wrong label input' => [
1146  '2 min', 121, 10,
1147  ],
1148  'default singular label values for wrong label input' => [
1149  '1 year', 31536000, 10,
1150  ]
1151  ];
1152  }
1153 
1163  public function calcAge($expect, $timestamp, $labels)
1164  {
1165  $this->assertSame(
1166  $expect,
1167  $this->subject->calcAge($timestamp, $labels)
1168  );
1169  }
1170 
1175  {
1176  return [
1177  'Prevent silent bool conversion' => [
1178  '1+1',
1179  [
1180  'prioriCalc.' => [
1181  'wrap' => '|',
1182  ],
1183  ],
1184  '1+1',
1185  ],
1186  ];
1187  }
1188 
1196  public function stdWrapReturnsExpectation($content, array $configuration, $expectation)
1197  {
1198  $this->assertSame($expectation, $this->subject->stdWrap($content, $configuration));
1199  }
1200 
1206  public function substringDataProvider()
1207  {
1208  return [
1209  'sub -1' => ['g', 'substring', '-1'],
1210  'sub -1,0' => ['g', 'substring', '-1,0'],
1211  'sub -1,-1' => ['', 'substring', '-1,-1'],
1212  'sub -1,1' => ['g', 'substring', '-1,1'],
1213  'sub 0' => ['substring', 'substring', '0'],
1214  'sub 0,0' => ['substring', 'substring', '0,0'],
1215  'sub 0,-1' => ['substrin', 'substring', '0,-1'],
1216  'sub 0,1' => ['s', 'substring', '0,1'],
1217  'sub 1' => ['ubstring', 'substring', '1'],
1218  'sub 1,0' => ['ubstring', 'substring', '1,0'],
1219  'sub 1,-1' => ['ubstrin', 'substring', '1,-1'],
1220  'sub 1,1' => ['u', 'substring', '1,1'],
1221  'sub' => ['substring', 'substring', ''],
1222  ];
1223  }
1224 
1234  public function substring($expect, $content, $conf)
1235  {
1236  $this->assertSame($expect, $this->subject->substring($content, $conf));
1237  }
1238 
1240  // Tests concerning getData()
1242 
1247  {
1248  return [
1249  'Value in get-data' => ['onlyInGet', 'GetValue'],
1250  'Value in post-data' => ['onlyInPost', 'PostValue'],
1251  'Value in post-data overriding get-data' => ['inGetAndPost', 'ValueInPost'],
1252  ];
1253  }
1254 
1261  public function getDataWithTypeGp($key, $expectedValue)
1262  {
1263  $_GET = [
1264  'onlyInGet' => 'GetValue',
1265  'inGetAndPost' => 'ValueInGet',
1266  ];
1267  $_POST = [
1268  'onlyInPost' => 'PostValue',
1269  'inGetAndPost' => 'ValueInPost',
1270  ];
1271  $this->assertEquals($expectedValue, $this->subject->getData('gp:' . $key));
1272  }
1273 
1279  public function getDataWithTypeTsfe()
1280  {
1281  $this->assertEquals($GLOBALS['TSFE']->metaCharset, $this->subject->getData('tsfe:metaCharset'));
1282  }
1283 
1289  public function getDataWithTypeGetenv()
1290  {
1291  $envName = $this->getUniqueId('frontendtest');
1292  $value = $this->getUniqueId('someValue');
1293  putenv($envName . '=' . $value);
1294  $this->assertEquals($value, $this->subject->getData('getenv:' . $envName));
1295  }
1296 
1302  public function getDataWithTypeGetindpenv()
1303  {
1304  $this->subject->expects($this->once())->method('getEnvironmentVariable')
1305  ->with($this->equalTo('SCRIPT_FILENAME'))->will($this->returnValue('dummyPath'));
1306  $this->assertEquals('dummyPath', $this->subject->getData('getindpenv:SCRIPT_FILENAME'));
1307  }
1308 
1314  public function getDataWithTypeField()
1315  {
1316  $key = 'someKey';
1317  $value = 'someValue';
1318  $field = [$key => $value];
1319 
1320  $this->assertEquals($value, $this->subject->getData('field:' . $key, $field));
1321  }
1322 
1330  {
1331  $key = 'somekey|level1|level2';
1332  $value = 'somevalue';
1333  $field = ['somekey' => ['level1' => ['level2' => 'somevalue']]];
1334 
1335  $this->assertEquals($value, $this->subject->getData('field:' . $key, $field));
1336  }
1337 
1344  {
1345  $uid = $this->getUniqueId();
1346  $file = $this->createMock(File::class);
1347  $file->expects($this->once())->method('getUid')->will($this->returnValue($uid));
1348  $this->subject->setCurrentFile($file);
1349  $this->assertEquals($uid, $this->subject->getData('file:current:uid'));
1350  }
1351 
1357  public function getDataWithTypeParameters()
1358  {
1359  $key = $this->getUniqueId('someKey');
1360  $value = $this->getUniqueId('someValue');
1361  $this->subject->parameters[$key] = $value;
1362 
1363  $this->assertEquals($value, $this->subject->getData('parameters:' . $key));
1364  }
1365 
1371  public function getDataWithTypeRegister()
1372  {
1373  $key = $this->getUniqueId('someKey');
1374  $value = $this->getUniqueId('someValue');
1375  $GLOBALS['TSFE']->register[$key] = $value;
1376 
1377  $this->assertEquals($value, $this->subject->getData('register:' . $key));
1378  }
1379 
1385  public function getDataWithTypeSession()
1386  {
1387  $frontendUser = $this->getMockBuilder(FrontendUserAuthentication::class)
1388  ->setMethods(['getSessionData'])
1389  ->getMock();
1390  $frontendUser->expects($this->once())->method('getSessionData')->with('myext')->willReturn([
1391  'mydata' => [
1392  'someValue' => 42,
1393  ],
1394  ]);
1395  $GLOBALS['TSFE']->fe_user = $frontendUser;
1396 
1397  $this->assertEquals(42, $this->subject->getData('session:myext|mydata|someValue'));
1398  }
1399 
1405  public function getDataWithTypeLevel()
1406  {
1407  $rootline = [
1408  0 => ['uid' => 1, 'title' => 'title1'],
1409  1 => ['uid' => 2, 'title' => 'title2'],
1410  2 => ['uid' => 3, 'title' => 'title3'],
1411  ];
1412 
1413  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1414  $this->assertEquals(2, $this->subject->getData('level'));
1415  }
1416 
1422  public function getDataWithTypeGlobal()
1423  {
1424  $this->assertEquals($GLOBALS['TSFE']->metaCharset, $this->subject->getData('global:TSFE|metaCharset'));
1425  }
1426 
1432  public function getDataWithTypeLeveltitle()
1433  {
1434  $rootline = [
1435  0 => ['uid' => 1, 'title' => 'title1'],
1436  1 => ['uid' => 2, 'title' => 'title2'],
1437  2 => ['uid' => 3, 'title' => ''],
1438  ];
1439 
1440  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1441  $this->assertEquals('', $this->subject->getData('leveltitle:-1'));
1442  // since "title3" is not set, it will slide to "title2"
1443  $this->assertEquals('title2', $this->subject->getData('leveltitle:-1,slide'));
1444  }
1445 
1451  public function getDataWithTypeLevelmedia()
1452  {
1453  $rootline = [
1454  0 => ['uid' => 1, 'title' => 'title1', 'media' => 'media1'],
1455  1 => ['uid' => 2, 'title' => 'title2', 'media' => 'media2'],
1456  2 => ['uid' => 3, 'title' => 'title3', 'media' => ''],
1457  ];
1458 
1459  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1460  $this->assertEquals('', $this->subject->getData('levelmedia:-1'));
1461  // since "title3" is not set, it will slide to "title2"
1462  $this->assertEquals('media2', $this->subject->getData('levelmedia:-1,slide'));
1463  }
1464 
1470  public function getDataWithTypeLeveluid()
1471  {
1472  $rootline = [
1473  0 => ['uid' => 1, 'title' => 'title1'],
1474  1 => ['uid' => 2, 'title' => 'title2'],
1475  2 => ['uid' => 3, 'title' => 'title3'],
1476  ];
1477 
1478  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1479  $this->assertEquals(3, $this->subject->getData('leveluid:-1'));
1480  // every element will have a uid - so adding slide doesn't really make sense, just for completeness
1481  $this->assertEquals(3, $this->subject->getData('leveluid:-1,slide'));
1482  }
1483 
1489  public function getDataWithTypeLevelfield()
1490  {
1491  $rootline = [
1492  0 => ['uid' => 1, 'title' => 'title1', 'testfield' => 'field1'],
1493  1 => ['uid' => 2, 'title' => 'title2', 'testfield' => 'field2'],
1494  2 => ['uid' => 3, 'title' => 'title3', 'testfield' => ''],
1495  ];
1496 
1497  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1498  $this->assertEquals('', $this->subject->getData('levelfield:-1,testfield'));
1499  $this->assertEquals('field2', $this->subject->getData('levelfield:-1,testfield,slide'));
1500  }
1501 
1508  {
1509  $rootline1 = [
1510  0 => ['uid' => 1, 'title' => 'title1', 'testfield' => 'field1'],
1511  ];
1512  $rootline2 = [
1513  0 => ['uid' => 1, 'title' => 'title1', 'testfield' => 'field1'],
1514  1 => ['uid' => 2, 'title' => 'title2', 'testfield' => 'field2'],
1515  2 => ['uid' => 3, 'title' => 'title3', 'testfield' => 'field3'],
1516  ];
1517 
1518  $GLOBALS['TSFE']->tmpl->rootLine = $rootline1;
1519  $GLOBALS['TSFE']->rootLine = $rootline2;
1520  $this->assertEquals('field2', $this->subject->getData('fullrootline:-1,testfield'));
1521  }
1522 
1528  public function getDataWithTypeDate()
1529  {
1530  $format = 'Y-M-D';
1531  $defaultFormat = 'd/m Y';
1532 
1533  $this->assertEquals(date($format, $GLOBALS['EXEC_TIME']), $this->subject->getData('date:' . $format));
1534  $this->assertEquals(date($defaultFormat, $GLOBALS['EXEC_TIME']), $this->subject->getData('date'));
1535  }
1536 
1542  public function getDataWithTypePage()
1543  {
1544  $uid = rand();
1545  $GLOBALS['TSFE']->page['uid'] = $uid;
1546  $this->assertEquals($uid, $this->subject->getData('page:uid'));
1547  }
1548 
1554  public function getDataWithTypeCurrent()
1555  {
1556  $key = $this->getUniqueId('someKey');
1557  $value = $this->getUniqueId('someValue');
1558  $this->subject->data[$key] = $value;
1559  $this->subject->currentValKey = $key;
1560  $this->assertEquals($value, $this->subject->getData('current'));
1561  }
1562 
1568  public function getDataWithTypeDb()
1569  {
1570  $dummyRecord = ['uid' => 5, 'title' => 'someTitle'];
1571 
1572  $GLOBALS['TSFE']->sys_page->expects($this->atLeastOnce())->method('getRawRecord')->with('tt_content', '106')->will($this->returnValue($dummyRecord));
1573  $this->assertEquals($dummyRecord['title'], $this->subject->getData('db:tt_content:106:title'));
1574  }
1575 
1581  public function getDataWithTypeLll()
1582  {
1583  $key = $this->getUniqueId('someKey');
1584  $value = $this->getUniqueId('someValue');
1585  $language = $this->getUniqueId('someLanguage');
1586  $GLOBALS['TSFE']->LL_labels_cache[$language]['LLL:' . $key] = $value;
1587  $GLOBALS['TSFE']->lang = $language;
1588 
1589  $this->assertEquals($value, $this->subject->getData('lll:' . $key));
1590  }
1591 
1597  public function getDataWithTypePath()
1598  {
1599  $filenameIn = $this->getUniqueId('someValue');
1600  $filenameOut = $this->getUniqueId('someValue');
1601  $this->templateServiceMock->expects($this->atLeastOnce())->method('getFileName')->with($filenameIn)->will($this->returnValue($filenameOut));
1602  $this->assertEquals($filenameOut, $this->subject->getData('path:' . $filenameIn));
1603  }
1604 
1611  {
1612  $recordNumber = rand();
1613  $this->subject->parentRecordNumber = $recordNumber;
1614  $this->assertEquals($recordNumber, $this->subject->getData('cobj:parentRecordNumber'));
1615  }
1616 
1623  {
1624  $rootline = [
1625  0 => ['uid' => 1, 'title' => 'title1'],
1626  1 => ['uid' => 2, 'title' => 'title2'],
1627  2 => ['uid' => 3, 'title' => ''],
1628  ];
1629  $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)';
1630  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1631 
1633  $result = $this->subject->getData('debug:rootLine');
1634  $cleanedResult = str_replace("\r", '', $result);
1635  $cleanedResult = str_replace("\n", '', $cleanedResult);
1636  $cleanedResult = str_replace("\t", '', $cleanedResult);
1637  $cleanedResult = str_replace(' ', '', $cleanedResult);
1638 
1639  $this->assertEquals($expectedResult, $cleanedResult);
1640  }
1641 
1648  {
1649  $rootline = [
1650  0 => ['uid' => 1, 'title' => 'title1'],
1651  1 => ['uid' => 2, 'title' => 'title2'],
1652  2 => ['uid' => 3, 'title' => ''],
1653  ];
1654  $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)';
1655  $GLOBALS['TSFE']->rootLine = $rootline;
1656 
1658  $result = $this->subject->getData('debug:fullRootLine');
1659  $cleanedResult = str_replace("\r", '', $result);
1660  $cleanedResult = str_replace("\n", '', $cleanedResult);
1661  $cleanedResult = str_replace("\t", '', $cleanedResult);
1662  $cleanedResult = str_replace(' ', '', $cleanedResult);
1663 
1664  $this->assertEquals($expectedResult, $cleanedResult);
1665  }
1666 
1672  public function getDataWithTypeDebugData()
1673  {
1674  $key = $this->getUniqueId('someKey');
1675  $value = $this->getUniqueId('someValue');
1676  $this->subject->data = [$key => $value];
1677 
1678  $expectedResult = 'array(1item)' . $key . '=>"' . $value . '"(' . strlen($value) . 'chars)';
1679 
1681  $result = $this->subject->getData('debug:data');
1682  $cleanedResult = str_replace("\r", '', $result);
1683  $cleanedResult = str_replace("\n", '', $cleanedResult);
1684  $cleanedResult = str_replace("\t", '', $cleanedResult);
1685  $cleanedResult = str_replace(' ', '', $cleanedResult);
1686 
1687  $this->assertEquals($expectedResult, $cleanedResult);
1688  }
1689 
1696  {
1697  $key = $this->getUniqueId('someKey');
1698  $value = $this->getUniqueId('someValue');
1699  $GLOBALS['TSFE']->register = [$key => $value];
1700 
1701  $expectedResult = 'array(1item)' . $key . '=>"' . $value . '"(' . strlen($value) . 'chars)';
1702 
1704  $result = $this->subject->getData('debug:register');
1705  $cleanedResult = str_replace("\r", '', $result);
1706  $cleanedResult = str_replace("\n", '', $cleanedResult);
1707  $cleanedResult = str_replace("\t", '', $cleanedResult);
1708  $cleanedResult = str_replace(' ', '', $cleanedResult);
1709 
1710  $this->assertEquals($expectedResult, $cleanedResult);
1711  }
1712 
1718  public function getDataWithTypeDebugPage()
1719  {
1720  $uid = rand();
1721  $GLOBALS['TSFE']->page = ['uid' => $uid];
1722 
1723  $expectedResult = 'array(1item)uid=>' . $uid . '(integer)';
1724 
1726  $result = $this->subject->getData('debug:page');
1727  $cleanedResult = str_replace("\r", '', $result);
1728  $cleanedResult = str_replace("\n", '', $cleanedResult);
1729  $cleanedResult = str_replace("\t", '', $cleanedResult);
1730  $cleanedResult = str_replace(' ', '', $cleanedResult);
1731 
1732  $this->assertEquals($expectedResult, $cleanedResult);
1733  }
1734 
1739  {
1740  $aTagParams = $this->subject->getATagParams(['ATagParams' => 'data-test="testdata"']);
1741  $this->assertEquals(' data-test="testdata"', $aTagParams);
1742  }
1743 
1748  {
1749  $GLOBALS['TSFE']->ATagParams = 'data-global="dataglobal"';
1750  $aTagParams = $this->subject->getATagParams(['ATagParams' => 'data-test="testdata"']);
1751  $this->assertEquals(' data-global="dataglobal" data-test="testdata"', $aTagParams);
1752  }
1753 
1758  {
1759  // make sure global ATagParams are empty
1760  $GLOBALS['TSFE']->ATagParams = '';
1761  $aTagParams = $this->subject->getATagParams(['ATagParams' => '']);
1762  $this->assertEquals('', $aTagParams);
1763  }
1764 
1769  {
1770  return [
1771  [null, null],
1772  ['', null],
1773  ['', []],
1774  ['fooo', ['foo' => 'bar']]
1775  ];
1776  }
1777 
1787  {
1788  $defaultImgTagTemplate = '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>';
1789  $result = $this->subject->getImageTagTemplate($key, $configuration);
1790  $this->assertEquals($result, $defaultImgTagTemplate);
1791  }
1792 
1797  {
1798  return [
1799  [
1800  'foo',
1801  [
1802  'layout.' => [
1803  'foo.' => [
1804  'element' => '<img src="###SRC###" srcset="###SOURCES###" ###PARAMS### ###ALTPARAMS### ###FOOBAR######SELFCLOSINGTAGSLASH###>'
1805  ]
1806  ]
1807  ],
1808  '<img src="###SRC###" srcset="###SOURCES###" ###PARAMS### ###ALTPARAMS### ###FOOBAR######SELFCLOSINGTAGSLASH###>'
1809  ]
1810 
1811  ];
1812  }
1813 
1823  public function getImageTagTemplateReturnTemplateElementIdentifiedByKey($key, $configuration, $expectation)
1824  {
1825  $result = $this->subject->getImageTagTemplate($key, $configuration);
1826  $this->assertEquals($result, $expectation);
1827  }
1828 
1833  {
1834  return [
1835  [null, null, null],
1836  ['foo', null, null],
1837  ['foo', ['sourceCollection.' => 1], 'bar']
1838  ];
1839  }
1840 
1850  public function getImageSourceCollectionReturnsEmptyStringIfNoSourcesAreDefined($layoutKey, $configuration, $file)
1851  {
1852  $result = $this->subject->getImageSourceCollection($layoutKey, $configuration, $file);
1853  $this->assertSame($result, '');
1854  }
1855 
1861  public function getImageSourceCollectionRendersDefinedSources()
1862  {
1864  $cObj = $this->getMockBuilder(ContentObjectRenderer::class)
1865  ->setMethods(['stdWrap', 'getImgResource'])
1866  ->getMock();
1867 
1868  $cObj->start([], 'tt_content');
1869 
1870  $layoutKey = 'test';
1871 
1872  $configuration = [
1873  'layoutKey' => 'test',
1874  'layout.' => [
1875  'test.' => [
1876  'element' => '<img ###SRC### ###SRCCOLLECTION### ###SELFCLOSINGTAGSLASH###>',
1877  'source' => '---###SRC###---'
1878  ]
1879  ],
1880  'sourceCollection.' => [
1881  '1.' => [
1882  'width' => '200'
1883  ]
1884  ]
1885  ];
1886 
1887  $file = 'testImageName';
1888 
1889  // Avoid calling of stdWrap
1890  $cObj
1891  ->expects($this->any())
1892  ->method('stdWrap')
1893  ->will($this->returnArgument(0));
1894 
1895  // Avoid calling of imgResource
1896  $cObj
1897  ->expects($this->exactly(1))
1898  ->method('getImgResource')
1899  ->with($this->equalTo('testImageName'))
1900  ->will($this->returnValue([100, 100, null, 'bar']));
1901 
1902  $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
1903 
1904  $this->assertEquals('---bar---', $result);
1905  }
1906 
1914  {
1918  $sourceCollectionArray = [
1919  'small.' => [
1920  'width' => 200,
1921  'srcsetCandidate' => '600w',
1922  'mediaQuery' => '(max-device-width: 600px)',
1923  'dataKey' => 'small',
1924  ],
1925  'smallRetina.' => [
1926  'if.directReturn' => 0,
1927  'width' => 200,
1928  'pixelDensity' => '2',
1929  'srcsetCandidate' => '600w 2x',
1930  'mediaQuery' => '(max-device-width: 600px) AND (min-resolution: 192dpi)',
1931  'dataKey' => 'smallRetina',
1932  ]
1933  ];
1934  return [
1935  [
1936  'default',
1937  [
1938  'layoutKey' => 'default',
1939  'layout.' => [
1940  'default.' => [
1941  'element' => '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>',
1942  'source' => ''
1943  ]
1944  ],
1945  'sourceCollection.' => $sourceCollectionArray
1946  ]
1947  ],
1948  ];
1949  }
1950 
1959  public function getImageSourceCollectionRendersDefinedLayoutKeyDefault($layoutKey, $configuration)
1960  {
1962  $cObj = $this->getMockBuilder(ContentObjectRenderer::class)
1963  ->setMethods(['stdWrap', 'getImgResource'])
1964  ->getMock();
1965 
1966  $cObj->start([], 'tt_content');
1967 
1968  $file = 'testImageName';
1969 
1970  // Avoid calling of stdWrap
1971  $cObj
1972  ->expects($this->any())
1973  ->method('stdWrap')
1974  ->will($this->returnArgument(0));
1975 
1976  $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
1977 
1978  $this->assertEmpty($result);
1979  }
1980 
1988  {
1992  $sourceCollectionArray = [
1993  'small.' => [
1994  'width' => 200,
1995  'srcsetCandidate' => '600w',
1996  'mediaQuery' => '(max-device-width: 600px)',
1997  'dataKey' => 'small',
1998  ],
1999  'smallRetina.' => [
2000  'if.directReturn' => 1,
2001  'width' => 200,
2002  'pixelDensity' => '2',
2003  'srcsetCandidate' => '600w 2x',
2004  'mediaQuery' => '(max-device-width: 600px) AND (min-resolution: 192dpi)',
2005  'dataKey' => 'smallRetina',
2006  ]
2007  ];
2008  return [
2009  [
2010  'srcset',
2011  [
2012  'layoutKey' => 'srcset',
2013  'layout.' => [
2014  'srcset.' => [
2015  'element' => '<img src="###SRC###" srcset="###SOURCECOLLECTION###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
2016  'source' => '|*|###SRC### ###SRCSETCANDIDATE###,|*|###SRC### ###SRCSETCANDIDATE###'
2017  ]
2018  ],
2019  'sourceCollection.' => $sourceCollectionArray
2020  ],
2021  'xhtml_strict',
2022  'bar-file.jpg 600w,bar-file.jpg 600w 2x',
2023  ],
2024  [
2025  'picture',
2026  [
2027  'layoutKey' => 'picture',
2028  'layout.' => [
2029  'picture.' => [
2030  'element' => '<picture>###SOURCECOLLECTION###<img src="###SRC###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###></picture>',
2031  'source' => '<source src="###SRC###" media="###MEDIAQUERY###"###SELFCLOSINGTAGSLASH###>'
2032  ]
2033  ],
2034  'sourceCollection.' => $sourceCollectionArray,
2035  ],
2036  'xhtml_strict',
2037  '<source src="bar-file.jpg" media="(max-device-width: 600px)" /><source src="bar-file.jpg" media="(max-device-width: 600px) AND (min-resolution: 192dpi)" />',
2038  ],
2039  [
2040  'picture',
2041  [
2042  'layoutKey' => 'picture',
2043  'layout.' => [
2044  'picture.' => [
2045  'element' => '<picture>###SOURCECOLLECTION###<img src="###SRC###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###></picture>',
2046  'source' => '<source src="###SRC###" media="###MEDIAQUERY###"###SELFCLOSINGTAGSLASH###>'
2047  ]
2048  ],
2049  'sourceCollection.' => $sourceCollectionArray,
2050  ],
2051  '',
2052  '<source src="bar-file.jpg" media="(max-device-width: 600px)"><source src="bar-file.jpg" media="(max-device-width: 600px) AND (min-resolution: 192dpi)">',
2053  ],
2054  [
2055  'data',
2056  [
2057  'layoutKey' => 'data',
2058  'layout.' => [
2059  'data.' => [
2060  'element' => '<img src="###SRC###" ###SOURCECOLLECTION### ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
2061  'source' => 'data-###DATAKEY###="###SRC###"'
2062  ]
2063  ],
2064  'sourceCollection.' => $sourceCollectionArray
2065  ],
2066  'xhtml_strict',
2067  'data-small="bar-file.jpg"data-smallRetina="bar-file.jpg"',
2068  ],
2069  ];
2070  }
2071 
2082  public function getImageSourceCollectionRendersDefinedLayoutKeyData($layoutKey, $configuration, $xhtmlDoctype, $expectedHtml)
2083  {
2085  $cObj = $this->getMockBuilder(ContentObjectRenderer::class)
2086  ->setMethods(['stdWrap', 'getImgResource'])
2087  ->getMock();
2088 
2089  $cObj->start([], 'tt_content');
2090 
2091  $file = 'testImageName';
2092 
2093  $GLOBALS['TSFE']->xhtmlDoctype = $xhtmlDoctype;
2094 
2095  // Avoid calling of stdWrap
2096  $cObj
2097  ->expects($this->any())
2098  ->method('stdWrap')
2099  ->will($this->returnArgument(0));
2100 
2101  // Avoid calling of imgResource
2102  $cObj
2103  ->expects($this->exactly(2))
2104  ->method('getImgResource')
2105  ->with($this->equalTo('testImageName'))
2106  ->will($this->returnValue([100, 100, null, 'bar-file.jpg']));
2107 
2108  $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
2109 
2110  $this->assertEquals($expectedHtml, $result);
2111  }
2112 
2119  {
2120  $this->subject = $this->getAccessibleMock(
2121  ContentObjectRenderer::class,
2122  ['getResourceFactory', 'stdWrap', 'getImgResource']
2123  );
2124  $this->subject->start([], 'tt_content');
2125 
2126  // Avoid calling stdwrap and getImgResource
2127  $this->subject->expects($this->any())
2128  ->method('stdWrap')
2129  ->will($this->returnArgument(0));
2130 
2131  $this->subject->expects($this->any())
2132  ->method('getImgResource')
2133  ->will($this->returnValue([100, 100, null, 'bar-file.jpg']));
2134 
2135  $resourceFactory = $this->createMock(ResourceFactory::class);
2136  $this->subject->expects($this->any())->method('getResourceFactory')->will($this->returnValue($resourceFactory));
2137 
2138  $className = $this->getUniqueId('tx_coretest_getImageSourceCollectionHookCalled');
2139  $getImageSourceCollectionHookMock = $this->getMockBuilder(
2140  ContentObjectOneSourceCollectionHookInterface::class
2141  )
2142  ->setMethods(['getOneSourceCollection'])
2143  ->setMockClassName($className)
2144  ->getMock();
2145  GeneralUtility::addInstance($className, $getImageSourceCollectionHookMock);
2146  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'][] = $className;
2147 
2148  $getImageSourceCollectionHookMock
2149  ->expects($this->exactly(1))
2150  ->method('getOneSourceCollection')
2151  ->will($this->returnCallback([$this, 'isGetOneSourceCollectionCalledCallback']));
2152 
2153  $configuration = [
2154  'layoutKey' => 'data',
2155  'layout.' => [
2156  'data.' => [
2157  'element' => '<img src="###SRC###" ###SOURCECOLLECTION### ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
2158  'source' => 'data-###DATAKEY###="###SRC###"'
2159  ]
2160  ],
2161  'sourceCollection.' => [
2162  'small.' => [
2163  'width' => 200,
2164  'srcsetCandidate' => '600w',
2165  'mediaQuery' => '(max-device-width: 600px)',
2166  'dataKey' => 'small',
2167  ],
2168  ],
2169  ];
2170 
2171  $result = $this->subject->getImageSourceCollection('data', $configuration, $this->getUniqueId('testImage-'));
2172 
2173  $this->assertSame($result, 'isGetOneSourceCollectionCalledCallback');
2174  }
2175 
2186  public function isGetOneSourceCollectionCalledCallback($sourceRenderConfiguration, $sourceConfiguration, $oneSourceCollection, $parent)
2187  {
2188  $this->assertTrue(is_array($sourceRenderConfiguration));
2189  $this->assertTrue(is_array($sourceConfiguration));
2190  return 'isGetOneSourceCollectionCalledCallback';
2191  }
2192 
2197  {
2198  $this->expectException(\LogicException::class);
2199  $this->expectExceptionCode(1414513947);
2200  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2201  $this->subject->render($contentObjectFixture, []);
2202  }
2203 
2208  {
2209  $backupApplicationContext = GeneralUtility::getApplicationContext();
2211 
2212  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2213  $this->subject->render($contentObjectFixture, []);
2214 
2215  Fixtures\GeneralUtilityFixture::setApplicationContext($backupApplicationContext);
2216  }
2217 
2222  {
2223  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2224 
2225  $configuration = [
2226  'exceptionHandler' => '1'
2227  ];
2228  $this->subject->render($contentObjectFixture, $configuration);
2229  }
2230 
2235  {
2236  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2237 
2238  $this->frontendControllerMock->config['config']['contentObjectExceptionHandler'] = '1';
2239  $this->subject->render($contentObjectFixture, []);
2240  }
2241 
2246  {
2247  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2248  $this->expectException(\LogicException::class);
2249  $this->expectExceptionCode(1414513947);
2250  $this->frontendControllerMock->config['config']['contentObjectExceptionHandler'] = '1';
2251  $configuration = [
2252  'exceptionHandler' => '0'
2253  ];
2254  $this->subject->render($contentObjectFixture, $configuration);
2255  }
2256 
2261  {
2262  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2263 
2264  $configuration = [
2265  'exceptionHandler' => '1',
2266  'exceptionHandler.' => [
2267  'errorMessage' => 'New message for testing',
2268  ]
2269  ];
2270 
2271  $this->assertSame('New message for testing', $this->subject->render($contentObjectFixture, $configuration));
2272  }
2273 
2278  {
2279  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2280 
2281  $this->frontendControllerMock
2282  ->config['config']['contentObjectExceptionHandler.'] = [
2283  'errorMessage' => 'Global message for testing',
2284  ];
2285  $configuration = [
2286  'exceptionHandler' => '1',
2287  'exceptionHandler.' => [
2288  'errorMessage' => 'New message for testing',
2289  ]
2290  ];
2291 
2292  $this->assertSame('New message for testing', $this->subject->render($contentObjectFixture, $configuration));
2293  }
2294 
2299  {
2300  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2301 
2302  $configuration = [
2303  'exceptionHandler' => '1',
2304  'exceptionHandler.' => [
2305  'ignoreCodes.' => ['10.' => '1414513947'],
2306  ]
2307  ];
2308  $this->expectException(\LogicException::class);
2309  $this->expectExceptionCode(1414513947);
2310  $this->subject->render($contentObjectFixture, $configuration);
2311  }
2312 
2317  {
2318  $contentObjectFixture = $this->getMockBuilder(AbstractContentObject::class)
2319  ->setConstructorArgs([$this->subject])
2320  ->getMock();
2321  $contentObjectFixture->expects($this->once())
2322  ->method('render')
2323  ->willReturnCallback(function () {
2324  throw new \LogicException('Exception during rendering', 1414513947);
2325  });
2326  return $contentObjectFixture;
2327  }
2328 
2332  protected function getLibParseTarget()
2333  {
2334  return [
2335  'override' => '',
2336  'override.' => [
2337  'if.' => [
2338  'isTrue.' => [
2339  'data' => 'TSFE:dtdAllowsFrames',
2340  ],
2341  ],
2342  ],
2343  ];
2344  }
2345 
2349  protected function getLibParseFunc()
2350  {
2351  return [
2352  'makelinks' => '1',
2353  'makelinks.' => [
2354  'http.' => [
2355  'keep' => '{$styles.content.links.keep}',
2356  'extTarget' => '',
2357  'extTarget.' => $this->getLibParseTarget(),
2358  'mailto.' => [
2359  'keep' => 'path',
2360  ],
2361  ],
2362  ],
2363  'tags' => [
2364  'link' => 'TEXT',
2365  'link.' => [
2366  'current' => '1',
2367  'typolink.' => [
2368  'parameter.' => [
2369  'data' => 'parameters : allParams',
2370  ],
2371  'extTarget.' => $this->getLibParseTarget(),
2372  'target.' => $this->getLibParseTarget(),
2373  ],
2374  'parseFunc.' => [
2375  'constants' => '1',
2376  ],
2377  ],
2378  ],
2379 
2380  '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',
2381  'denyTags' => '*',
2382  'sword' => '<span class="csc-sword">|</span>',
2383  'constants' => '1',
2384  'nonTypoTagStdWrap.' => [
2385  'HTMLparser' => '1',
2386  'HTMLparser.' => [
2387  'keepNonMatchedTags' => '1',
2388  'htmlSpecialChars' => '2',
2389  ],
2390  ],
2391  ];
2392  }
2393 
2397  protected function getLibParseFunc_RTE()
2398  {
2399  return [
2400  'parseFunc' => '',
2401  'parseFunc.' => [
2402  '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',
2403  'constants' => '1',
2404  'denyTags' => '*',
2405  'externalBlocks' => 'article, aside, blockquote, div, dd, dl, footer, header, nav, ol, section, table, ul, pre',
2406  'externalBlocks.' => [
2407  'article.' => [
2408  'callRecursive' => '1',
2409  'stripNL' => '1',
2410  ],
2411  'aside.' => [
2412  'callRecursive' => '1',
2413  'stripNL' => '1',
2414  ],
2415  'blockquote.' => [
2416  'callRecursive' => '1',
2417  'stripNL' => '1',
2418  ],
2419  'dd.' => [
2420  'callRecursive' => '1',
2421  'stripNL' => '1',
2422  ],
2423  'div.' => [
2424  'callRecursive' => '1',
2425  'stripNL' => '1',
2426  ],
2427  'dl.' => [
2428  'callRecursive' => '1',
2429  'stripNL' => '1',
2430  ],
2431  'footer.' => [
2432  'callRecursive' => '1',
2433  'stripNL' => '1',
2434  ],
2435  'header.' => [
2436  'callRecursive' => '1',
2437  'stripNL' => '1',
2438  ],
2439  'nav.' => [
2440  'callRecursive' => '1',
2441  'stripNL' => '1',
2442  ],
2443  'ol.' => [
2444  'callRecursive' => '1',
2445  'stripNL' => '1',
2446  ],
2447  'section.' => [
2448  'callRecursive' => '1',
2449  'stripNL' => '1',
2450  ],
2451  'table.' => [
2452  'HTMLtableCells' => '1',
2453  'HTMLtableCells.' => [
2454  'addChr10BetweenParagraphs' => '1',
2455  'default.' => [
2456  'stdWrap.' => [
2457  'parseFunc' => '=< lib.parseFunc_RTE',
2458  'parseFunc.' => [
2459  'nonTypoTagStdWrap.' => [
2460  'encapsLines.' => [
2461  'nonWrappedTag' => '',
2462  ],
2463  ],
2464  ],
2465  ],
2466  ],
2467  ],
2468  'stdWrap.' => [
2469  'HTMLparser' => '1',
2470  'HTMLparser.' => [
2471  'keepNonMatchedTags' => '1',
2472  'tags.' => [
2473  'table.' => [
2474  'fixAttrib.' => [
2475  'class.' => [
2476  'always' => '1',
2477  'default' => 'contenttable',
2478  'list' => 'contenttable',
2479  ],
2480  ],
2481  ],
2482  ],
2483  ],
2484  ],
2485  'stripNL' => '1',
2486  ],
2487  'ul.' => [
2488  'callRecursive' => '1',
2489  'stripNL' => '1',
2490  ],
2491  ],
2492  'makelinks' => '1',
2493  'makelinks.' => [
2494  'http.' => [
2495  'extTarget.' => [
2496  'override' => '_blank',
2497  'override.' => [
2498  'if.' => [
2499  'isTrue.' => [
2500  'data' => 'TSFE:dtdAllowsFrames',
2501  ],
2502  ],
2503  ],
2504  ],
2505  'keep' => 'path',
2506  ],
2507  ],
2508  'nonTypoTagStdWrap.' => [
2509  'encapsLines.' => [
2510  'addAttributes.' => [
2511  'P.' => [
2512  'class' => 'bodytext',
2513  'class.' => [
2514  'setOnly' => 'blank',
2515  ],
2516  ],
2517  ],
2518  'encapsTagList' => 'p,pre,h1,h2,h3,h4,h5,h6,hr,dt,li',
2519  'innerStdWrap_all.' => [
2520  'ifBlank' => '&nbsp;',
2521  ],
2522  'nonWrappedTag' => 'P',
2523  'remapTag.' => [
2524  'DIV' => 'P',
2525  ],
2526  ],
2527  'HTMLparser' => '1',
2528  'HTMLparser.' => [
2529  'htmlSpecialChars' => '2',
2530  'keepNonMatchedTags' => '1',
2531  ],
2532  ],
2533  'sword' => '<span class="csc-sword">|</span>',
2534  'tags.' => [
2535  'link' => 'TEXT',
2536  'link.' => [
2537  'current' => '1',
2538  'parseFunc.' => [
2539  'constants' => '1',
2540  ],
2541  'typolink.' => [
2542  'extTarget.' => [
2543  'override' => '',
2544  'override.' => [
2545  'if.' => [
2546  'isTrue.' => [
2547  'data' => 'TSFE:dtdAllowsFrames',
2548  ],
2549  ],
2550  ],
2551  ],
2552  'parameter.' => [
2553  'data' => 'parameters : allParams',
2554  ],
2555  'target.' => [
2556  'override' => '',
2557  'override.' => [
2558  'if.' => [
2559  'isTrue.' => [
2560  'data' => 'TSFE:dtdAllowsFrames',
2561  ],
2562  ],
2563  ],
2564  ],
2565  ],
2566  ],
2567  ],
2568  ],
2569  ];
2570  }
2571 
2576  {
2577  return [
2578  'Text without tag is wrapped with <p> tag' => [
2579  'Text without tag',
2580  $this->getLibParseFunc_RTE(),
2581  '<p class="bodytext">Text without tag</p>',
2582  ],
2583  'Text wrapped with <p> tag remains the same' => [
2584  '<p class="myclass">Text with &lt;p&gt; tag</p>',
2585  $this->getLibParseFunc_RTE(),
2586  '<p class="myclass">Text with &lt;p&gt; tag</p>',
2587  ],
2588  'Text with absolute external link' => [
2589  'Text with <link http://example.com/foo/>external link</link>',
2590  $this->getLibParseFunc_RTE(),
2591  '<p class="bodytext">Text with <a href="http://example.com/foo/">external link</a></p>',
2592  ],
2593  'Empty lines are not duplicated' => [
2594  LF,
2595  $this->getLibParseFunc_RTE(),
2596  '<p class="bodytext">&nbsp;</p>',
2597  ],
2598  'Multiple empty lines with no text' => [
2599  LF . LF . LF,
2600  $this->getLibParseFunc_RTE(),
2601  '<p class="bodytext">&nbsp;</p>' . LF . '<p class="bodytext">&nbsp;</p>' . LF . '<p class="bodytext">&nbsp;</p>',
2602  ],
2603  'Empty lines are not duplicated at the end of content' => [
2604  'test' . LF . LF,
2605  $this->getLibParseFunc_RTE(),
2606  '<p class="bodytext">test</p>' . LF . '<p class="bodytext">&nbsp;</p>',
2607  ],
2608  'Empty lines are not trimmed' => [
2609  LF . 'test' . LF,
2610  $this->getLibParseFunc_RTE(),
2611  '<p class="bodytext">&nbsp;</p>' . LF . '<p class="bodytext">test</p>' . LF . '<p class="bodytext">&nbsp;</p>',
2612  ],
2613  ];
2614  }
2615 
2623  public function stdWrap_parseFuncReturnsParsedHtml($value, $configuration, $expectedResult)
2624  {
2625  $this->assertEquals($expectedResult, $this->subject->stdWrap_parseFunc($value, $configuration));
2626  }
2627 
2632  {
2633  return [
2634  'Link to url' => [
2635  'TYPO3',
2636  [
2637  'parameter' => 'http://typo3.org',
2638  ],
2639  '<a href="http://typo3.org">TYPO3</a>',
2640  ],
2641  'Link to url without schema' => [
2642  'TYPO3',
2643  [
2644  'parameter' => 'typo3.org',
2645  ],
2646  '<a href="http://typo3.org">TYPO3</a>',
2647  ],
2648  'Link to url without link text' => [
2649  '',
2650  [
2651  'parameter' => 'http://typo3.org',
2652  ],
2653  '<a href="http://typo3.org">http://typo3.org</a>',
2654  ],
2655  'Link to url with attributes' => [
2656  'TYPO3',
2657  [
2658  'parameter' => 'http://typo3.org',
2659  'ATagParams' => 'class="url-class"',
2660  'extTarget' => '_blank',
2661  'title' => 'Open new window',
2662  ],
2663  '<a href="http://typo3.org" title="Open new window" target="_blank" class="url-class">TYPO3</a>',
2664  ],
2665  'Link to url with attributes in parameter' => [
2666  'TYPO3',
2667  [
2668  'parameter' => 'http://typo3.org _blank url-class "Open new window"',
2669  ],
2670  '<a href="http://typo3.org" title="Open new window" target="_blank" class="url-class">TYPO3</a>',
2671  ],
2672  'Link to url with script tag' => [
2673  '',
2674  [
2675  'parameter' => 'http://typo3.org<script>alert(123)</script>',
2676  ],
2677  '<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>',
2678  ],
2679  'Link to email address' => [
2680  'Email address',
2681  [
2682  'parameter' => 'foo@bar.org',
2683  ],
2684  '<a href="mailto:foo@bar.org">Email address</a>',
2685  ],
2686  'Link to email address without link text' => [
2687  '',
2688  [
2689  'parameter' => 'foo@bar.org',
2690  ],
2691  '<a href="mailto:foo@bar.org">foo@bar.org</a>',
2692  ],
2693  'Link to email with attributes' => [
2694  'Email address',
2695  [
2696  'parameter' => 'foo@bar.org',
2697  'ATagParams' => 'class="email-class"',
2698  'title' => 'Write an email',
2699  ],
2700  '<a href="mailto:foo@bar.org" title="Write an email" class="email-class">Email address</a>',
2701  ],
2702  'Link to email with attributes in parameter' => [
2703  'Email address',
2704  [
2705  'parameter' => 'foo@bar.org - email-class "Write an email"',
2706  ],
2707  '<a href="mailto:foo@bar.org" title="Write an email" class="email-class">Email address</a>',
2708  ],
2709  ];
2710  }
2711 
2719  public function typolinkReturnsCorrectLinksForEmailsAndUrls($linkText, $configuration, $expectedResult)
2720  {
2721  $templateServiceObjectMock = $this->getMockBuilder(TemplateService::class)
2722  ->setMethods(['dummy'])
2723  ->getMock();
2724  $templateServiceObjectMock->setup = [
2725  'lib.' => [
2726  'parseFunc.' => $this->getLibParseFunc(),
2727  ],
2728  ];
2729  $typoScriptFrontendControllerMockObject = $this->createMock(TypoScriptFrontendController::class);
2730  $typoScriptFrontendControllerMockObject->config = [
2731  'config' => [],
2732  'mainScript' => 'index.php',
2733  ];
2734  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
2735  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
2736  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
2737 
2738  $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
2739  }
2740 
2749  public function typoLinkEncodesMailAddressForSpamProtection(array $settings, $linkText, $mailAddress, $expected)
2750  {
2751  $this->getFrontendController()->spamProtectEmailAddresses = $settings['spamProtectEmailAddresses'];
2752  $this->getFrontendController()->config['config'] = $settings;
2753  $typoScript = ['parameter' => $mailAddress];
2754 
2755  $this->assertEquals($expected, $this->subject->typoLink($linkText, $typoScript));
2756  }
2757 
2762  {
2763  return [
2764  'plain mail without mailto scheme' => [
2765  [
2766  'spamProtectEmailAddresses' => '',
2767  'spamProtectEmailAddresses_atSubst' => '',
2768  'spamProtectEmailAddresses_lastDotSubst' => '',
2769  ],
2770  'some.body@test.typo3.org',
2771  'some.body@test.typo3.org',
2772  '<a href="mailto:some.body@test.typo3.org">some.body@test.typo3.org</a>',
2773  ],
2774  'plain mail with mailto scheme' => [
2775  [
2776  'spamProtectEmailAddresses' => '',
2777  'spamProtectEmailAddresses_atSubst' => '',
2778  'spamProtectEmailAddresses_lastDotSubst' => '',
2779  ],
2780  'some.body@test.typo3.org',
2781  'mailto:some.body@test.typo3.org',
2782  '<a href="mailto:some.body@test.typo3.org">some.body@test.typo3.org</a>',
2783  ],
2784  'plain with at and dot substitution' => [
2785  [
2786  'spamProtectEmailAddresses' => '0',
2787  'spamProtectEmailAddresses_atSubst' => '(at)',
2788  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
2789  ],
2790  'some.body@test.typo3.org',
2791  'mailto:some.body@test.typo3.org',
2792  '<a href="mailto:some.body@test.typo3.org">some.body@test.typo3.org</a>',
2793  ],
2794  'mono-alphabetic substitution offset +1' => [
2795  [
2796  'spamProtectEmailAddresses' => '1',
2797  'spamProtectEmailAddresses_atSubst' => '',
2798  'spamProtectEmailAddresses_lastDotSubst' => '',
2799  ],
2800  'some.body@test.typo3.org',
2801  'mailto:some.body@test.typo3.org',
2802  '<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body(at)test.typo3.org</a>',
2803  ],
2804  'mono-alphabetic substitution offset +1 with at substitution' => [
2805  [
2806  'spamProtectEmailAddresses' => '1',
2807  'spamProtectEmailAddresses_atSubst' => '@',
2808  'spamProtectEmailAddresses_lastDotSubst' => '',
2809  ],
2810  'some.body@test.typo3.org',
2811  'mailto:some.body@test.typo3.org',
2812  '<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body@test.typo3.org</a>',
2813  ],
2814  'mono-alphabetic substitution offset +1 with at and dot substitution' => [
2815  [
2816  'spamProtectEmailAddresses' => '1',
2817  'spamProtectEmailAddresses_atSubst' => '(at)',
2818  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
2819  ],
2820  'some.body@test.typo3.org',
2821  'mailto:some.body@test.typo3.org',
2822  '<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body(at)test.typo3(dot)org</a>',
2823  ],
2824  'mono-alphabetic substitution offset -1 with at and dot substitution' => [
2825  [
2826  'spamProtectEmailAddresses' => '-1',
2827  'spamProtectEmailAddresses_atSubst' => '(at)',
2828  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
2829  ],
2830  'some.body@test.typo3.org',
2831  'mailto:some.body@test.typo3.org',
2832  '<a href="javascript:linkTo_UnCryptMailto(\'lzhksn9rnld-ancxZsdrs-sxon2-nqf\');">some.body(at)test.typo3(dot)org</a>',
2833  ],
2834  'entity substitution with at and dot substitution' => [
2835  [
2836  'spamProtectEmailAddresses' => 'ascii',
2837  'spamProtectEmailAddresses_atSubst' => '',
2838  'spamProtectEmailAddresses_lastDotSubst' => '',
2839  ],
2840  'some.body@test.typo3.org',
2841  'mailto:some.body@test.typo3.org',
2842  '<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>',
2843  ],
2844  'entity substitution with at and dot substitution with at and dot substitution' => [
2845  [
2846  'spamProtectEmailAddresses' => 'ascii',
2847  'spamProtectEmailAddresses_atSubst' => '(at)',
2848  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
2849  ],
2850  'some.body@test.typo3.org',
2851  'mailto:some.body@test.typo3.org',
2852  '<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>',
2853  ],
2854  ];
2855  }
2856 
2861  {
2862  return [
2863  'Link to file' => [
2864  'My file',
2865  [
2866  'parameter' => 'fileadmin/foo.bar',
2867  ],
2868  '<a href="fileadmin/foo.bar">My file</a>',
2869  ],
2870  'Link to file without link text' => [
2871  '',
2872  [
2873  'parameter' => 'fileadmin/foo.bar',
2874  ],
2875  '<a href="fileadmin/foo.bar">fileadmin/foo.bar</a>',
2876  ],
2877  'Link to file with attributes' => [
2878  'My file',
2879  [
2880  'parameter' => 'fileadmin/foo.bar',
2881  'ATagParams' => 'class="file-class"',
2882  'fileTarget' => '_blank',
2883  'title' => 'Title of the file',
2884  ],
2885  '<a href="fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
2886  ],
2887  'Link to file with attributes and additional href' => [
2888  'My file',
2889  [
2890  'parameter' => 'fileadmin/foo.bar',
2891  'ATagParams' => 'href="foo-bar"',
2892  'fileTarget' => '_blank',
2893  'title' => 'Title of the file',
2894  ],
2895  '<a href="fileadmin/foo.bar" title="Title of the file" target="_blank">My file</a>',
2896  ],
2897  'Link to file with attributes and additional href and class' => [
2898  'My file',
2899  [
2900  'parameter' => 'fileadmin/foo.bar',
2901  'ATagParams' => 'href="foo-bar" class="file-class"',
2902  'fileTarget' => '_blank',
2903  'title' => 'Title of the file',
2904  ],
2905  '<a href="fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
2906  ],
2907  'Link to file with attributes and additional class and href' => [
2908  'My file',
2909  [
2910  'parameter' => 'fileadmin/foo.bar',
2911  'ATagParams' => 'class="file-class" href="foo-bar"',
2912  'fileTarget' => '_blank',
2913  'title' => 'Title of the file',
2914  ],
2915  '<a href="fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
2916  ],
2917  'Link to file with attributes and additional class and href and title' => [
2918  'My file',
2919  [
2920  'parameter' => 'fileadmin/foo.bar',
2921  'ATagParams' => 'class="file-class" href="foo-bar" title="foo-bar"',
2922  'fileTarget' => '_blank',
2923  'title' => 'Title of the file',
2924  ],
2925  '<a href="fileadmin/foo.bar" title="foo-bar" target="_blank" class="file-class">My file</a>',
2926  ],
2927  'Link to file with attributes and empty ATagParams' => [
2928  'My file',
2929  [
2930  'parameter' => 'fileadmin/foo.bar',
2931  'ATagParams' => '',
2932  'fileTarget' => '_blank',
2933  'title' => 'Title of the file',
2934  ],
2935  '<a href="fileadmin/foo.bar" title="Title of the file" target="_blank">My file</a>',
2936  ],
2937  'Link to file with attributes in parameter' => [
2938  'My file',
2939  [
2940  'parameter' => 'fileadmin/foo.bar _blank file-class "Title of the file"',
2941  ],
2942  '<a href="fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
2943  ],
2944  'Link to file with script tag in name' => [
2945  '',
2946  [
2947  'parameter' => 'fileadmin/<script>alert(123)</script>',
2948  ],
2949  '<a href="fileadmin/&lt;script&gt;alert(123)&lt;/script&gt;">fileadmin/&lt;script&gt;alert(123)&lt;/script&gt;</a>',
2950  ],
2951  ];
2952  }
2953 
2961  public function typolinkReturnsCorrectLinksFiles($linkText, $configuration, $expectedResult)
2962  {
2963  $templateServiceObjectMock = $this->getMockBuilder(TemplateService::class)
2964  ->setMethods(['dummy'])
2965  ->getMock();
2966  $templateServiceObjectMock->setup = [
2967  'lib.' => [
2968  'parseFunc.' => $this->getLibParseFunc(),
2969  ],
2970  ];
2971  $typoScriptFrontendControllerMockObject = $this->createMock(TypoScriptFrontendController::class);
2972  $typoScriptFrontendControllerMockObject->config = [
2973  'config' => [],
2974  'mainScript' => 'index.php',
2975  ];
2976  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
2977  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
2978 
2979  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
2980 
2981  $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
2982  }
2983 
2988  {
2989  return [
2990  'Link to file' => [
2991  'My file',
2992  [
2993  'parameter' => 'fileadmin/foo.bar',
2994  ],
2995  '/',
2996  '<a href="/fileadmin/foo.bar">My file</a>',
2997  ],
2998  'Link to file with longer absRefPrefix' => [
2999  'My file',
3000  [
3001  'parameter' => 'fileadmin/foo.bar',
3002  ],
3003  '/sub/',
3004  '<a href="/sub/fileadmin/foo.bar">My file</a>',
3005  ],
3006  'Link to absolute file' => [
3007  'My file',
3008  [
3009  'parameter' => '/images/foo.bar',
3010  ],
3011  '/',
3012  '<a href="/images/foo.bar">My file</a>',
3013  ],
3014  'Link to absolute file with longer absRefPrefix' => [
3015  'My file',
3016  [
3017  'parameter' => '/images/foo.bar',
3018  ],
3019  '/sub/',
3020  '<a href="/images/foo.bar">My file</a>',
3021  ],
3022  'Link to absolute file with identical longer absRefPrefix' => [
3023  'My file',
3024  [
3025  'parameter' => '/sub/fileadmin/foo.bar',
3026  ],
3027  '/sub/',
3028  '<a href="/sub/fileadmin/foo.bar">My file</a>',
3029  ],
3030  'Link to file with empty absRefPrefix' => [
3031  'My file',
3032  [
3033  'parameter' => 'fileadmin/foo.bar',
3034  ],
3035  '',
3036  '<a href="fileadmin/foo.bar">My file</a>',
3037  ],
3038  'Link to absolute file with empty absRefPrefix' => [
3039  'My file',
3040  [
3041  'parameter' => '/fileadmin/foo.bar',
3042  ],
3043  '',
3044  '<a href="/fileadmin/foo.bar">My file</a>',
3045  ],
3046  'Link to file with attributes with absRefPrefix' => [
3047  'My file',
3048  [
3049  'parameter' => 'fileadmin/foo.bar',
3050  'ATagParams' => 'class="file-class"',
3051  'fileTarget' => '_blank',
3052  'title' => 'Title of the file',
3053  ],
3054  '/',
3055  '<a href="/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
3056  ],
3057  'Link to file with attributes with longer absRefPrefix' => [
3058  'My file',
3059  [
3060  'parameter' => 'fileadmin/foo.bar',
3061  'ATagParams' => 'class="file-class"',
3062  'fileTarget' => '_blank',
3063  'title' => 'Title of the file',
3064  ],
3065  '/sub/',
3066  '<a href="/sub/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
3067  ],
3068  'Link to absolute file with attributes with absRefPrefix' => [
3069  'My file',
3070  [
3071  'parameter' => '/images/foo.bar',
3072  'ATagParams' => 'class="file-class"',
3073  'fileTarget' => '_blank',
3074  'title' => 'Title of the file',
3075  ],
3076  '/',
3077  '<a href="/images/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
3078  ],
3079  'Link to absolute file with attributes with longer absRefPrefix' => [
3080  'My file',
3081  [
3082  'parameter' => '/images/foo.bar',
3083  'ATagParams' => 'class="file-class"',
3084  'fileTarget' => '_blank',
3085  'title' => 'Title of the file',
3086  ],
3087  '/sub/',
3088  '<a href="/images/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
3089  ],
3090  'Link to absolute file with attributes with identical longer absRefPrefix' => [
3091  'My file',
3092  [
3093  'parameter' => '/sub/fileadmin/foo.bar',
3094  'ATagParams' => 'class="file-class"',
3095  'fileTarget' => '_blank',
3096  'title' => 'Title of the file',
3097  ],
3098  '/sub/',
3099  '<a href="/sub/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
3100  ],
3101  ];
3102  }
3103 
3112  public function typolinkReturnsCorrectLinksForFilesWithAbsRefPrefix($linkText, $configuration, $absRefPrefix, $expectedResult)
3113  {
3114  $templateServiceObjectMock = $this->getMockBuilder(TemplateService::class)
3115  ->setMethods(['dummy'])
3116  ->getMock();
3117  $templateServiceObjectMock->setup = [
3118  'lib.' => [
3119  'parseFunc.' => $this->getLibParseFunc(),
3120  ],
3121  ];
3122  $typoScriptFrontendControllerMockObject = $this->createMock(TypoScriptFrontendController::class);
3123  $typoScriptFrontendControllerMockObject->config = [
3124  'config' => [],
3125  'mainScript' => 'index.php',
3126  ];
3127  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
3128  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
3129  $GLOBALS['TSFE']->absRefPrefix = $absRefPrefix;
3130  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
3131 
3132  $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
3133  }
3134 
3139  {
3140  $linkService = $this->prophesize(LinkService::class);
3141  GeneralUtility::setSingletonInstance(LinkService::class, $linkService->reveal());
3142  $linkService->resolve('foo')->willThrow(InvalidPathException::class);
3143 
3144  $this->assertSame('foo', $this->subject->typoLink('foo', ['parameter' => 'foo']));
3145  }
3146 
3151  {
3152  $linkService = $this->prophesize(LinkService::class);
3153  GeneralUtility::setSingletonInstance(LinkService::class, $linkService->reveal());
3154  $linkService->resolve('foo')->willThrow(InvalidPathException::class);
3155 
3156  $logManager = $this->prophesize(LogManager::class);
3157  GeneralUtility::setSingletonInstance(LogManager::class, $logManager->reveal());
3158  $logger = $this->prophesize(Logger::class);
3159  $logger->warning('The link could not be generated', Argument::any())->shouldBeCalled();
3160  $logManager->getLogger(Argument::any())->willReturn($logger->reveal());
3161 
3162  $this->subject->typoLink('foo', ['parameter' => 'foo']);
3163  }
3164 
3169  {
3170  $conf = [
3171  'token' => ',',
3172  'returnCount' => 1
3173  ];
3174  $expectedResult = 5;
3175  $amountOfEntries = $this->subject->splitObj('1, 2, 3, 4, 5', $conf);
3176  $this->assertSame(
3177  $expectedResult,
3178  $amountOfEntries
3179  );
3180  }
3181 
3183  // Test concerning link generation
3185 
3190  {
3191  $fileNameAndPath = PATH_site . 'typo3temp/var/tests/phpunitJumpUrlTestFile with spaces & amps.txt';
3192  file_put_contents($fileNameAndPath, 'Some test data');
3193  $relativeFileNameAndPath = substr($fileNameAndPath, strlen(PATH_site));
3194  $fileName = substr($fileNameAndPath, strlen(PATH_site . 'typo3temp/var/tests/'));
3195 
3196  $expectedLink = str_replace('%2F', '/', rawurlencode($relativeFileNameAndPath));
3197  $result = $this->subject->filelink($fileName, ['path' => 'typo3temp/var/tests/']);
3198  $this->assertEquals('<a href="' . $expectedLink . '">' . $fileName . '</a>', $result);
3199 
3200  GeneralUtility::unlink_tempfile($fileNameAndPath);
3201  }
3202 
3209  {
3210  $value = $this->getUniqueId('value');
3211  $wrap = [$this->getUniqueId('wrap')];
3212  $valueConf = ['key' => $value];
3213  $wrapConf = ['key.' => $wrap];
3214  $conf = array_merge($valueConf, $wrapConf);
3215  $will = $this->getUniqueId('stdWrap');
3216 
3217  return [
3218  'no conf' => [
3219  '',
3220  [],
3221  0,
3222  null,
3223  null,
3224  null
3225  ],
3226  'value conf only' => [
3227  $value,
3228  $valueConf,
3229  0,
3230  null,
3231  null,
3232  null
3233  ],
3234  'wrap conf only' => [
3235  $will,
3236  $wrapConf,
3237  1,
3238  '',
3239  $wrap,
3240  $will
3241  ],
3242  'full conf' => [
3243  $will,
3244  $conf,
3245  1,
3246  $value,
3247  $wrap,
3248  $will
3249  ],
3250  ];
3251  }
3252 
3267  public function calculateCacheKey($expect, $conf, $times, $with, $withWrap, $will)
3268  {
3269  $subject = $this->getAccessibleMock(ContentObjectRenderer::class, ['stdWrap']);
3270  $subject->expects($this->exactly($times))
3271  ->method('stdWrap')
3272  ->with($with, $withWrap)
3273  ->willReturn($will);
3274 
3275  $result = $subject->_call('calculateCacheKey', $conf);
3276  $this->assertSame($expect, $result);
3277  }
3278 
3284  public function getFromCacheDtataProvider()
3285  {
3286  $conf = [$this->getUniqueId('conf')];
3287  return [
3288  'empty cache key' => [
3289  false, $conf, '', 0, null,
3290  ],
3291  'non-empty cache key' => [
3292  'value', $conf, 'non-empty-key', 1, 'value',
3293  ],
3294  ];
3295  }
3296 
3313  public function getFromCache($expect, $conf, $cacheKey, $times, $cached)
3314  {
3315  $subject = $this->getAccessibleMock(
3316  ContentObjectRenderer::class,
3317  ['calculateCacheKey']
3318  );
3319  $subject
3320  ->expects($this->exactly(1))
3321  ->method('calculateCacheKey')
3322  ->with($conf)
3323  ->willReturn($cacheKey);
3324  $cacheFrontend = $this->createMock(CacheFrontendInterface::class);
3325  $cacheFrontend
3326  ->expects($this->exactly($times))
3327  ->method('get')
3328  ->with($cacheKey)
3329  ->willReturn($cached);
3330  $cacheManager = $this->createMock(CacheManager::class);
3331  $cacheManager
3332  ->method('getCache')
3333  ->willReturn($cacheFrontend);
3335  CacheManager::class,
3336  $cacheManager
3337  );
3338  $this->assertSame($expect, $subject->_call('getFromCache', $conf));
3339  }
3340 
3346  public function getFieldValDataProvider()
3347  {
3348  return [
3349  'invalid single key' => [null, 'invalid'],
3350  'single key of null' => [null, 'null'],
3351  'single key of empty string' => ['', 'empty'],
3352  'single key of non-empty string' => ['string 1', 'string1'],
3353  'single key of boolean false' => [false, 'false'],
3354  'single key of boolean true' => [true, 'true'],
3355  'single key of integer 0' => [0, 'zero'],
3356  'single key of integer 1' => [1, 'one'],
3357  'single key to be trimmed' => ['string 1', ' string1 '],
3358 
3359  'split nothing' => ['', '//'],
3360  'split one before' => ['string 1', 'string1//'],
3361  'split one after' => ['string 1', '//string1'],
3362  'split two ' => ['string 1', 'string1//string2'],
3363  'split three ' => ['string 1', 'string1//string2//string3'],
3364  'split to be trimmed' => ['string 1', ' string1 // string2 '],
3365  '0 is not empty' => [0, '// zero'],
3366  '1 is not empty' => [1, '// one'],
3367  'true is not empty' => [true, '// true'],
3368  'false is empty' => ['', '// false'],
3369  'null is empty' => ['', '// null'],
3370  'empty string is empty' => ['', '// empty'],
3371  'string is not empty' => ['string 1', '// string1'],
3372  'first non-empty winns' => [0, 'false//empty//null//zero//one'],
3373  'empty string is fallback' => ['', 'false // empty // null'],
3374  ];
3375  }
3376 
3415  public function getFieldVal($expect, $fields)
3416  {
3417  $data = [
3418  'string1' => 'string 1',
3419  'string2' => 'string 2',
3420  'string3' => 'string 3',
3421  'empty' => '',
3422  'null' => null,
3423  'false' => false,
3424  'true' => true,
3425  'zero' => 0,
3426  'one' => 1,
3427  ];
3428  $this->subject->_set('data', $data);
3429  $this->assertSame($expect, $this->subject->getFieldVal($fields));
3430  }
3431 
3437  public function caseshiftDataProvider()
3438  {
3439  return [
3440  'lower' => ['x y', 'X Y', 'lower'],
3441  'upper' => ['X Y', 'x y', 'upper'],
3442  'capitalize' => ['One Two', 'one two', 'capitalize'],
3443  'ucfirst' => ['One two', 'one two', 'ucfirst'],
3444  'lcfirst' => ['oNE TWO', 'ONE TWO', 'lcfirst'],
3445  'uppercamelcase' => ['CamelCase', 'camel_case', 'uppercamelcase'],
3446  'lowercamelcase' => ['camelCase', 'camel_case', 'lowercamelcase'],
3447  ];
3448  }
3449 
3459  public function caseshift($expect, $content, $case)
3460  {
3461  $this->assertSame(
3462  $expect,
3463  $this->subject->caseshift($content, $case)
3464  );
3465  }
3466 
3472  public function HTMLcaseshiftDataProvider()
3473  {
3474  $case = $this->getUniqueId('case');
3475  return [
3476  'simple text' => [
3477  'TEXT', 'text', $case,
3478  [['text', $case]],
3479  ['TEXT']
3480  ],
3481  'simple tag' => [
3482  '<i>TEXT</i>', '<i>text</i>', $case,
3483  [['', $case], ['text', $case]],
3484  ['', 'TEXT']
3485  ],
3486  'multiple nested tags with classes' => [
3487  '<div class="typo3">'
3488  . '<p>A <b>BOLD<\b> WORD.</p>'
3489  . '<p>AN <i>ITALIC<\i> WORD.</p>'
3490  . '</div>',
3491  '<div class="typo3">'
3492  . '<p>A <b>bold<\b> word.</p>'
3493  . '<p>An <i>italic<\i> word.</p>'
3494  . '</div>',
3495  $case,
3496  [
3497  ['', $case],
3498  ['', $case],
3499  ['A ', $case],
3500  ['bold', $case],
3501  [' word.', $case],
3502  ['', $case],
3503  ['An ', $case],
3504  ['italic', $case],
3505  [' word.', $case],
3506  ['', $case],
3507  ],
3508  [ '', '', 'A ', 'BOLD', ' WORD.', '', 'AN ', 'ITALIC', ' WORD.', '']
3509  ],
3510  ];
3511  }
3512 
3529  public function HTMLcaseshift($expect, $content, $case, $with, $will)
3530  {
3531  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
3532  ->setMethods(['caseshift'])->getMock();
3533  $subject
3534  ->expects($this->exactly(count($with)))
3535  ->method('caseshift')
3536  ->withConsecutive(...$with)
3537  ->will($this->onConsecutiveCalls(...$will));
3538  $this->assertSame(
3539  $expect,
3540  $subject->HTMLcaseshift($content, $case)
3541  );
3542  }
3543 
3544  /***************************************************************************
3545  * General tests for stdWrap_
3546  ***************************************************************************/
3547 
3560  {
3561  $callable = 0;
3562  $notCallable = 0;
3563  $processors = ['invalidProcessor'];
3564  foreach (array_keys($this->subject->_get('stdWrapOrder')) as $key) {
3565  $processors[] = strtr($key, ['.' => '']);
3566  }
3567  foreach (array_unique($processors) as $processor) {
3568  $method = [$this->subject, 'stdWrap_' . $processor];
3569  if (is_callable($method)) {
3570  $callable += 1;
3571  } else {
3572  $notCallable += 1;
3573  }
3574  }
3575  $this->assertSame(1, $notCallable);
3576  $this->assertSame(91, $callable);
3577  }
3578 
3599  {
3600  $expectExceptions = ['numRows', 'split'];
3601  if (!version_compare(PHP_VERSION, '7.1', '<')) {
3602  // PHP >= 7.1 throws "A non-numeric value encountered" in GeneralUtility::formatSize()
3603  // @todo: If that is sanitized in a better way in formatSize(), this call needs adaption
3604  $expectExceptions[] = 'bytes';
3605  }
3606  $count = 0;
3607  $processors = [];
3608  $exceptions = [];
3609  foreach (array_keys($this->subject->_get('stdWrapOrder')) as $key) {
3610  $processors[] = strtr($key, ['.' => '']);
3611  }
3612  foreach (array_unique($processors) as $processor) {
3613  $count += 1;
3614  try {
3615  $conf = [$processor => '', $processor . '.' => ['table' => 'tt_content']];
3616  $method = 'stdWrap_' . $processor;
3617  $this->subject->$method('', $conf);
3618  } catch (\Exception $e) {
3619  $exceptions[] = $processor;
3620  }
3621  }
3622  $this->assertSame($expectExceptions, $exceptions);
3623  $this->assertSame(91, $count);
3624  }
3625 
3626  /***************************************************************************
3627  * End general tests for stdWrap_
3628  ***************************************************************************/
3629 
3630  /***************************************************************************
3631  * Tests for stdWrap_ in alphabetical order (all uppercase before lowercase)
3632  ***************************************************************************/
3633 
3640  {
3641  return [
3642  'preProcess' => [
3643  'stdWrap_stdWrapPreProcess', 'stdWrapPreProcess'
3644  ],
3645  'override' => [
3646  'stdWrap_stdWrapOverride', 'stdWrapOverride'
3647  ],
3648  'process' => [
3649  'stdWrap_stdWrapProcess', 'stdWrapProcess'
3650  ],
3651  'postProcess' => [
3652  'stdWrap_stdWrapPostProcess', 'stdWrapPostProcess'
3653  ],
3654  ];
3655  }
3656 
3673  $stdWrapMethod,
3674  $hookObjectCall
3675  ) {
3676  $conf = [$this->getUniqueId('conf')];
3677  $content = $this->getUniqueId('content');
3678  $processed1 = $this->getUniqueId('processed1');
3679  $processed2 = $this->getUniqueId('processed2');
3680  $hookObject1 = $this->createMock(
3681  ContentObjectStdWrapHookInterface::class
3682  );
3683  $hookObject1->expects($this->once())
3684  ->method($hookObjectCall)
3685  ->with($content, $conf)
3686  ->willReturn($processed1);
3687  $hookObject2 = $this->createMock(
3688  ContentObjectStdWrapHookInterface::class
3689  );
3690  $hookObject2->expects($this->once())
3691  ->method($hookObjectCall)
3692  ->with($processed1, $conf)
3693  ->willReturn($processed2);
3694  $this->subject->_set(
3695  'stdWrapHookObjects',
3696  [$hookObject1, $hookObject2]
3697  );
3698  $result = $this->subject->$stdWrapMethod($content, $conf);
3699  $this->assertSame($processed2, $result);
3700  }
3701 
3708  {
3709  $content = $this->getUniqueId('content');
3710  $parsed = $this->getUniqueId('parsed');
3711  return [
3712  'no config' => [
3713  $content, $content, [], 0, $parsed
3714  ],
3715  'no array' => [
3716  $content, $content, ['HTMLparser.' => 1], 0, $parsed
3717  ],
3718  'empty array' => [
3719  $parsed, $content, ['HTMLparser.' => []], 1, $parsed
3720  ],
3721  'non-empty array' => [
3722  $parsed, $content, ['HTMLparser.' => [true]], 1, $parsed
3723  ],
3724  ];
3725  }
3726 
3749  public function stdWrap_HTMLparser(
3750  $expect,
3751  $content,
3752  $conf,
3753  $times,
3754  $will
3755  ) {
3756  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
3757  ->setMethods(['HTMLparser_TSbridge'])->getMock();
3758  $subject
3759  ->expects($this->exactly($times))
3760  ->method('HTMLparser_TSbridge')
3761  ->with($content, $conf['HTMLparser.'])
3762  ->willReturn($will);
3763  $this->assertSame(
3764  $expect,
3765  $subject->stdWrap_HTMLparser($content, $conf)
3766  );
3767  }
3768 
3775  {
3776  $content = $this->getUniqueId('content');
3777  $array = [$this->getUniqueId('TCAselectItem.')];
3778  $will = $this->getUniqueId('will');
3779  return [
3780  'empty conf' => [
3781  $content, $content, [], 0, $will
3782  ],
3783  'no array' => [
3784  $content, $content, ['TCAselectItem.' => true], 0, $will
3785  ],
3786  'empty array' => [
3787  $will, $content, ['TCAselectItem.' => []], 1, $will
3788  ],
3789  'array' => [
3790  $will, $content, ['TCAselectItem.' => $array], 1, $will
3791  ]
3792  ];
3793  }
3794 
3817  public function stdWrap_TCAselectItem(
3818  $expect,
3819  $content,
3820  $conf,
3821  $times,
3822  $will
3823  ) {
3824  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
3825  ->setMethods(['TCAlookup'])->getMock();
3826  $subject
3827  ->expects($this->exactly($times))
3828  ->method('TCAlookup')
3829  ->with($content, $conf['TCAselectItem.'])
3830  ->willReturn($will);
3831  $this->assertSame(
3832  $expect,
3833  $subject->stdWrap_TCAselectItem($content, $conf)
3834  );
3835  }
3836 
3841  {
3842  return [
3843  'No Tag' => [
3844  [],
3845  ['addPageCacheTags' => ''],
3846  ],
3847  'Two expectedTags' => [
3848  ['tag1', 'tag2'],
3849  ['addPageCacheTags' => 'tag1,tag2'],
3850  ],
3851  'Two expectedTags plus one with stdWrap' => [
3852  ['tag1', 'tag2', 'tag3'],
3853  [
3854  'addPageCacheTags' => 'tag1,tag2',
3855  'addPageCacheTags.' => ['wrap' => '|,tag3']
3856  ],
3857  ],
3858  ];
3859  }
3860 
3867  public function stdWrap_addPageCacheTagsAddsPageTags(array $expectedTags, array $configuration)
3868  {
3869  $this->subject->stdWrap_addPageCacheTags('', $configuration);
3870  $this->assertEquals($expectedTags, $this->frontendControllerMock->_get('pageCacheTags'));
3871  }
3872 
3885  public function stdWrap_addParams()
3886  {
3887  $content = $this->getUniqueId('content');
3888  $conf = [
3889  'addParams' => $this->getUniqueId('not used'),
3890  'addParams.' => [$this->getUniqueId('addParams.')],
3891  ];
3892  $return = $this->getUniqueId('return');
3893  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
3894  ->setMethods(['addParams'])->getMock();
3895  $subject
3896  ->expects($this->once())
3897  ->method('addParams')
3898  ->with($content, $conf['addParams.'])
3899  ->willReturn($return);
3900  $this->assertSame(
3901  $return,
3902  $subject->stdWrap_addParams($content, $conf)
3903  );
3904  }
3905 
3918  public function stdWrap_age()
3919  {
3920  $now = 10;
3921  $content = '9';
3922  $conf = ['age' => $this->getUniqueId('age')];
3923  $return = $this->getUniqueId('return');
3924  $difference = $now - (int)$content;
3925  $GLOBALS['EXEC_TIME'] = $now;
3926  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
3927  ->setMethods(['calcAge'])->getMock();
3928  $subject
3929  ->expects($this->once())
3930  ->method('calcAge')
3931  ->with($difference, $conf['age'])
3932  ->willReturn($return);
3933  $this->assertSame($return, $subject->stdWrap_age($content, $conf));
3934  }
3935 
3949  public function stdWrap_append()
3950  {
3951  $debugKey = '/stdWrap/.append';
3952  $content = $this->getUniqueId('content');
3953  $conf = [
3954  'append' => $this->getUniqueId('append'),
3955  'append.' => [$this->getUniqueId('append.')],
3956  ];
3957  $return = $this->getUniqueId('return');
3958  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
3959  ->setMethods(['cObjGetSingle'])->getMock();
3960  $subject
3961  ->expects($this->once())
3962  ->method('cObjGetSingle')
3963  ->with($conf['append'], $conf['append.'], $debugKey)
3964  ->willReturn($return);
3965  $this->assertSame(
3966  $content . $return,
3967  $subject->stdWrap_append($content, $conf)
3968  );
3969  }
3970 
3976  public function stdWrapBrDataProvider()
3977  {
3978  return [
3979  'no xhtml with LF in between' => [
3980  'one<br>' . LF . 'two',
3981  'one' . LF . 'two',
3982  null
3983  ],
3984  'no xhtml with LF in between and around' => [
3985  '<br>' . LF . 'one<br>' . LF . 'two<br>' . LF,
3986  LF . 'one' . LF . 'two' . LF,
3987  null
3988  ],
3989  'xhtml with LF in between' => [
3990  'one<br />' . LF . 'two',
3991  'one' . LF . 'two',
3992  'xhtml_strict'
3993  ],
3994  'xhtml with LF in between and around' => [
3995  '<br />' . LF . 'one<br />' . LF . 'two<br />' . LF,
3996  LF . 'one' . LF . 'two' . LF,
3997  'xhtml_strict'
3998  ],
3999  ];
4000  }
4001 
4011  public function stdWrap_br($expected, $input, $xhtmlDoctype)
4012  {
4013  $GLOBALS['TSFE']->xhtmlDoctype = $xhtmlDoctype;
4014  $this->assertSame($expected, $this->subject->stdWrap_br($input));
4015  }
4016 
4022  public function stdWrapBrTagDataProvider()
4023  {
4024  $noConfig = [];
4025  $config1 = ['brTag' => '<br/>'];
4026  $config2 = ['brTag' => '<br>'];
4027  return [
4028  'no config: one break at the beginning' => [LF . 'one' . LF . 'two', 'onetwo', $noConfig],
4029  'no config: multiple breaks at the beginning' => [LF . LF . 'one' . LF . 'two', 'onetwo', $noConfig],
4030  'no config: one break at the end' => ['one' . LF . 'two' . LF, 'onetwo', $noConfig],
4031  'no config: multiple breaks at the end' => ['one' . LF . 'two' . LF . LF, 'onetwo', $noConfig],
4032 
4033  'config1: one break at the beginning' => [LF . 'one' . LF . 'two', '<br/>one<br/>two', $config1],
4034  'config1: multiple breaks at the beginning' => [LF . LF . 'one' . LF . 'two', '<br/><br/>one<br/>two', $config1],
4035  'config1: one break at the end' => ['one' . LF . 'two' . LF, 'one<br/>two<br/>', $config1],
4036  'config1: multiple breaks at the end' => ['one' . LF . 'two' . LF . LF, 'one<br/>two<br/><br/>', $config1],
4037 
4038  'config2: one break at the beginning' => [LF . 'one' . LF . 'two', '<br>one<br>two', $config2],
4039  'config2: multiple breaks at the beginning' => [LF . LF . 'one' . LF . 'two', '<br><br>one<br>two', $config2],
4040  'config2: one break at the end' => ['one' . LF . 'two' . LF, 'one<br>two<br>', $config2],
4041  'config2: multiple breaks at the end' => ['one' . LF . 'two' . LF . LF, 'one<br>two<br><br>', $config2],
4042  ];
4043  }
4044 
4051  public function stdWrap_brTag($input, $expected, $config)
4052  {
4053  $this->assertEquals($expected, $this->subject->stdWrap_brTag($input, $config));
4054  }
4055 
4061  public function stdWrap_bytesDataProvider()
4062  {
4063  return [
4064  'value 1234 default' => [
4065  '1.21 Ki', '1234',
4066  ['labels' => '', 'base' => 0],
4067  ],
4068  'value 1234 si' => [
4069  '1.23 k', '1234',
4070  ['labels' => 'si', 'base' => 0],
4071  ],
4072  'value 1234 iec' => [
4073  '1.21 Ki', '1234',
4074  ['labels' => 'iec', 'base' => 0],
4075  ],
4076  'value 1234 a-i' => [
4077  '1.23b', '1234',
4078  ['labels' => 'a|b|c|d|e|f|g|h|i', 'base' => 1000],
4079  ],
4080  'value 1234 a-i invalid base' => [
4081  '1.21b', '1234',
4082  ['labels' => 'a|b|c|d|e|f|g|h|i', 'base' => 54],
4083  ],
4084  'value 1234567890 default' => [
4085  '1.15 Gi', '1234567890',
4086  ['labels' => '', 'base' => 0],
4087  ]
4088  ];
4089  }
4090 
4112  public function stdWrap_bytes($expect, $content, $conf)
4113  {
4114  $locale = 'en_US.UTF-8';
4115  try {
4116  $this->setLocale(LC_NUMERIC, $locale);
4117  } catch (\PHPUnit\Framework\Exception $e) {
4118  $this->markTestSkipped('Locale ' . $locale . ' is not available.');
4119  }
4120  $conf = ['bytes.' => $conf];
4121  $this->assertSame(
4122  $expect,
4123  $this->subject->stdWrap_bytes($content, $conf)
4124  );
4125  }
4126 
4140  public function stdWrap_cObject()
4141  {
4142  $debugKey = '/stdWrap/.cObject';
4143  $content = $this->getUniqueId('content');
4144  $conf = [
4145  'cObject' => $this->getUniqueId('cObject'),
4146  'cObject.' => [$this->getUniqueId('cObject.')],
4147  ];
4148  $return = $this->getUniqueId('return');
4149  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4150  ->setMethods(['cObjGetSingle'])->getMock();
4151  $subject
4152  ->expects($this->once())
4153  ->method('cObjGetSingle')
4154  ->with($conf['cObject'], $conf['cObject.'], $debugKey)
4155  ->willReturn($return);
4156  $this->assertSame(
4157  $return,
4158  $subject->stdWrap_cObject($content, $conf)
4159  );
4160  }
4161 
4168  {
4169  $confA = [$this->getUniqueId('conf A')];
4170  $confB = [$this->getUniqueId('conf B')];
4171  return [
4172  'standard case: order 1, 2' => [
4173  $confA, $confB, ['1.' => $confA, '2.' => $confB]
4174  ],
4175  'inverted: order 2, 1' => [
4176  $confB, $confA, ['2.' => $confA, '1.' => $confB]
4177  ],
4178  '0 as integer: order 0, 2' => [
4179  $confA, $confB, ['0.' => $confA, '2.' => $confB]
4180  ],
4181  'negative integers: order 2, -2' => [
4182  $confB, $confA, ['2.' => $confA, '-2.' => $confB]
4183  ],
4184  'chars are casted to key 0, that is not in the array' => [
4185  null, $confB, ['2.' => $confB, 'xxx.' => $confA]
4186  ],
4187  ];
4188  }
4189 
4212  public function stdWrap_orderedStdWrap($firstConf, $secondConf, $conf)
4213  {
4214  $content = $this->getUniqueId('content');
4215  $between = $this->getUniqueId('between');
4216  $expect = $this->getUniqueId('expect');
4217  $conf['orderedStdWrap.'] = $conf;
4218  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4219  ->setMethods(['stdWrap'])->getMock();
4220  $subject
4221  ->expects($this->exactly(2))
4222  ->method('stdWrap')
4223  ->withConsecutive([$content, $firstConf], [$between, $secondConf])
4224  ->will($this->onConsecutiveCalls($between, $expect));
4225  $this->assertSame(
4226  $expect,
4227  $subject->stdWrap_orderedStdWrap($content, $conf)
4228  );
4229  }
4230 
4237  {
4238  $cacheConf = [$this->getUniqueId('cache.')];
4239  $conf = ['cache.' => $cacheConf];
4240  return [
4241  'no conf' => [
4242  'content', 'content', [],
4243  0, null, null,
4244  ],
4245  'no cache. conf' => [
4246  'content', 'content', ['otherConf' => 1],
4247  0, null, null,
4248  ],
4249  'non-cached simulation' => [
4250  'content', 'content', $conf,
4251  1, $cacheConf, false,
4252  ],
4253  'cached simulation' => [
4254  'cachedContent', 'content', $conf,
4255  1, $cacheConf, 'cachedContent',
4256  ],
4257  ];
4258  }
4259 
4276  public function stdWrap_cacheRead(
4277  $expect,
4278  $input,
4279  $conf,
4280  $times,
4281  $with,
4282  $will
4283  ) {
4284  $subject = $this->getAccessibleMock(
4285  ContentObjectRenderer::class,
4286  ['getFromCache']
4287  );
4288  $subject
4289  ->expects($this->exactly($times))
4290  ->method('getFromCache')
4291  ->with($with)
4292  ->willReturn($will);
4293  $this->assertSame(
4294  $expect,
4295  $subject->stdWrap_cacheRead($input, $conf)
4296  );
4297  }
4298 
4305  {
4306  $confCache = [$this->getUniqueId('cache.')];
4307  $key = [$this->getUniqueId('key')];
4308  return [
4309  'Return immediate with no conf' => [
4310  null, 0, null, 0,
4311  ],
4312  'Return immediate with empty key' => [
4313  $confCache, 1, '0', 0,
4314  ],
4315  'Call all methods' => [
4316  $confCache, 1, $key, 1,
4317  ],
4318  ];
4319  }
4320 
4342  public function stdWrap_cacheStore(
4343  $confCache,
4344  $timesCCK,
4345  $key,
4346  $times
4347  ) {
4348  $content = $this->getUniqueId('content');
4349  $conf['cache.'] = $confCache;
4350  $tags = [$this->getUniqueId('tags')];
4351  $lifetime = $this->getUniqueId('lifetime');
4352  $params = ['key' => $key, 'content' => $content,
4353  'lifetime' => $lifetime, 'tags' => $tags];
4354  $subject = $this->getAccessibleMock(
4355  ContentObjectRenderer::class,
4356  ['calculateCacheKey',
4357  'calculateCacheTags', 'calculateCacheLifetime']
4358  );
4359  $subject
4360  ->expects($this->exactly($timesCCK))
4361  ->method('calculateCacheKey')
4362  ->with($confCache)
4363  ->willReturn($key);
4364  $subject
4365  ->expects($this->exactly($times))
4366  ->method('calculateCacheTags')
4367  ->with($confCache)
4368  ->willReturn($tags);
4369  $subject
4370  ->expects($this->exactly($times))
4371  ->method('calculateCacheLifetime')
4372  ->with($confCache)
4373  ->willReturn($lifetime);
4374  $cacheFrontend = $this->createMock(CacheFrontendInterface::class);
4375  $cacheFrontend
4376  ->expects($this->exactly($times))
4377  ->method('set')
4378  ->with($key, $content, $tags, $lifetime)
4379  ->willReturn($cached);
4380  $cacheManager = $this->createMock(CacheManager::class);
4381  $cacheManager
4382  ->method('getCache')
4383  ->willReturn($cacheFrontend);
4385  CacheManager::class,
4386  $cacheManager
4387  );
4388  list($countCalls, $test) = [0, $this];
4389  $closure = function ($par1, $par2) use (
4390  $test, $subject, $params, &$countCalls) {
4391  $test->assertSame($params, $par1);
4392  $test->assertSame($subject, $par2);
4393  $countCalls++;
4394  };
4395  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap_cacheStore'] = [$closure, $closure, $closure];
4396  $this->assertSame(
4397  $content,
4398  $subject->stdWrap_cacheStore($content, $conf)
4399  );
4400  $this->assertSame($times * 3, $countCalls);
4401  }
4402 
4415  public function stdWrap_case()
4416  {
4417  $content = $this->getUniqueId();
4418  $conf = [
4419  'case' => $this->getUniqueId('used'),
4420  'case.' => [$this->getUniqueId('discarded')],
4421  ];
4422  $return = $this->getUniqueId();
4423  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4424  ->setMethods(['HTMLcaseshift'])->getMock();
4425  $subject
4426  ->expects($this->once())
4427  ->method('HTMLcaseshift')
4428  ->with($content, $conf['case'])
4429  ->willReturn($return);
4430  $this->assertSame(
4431  $return,
4432  $subject->stdWrap_case($content, $conf)
4433  );
4434  }
4435 
4441  public function stdWrap_char()
4442  {
4443  $input = 'discarded';
4444  $expected = 'C';
4445  $this->assertEquals($expected, $this->subject->stdWrap_char($input, ['char' => '67']));
4446  }
4447 
4460  public function stdWrap_crop()
4461  {
4462  $content = $this->getUniqueId('content');
4463  $conf = [
4464  'crop' => $this->getUniqueId('crop'),
4465  'crop.' => $this->getUniqueId('not used'),
4466  ];
4467  $return = $this->getUniqueId('return');
4468  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4469  ->setMethods(['crop'])->getMock();
4470  $subject
4471  ->expects($this->once())
4472  ->method('crop')
4473  ->with($content, $conf['crop'])
4474  ->willReturn($return);
4475  $this->assertSame(
4476  $return,
4477  $subject->stdWrap_crop($content, $conf)
4478  );
4479  }
4480 
4493  public function stdWrap_cropHTML()
4494  {
4495  $content = $this->getUniqueId('content');
4496  $conf = [
4497  'cropHTML' => $this->getUniqueId('cropHTML'),
4498  'cropHTML.' => $this->getUniqueId('not used'),
4499  ];
4500  $return = $this->getUniqueId('return');
4501  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4502  ->setMethods(['cropHTML'])->getMock();
4503  $subject
4504  ->expects($this->once())
4505  ->method('cropHTML')
4506  ->with($content, $conf['cropHTML'])
4507  ->willReturn($return);
4508  $this->assertSame(
4509  $return,
4510  $subject->stdWrap_cropHTML($content, $conf)
4511  );
4512  }
4513 
4519  public function stdWrap_csConvDataProvider()
4520  {
4521  return [
4522  'empty string from ISO-8859-15' => [
4523  '',
4524  mb_convert_encoding('', 'ISO-8859-15', 'UTF-8'),
4525  ['csConv' => 'ISO-8859-15']
4526  ],
4527  'empty string from BIG-5' => [
4528  '',
4529  mb_convert_encoding('', 'BIG-5'),
4530  ['csConv' => 'BIG-5']
4531  ],
4532  '"0" from ISO-8859-15' => [
4533  '0',
4534  mb_convert_encoding('0', 'ISO-8859-15', 'UTF-8'),
4535  ['csConv' => 'ISO-8859-15']
4536  ],
4537  '"0" from BIG-5' => [
4538  '0',
4539  mb_convert_encoding('0', 'BIG-5'),
4540  ['csConv' => 'BIG-5']
4541  ],
4542  'euro symbol from ISO-88859-15' => [
4543  '€',
4544  mb_convert_encoding('€', 'ISO-8859-15', 'UTF-8'),
4545  ['csConv' => 'ISO-8859-15']
4546  ],
4547  'good morning from BIG-5' => [
4548  '早安',
4549  mb_convert_encoding('早安', 'BIG-5'),
4550  ['csConv' => 'BIG-5']
4551  ],
4552  ];
4553  }
4554 
4564  public function stdWrap_csConv($expected, $input, $conf)
4565  {
4566  $this->assertSame(
4567  $expected,
4568  $this->subject->stdWrap_csConv($input, $conf)
4569  );
4570  }
4571 
4583  public function stdWrap_current()
4584  {
4585  $data = [
4586  'currentValue_kidjls9dksoje' => 'default',
4587  'currentValue_new' => 'new',
4588  ];
4589  $this->subject->_set('data', $data);
4590  $this->assertSame(
4591  'currentValue_kidjls9dksoje',
4592  $this->subject->_get('currentValKey')
4593  );
4594  $this->assertSame(
4595  'default',
4596  $this->subject->stdWrap_current('discarded', ['discarded'])
4597  );
4598  $this->subject->_set('currentValKey', 'currentValue_new');
4599  $this->assertSame(
4600  'new',
4601  $this->subject->stdWrap_current('discarded', ['discarded'])
4602  );
4603  }
4604 
4610  public function stdWrap_dataDataProvider()
4611  {
4612  $data = [$this->getUniqueId('data')];
4613  $alt = [$this->getUniqueId('alternativeData')];
4614  return [
4615  'default' => [$data, $data, ''],
4616  'alt is array' => [$alt, $data, $alt],
4617  'alt is empty array' => [[], $data, []],
4618  'alt null' => [$data, $data, null],
4619  'alt string' => [$data, $data, 'xxx'],
4620  'alt int' => [$data, $data, 1],
4621  'alt bool' => [$data, $data, true],
4622  ];
4623  }
4624 
4643  public function stdWrap_data($expect, $data, $alt)
4644  {
4645  $conf = ['data' => $this->getUniqueId('conf.data')];
4646  $return = $this->getUniqueId('return');
4647  $subject = $this->getAccessibleMock(
4648  ContentObjectRenderer::class,
4649  ['getData']
4650  );
4651  $subject->_set('data', $data);
4652  $subject->_set('alternativeData', $alt);
4653  $subject
4654  ->expects($this->once())
4655  ->method('getData')
4656  ->with($conf['data'], $expect)
4657  ->willReturn($return);
4658  $this->assertSame($return, $subject->stdWrap_data('discard', $conf));
4659  $this->assertSame('', $subject->_get('alternativeData'));
4660  }
4661 
4674  public function stdWrap_dataWrap()
4675  {
4676  $content = $this->getUniqueId('content');
4677  $conf = [
4678  'dataWrap' => $this->getUniqueId('dataWrap'),
4679  'dataWrap.' => [$this->getUniqueId('not used')],
4680  ];
4681  $return = $this->getUniqueId('return');
4682  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4683  ->setMethods(['dataWrap'])->getMock();
4684  $subject
4685  ->expects($this->once())
4686  ->method('dataWrap')
4687  ->with($content, $conf['dataWrap'])
4688  ->willReturn($return);
4689  $this->assertSame(
4690  $return,
4691  $subject->stdWrap_dataWrap($content, $conf)
4692  );
4693  }
4694 
4700  public function stdWrap_dateDataProvider()
4701  {
4702  // Fictive execution time: 2015-10-02 12:00
4703  $now = 1443780000;
4704  return [
4705  'given timestamp' => [
4706  '02.10.2015',
4707  $now,
4708  ['date' => 'd.m.Y'],
4709  $now
4710  ],
4711  'empty string' => [
4712  '02.10.2015',
4713  '',
4714  ['date' => 'd.m.Y'],
4715  $now
4716  ],
4717  'testing null' => [
4718  '02.10.2015',
4719  null,
4720  ['date' => 'd.m.Y'],
4721  $now
4722  ],
4723  'given timestamp return GMT' => [
4724  '02.10.2015 10:00:00',
4725  $now,
4726  [
4727  'date' => 'd.m.Y H:i:s',
4728  'date.' => ['GMT' => true],
4729  ],
4730  $now
4731  ]
4732  ];
4733  }
4734 
4745  public function stdWrap_date($expected, $content, $conf, $now)
4746  {
4747  $GLOBALS['EXEC_TIME'] = $now;
4748  $this->assertEquals(
4749  $expected,
4750  $this->subject->stdWrap_date($content, $conf)
4751  );
4752  }
4753 
4759  public function stdWrap_debug()
4760  {
4761  $expect = '<pre>&lt;p class=&quot;class&quot;&gt;&lt;br/&gt;'
4762  . '&lt;/p&gt;</pre>';
4763  $content = '<p class="class"><br/></p>';
4764  $this->assertSame($expect, $this->subject->stdWrap_debug($content));
4765  }
4766 
4793  public function stdWrap_debugData()
4794  {
4795  $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'] = '*';
4796  $content = $this->getUniqueId('content');
4797  $key = $this->getUniqueId('key');
4798  $value = $this->getUniqueId('value');
4799  $altValue = $this->getUniqueId('value alt');
4800  $this->subject->data = [$key => $value];
4801  // Without alternative data only data is returned.
4802  ob_start();
4803  $result = $this->subject->stdWrap_debugData($content);
4804  $out = ob_get_clean();
4805  $this->assertSame($result, $content);
4806  $this->assertContains('$cObj->data', $out);
4807  $this->assertContains($value, $out);
4808  $this->assertNotContains($altValue, $out);
4809  // By adding alternative data both are returned together.
4810  $this->subject->alternativeData = [$key => $altValue];
4811  ob_start();
4812  $this->subject->stdWrap_debugData($content);
4813  $out = ob_get_clean();
4814  $this->assertNotContains('$cObj->alternativeData', $out);
4815  $this->assertContains($value, $out);
4816  $this->assertContains($altValue, $out);
4817  }
4818 
4819  /*
4820  * Data provider for stdWrap_debugFunc.
4821  *
4822  * @return array [$expectArray, $confDebugFunc]
4823  */
4825  {
4826  return [
4827  'expect array by string' => [ true, '2' ],
4828  'expect array by integer' => [ true, 2 ],
4829  'do not expect array' => [ false, '' ],
4830  ];
4831  }
4832 
4854  public function stdWrap_debugFunc($expectArray, $confDebugFunc)
4855  {
4856  $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'] = '*';
4857  $content = $this->getUniqueId('content');
4858  $conf = ['debugFunc' => $confDebugFunc];
4859  ob_start();
4860  $result = $this->subject->stdWrap_debugFunc($content, $conf);
4861  $out = ob_get_clean();
4862  $this->assertSame($result, $content);
4863  $this->assertContains($content, $out);
4864  if ($expectArray) {
4865  $this->assertContains('=>', $out);
4866  } else {
4867  $this->assertNotContains('=>', $out);
4868  }
4869  }
4870 
4877  {
4878  return [
4879  'no config: void input' => [
4880  '',
4881  '',
4882  [],
4883  ],
4884  'no config: single break' => [
4885  'one' . LF . 'two',
4886  'one' . LF . 'two',
4887  [],
4888  ],
4889  'no config: double break' => [
4890  'onetwo',
4891  'one' . LF . LF . 'two',
4892  [],
4893  ],
4894  'no config: double break with whitespace' => [
4895  'onetwo',
4896  'one' . LF . TAB . ' ' . TAB . ' ' . LF . 'two',
4897  [],
4898  ],
4899  'no config: single break around' => [
4900  LF . 'one' . LF,
4901  LF . 'one' . LF,
4902  [],
4903  ],
4904  'no config: double break around' => [
4905  'one',
4906  LF . LF . 'one' . LF . LF,
4907  [],
4908  ],
4909  'empty string: double break around' => [
4910  'one',
4911  LF . LF . 'one' . LF . LF,
4912  ['doubleBrTag' => ''],
4913  ],
4914  'br tag: double break' => [
4915  'one<br/>two',
4916  'one' . LF . LF . 'two',
4917  ['doubleBrTag' => '<br/>'],
4918  ],
4919  'br tag: double break around' => [
4920  '<br/>one<br/>',
4921  LF . LF . 'one' . LF . LF,
4922  ['doubleBrTag' => '<br/>'],
4923  ],
4924  'double br tag: double break around' => [
4925  '<br/><br/>one<br/><br/>',
4926  LF . LF . 'one' . LF . LF,
4927  ['doubleBrTag' => '<br/><br/>'],
4928  ],
4929  ];
4930  }
4931 
4941  public function stdWrap_doubleBrTag($expected, $input, $config)
4942  {
4943  $this->assertEquals($expected, $this->subject->stdWrap_doubleBrTag($input, $config));
4944  }
4945 
4952  {
4953  $content = $this->getUniqueId('content');
4954  $editIcons = $this->getUniqueId('editIcons');
4955  $editIconsArray = [$this->getUniqueId('editIcons.')];
4956  $will = $this->getUniqueId('will');
4957  return [
4958  'standard case calls edit icons' => [
4959  $will, $content,
4960  ['editIcons' => $editIcons, 'editIcons.' => $editIconsArray],
4961  true, 1, $editIconsArray, $will
4962  ],
4963  'null in editIcons. repalaced by []' => [
4964  $will, $content,
4965  ['editIcons' => $editIcons, 'editIcons.' => null],
4966  true, 1, [], $will
4967  ],
4968  'missing editIcons. replaced by []' => [
4969  $will, $content,
4970  ['editIcons' => $editIcons],
4971  true, 1, [], $will
4972  ],
4973  'no user login disables call' => [
4974  $content, $content,
4975  ['editIcons' => $editIcons, 'editIcons.' => $editIconsArray],
4976  false, 0, $editIconsArray, $will
4977  ],
4978  'empty string in editIcons disables call' => [
4979  $content, $content,
4980  ['editIcons' => '', 'editIcons.' => $editIconsArray],
4981  true, 0, $editIconsArray, $will
4982  ],
4983  'zero string in editIcons disables call' => [
4984  $content, $content,
4985  ['editIcons' => '0', 'editIcons.' => $editIconsArray],
4986  true, 0, $editIconsArray, $will
4987  ],
4988  ];
4989  }
4990 
5017  public function stdWrap_editIcons(
5018  $expect,
5019  $content,
5020  $conf,
5021  $login,
5022  $times,
5023  $param3,
5024  $will
5025  ) {
5026  $GLOBALS['TSFE']->beUserLogin = $login;
5027  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5028  ->setMethods(['editIcons'])->getMock();
5029  $subject
5030  ->expects($this->exactly($times))
5031  ->method('editIcons')
5032  ->with($content, $conf['editIcons'], $param3)
5033  ->willReturn($will);
5034  $this->assertSame(
5035  $expect,
5036  $subject->stdWrap_editIcons($content, $conf)
5037  );
5038  }
5039 
5052  public function stdWrap_encapsLines()
5053  {
5054  $content = $this->getUniqueId('content');
5055  $conf = [
5056  'encapsLines' => [$this->getUniqueId('not used')],
5057  'encapsLines.' => [$this->getUniqueId('encapsLines.')],
5058  ];
5059  $return = $this->getUniqueId('return');
5060  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5061  ->setMethods(['encaps_lineSplit'])->getMock();
5062  $subject
5063  ->expects($this->once())
5064  ->method('encaps_lineSplit')
5065  ->with($content, $conf['encapsLines.'])
5066  ->willReturn($return);
5067  $this->assertSame(
5068  $return,
5069  $subject->stdWrap_encapsLines($content, $conf)
5070  );
5071  }
5072 
5081  public function stdWrap_encapsLines_HTML5SelfClosingTags(string $input, string $expected)
5082  {
5083  $rteParseFunc = $this->getLibParseFunc_RTE();
5084 
5085  $conf = [
5086  'encapsLines' => $rteParseFunc['parseFunc.']['nonTypoTagStdWrap.']['encapsLines'],
5087  'encapsLines.' => $rteParseFunc['parseFunc.']['nonTypoTagStdWrap.']['encapsLines.'],
5088  ];
5089  // don't add an &nbsp; to tag without content
5090  $conf['encapsLines.']['innerStdWrap_all.']['ifBlank'] = '';
5091  $additionalEncapsTags = ['a', 'b', 'span'];
5092 
5093  // We want to allow any tag to be an encapsulating tag
5094  // since this is possible and we don't want an additional tag to be wrapped around.
5095  $conf['encapsLines.']['encapsTagList'] .= ',' . implode(',', $additionalEncapsTags);
5096  $conf['encapsLines.']['encapsTagList'] .= ',' . implode(',', [$input]);
5097 
5098  // Check if we get a self-closing tag for
5099  // empty tags where this is allowed according to HTML5
5100  $content = '<' . $input . ' id="myId" class="bodytext" />';
5101  $result = $this->subject->stdWrap_encapsLines($content, $conf);
5102  $this->assertSame($expected, $result);
5103  }
5104 
5106  {
5107  return [
5108  'areaTag_selfclosing' => [
5109  'input' => 'area',
5110  'expected' => '<area id="myId" class="bodytext" />'
5111  ],
5112  'base_selfclosing' => [
5113  'input' => 'base',
5114  'expected' => '<base id="myId" class="bodytext" />'
5115  ],
5116  'br_selfclosing' => [
5117  'input' => 'br',
5118  'expected' => '<br id="myId" class="bodytext" />'
5119  ],
5120  'col_selfclosing' => [
5121  'input' => 'col',
5122  'expected' => '<col id="myId" class="bodytext" />'
5123  ],
5124  'embed_selfclosing' => [
5125  'input' => 'embed',
5126  'expected' => '<embed id="myId" class="bodytext" />'
5127  ],
5128  'hr_selfclosing' => [
5129  'input' => 'hr',
5130  'expected' => '<hr id="myId" class="bodytext" />'
5131  ],
5132  'img_selfclosing' => [
5133  'input' => 'img',
5134  'expected' => '<img id="myId" class="bodytext" />'
5135  ],
5136  'input_selfclosing' => [
5137  'input' => 'input',
5138  'expected' => '<input id="myId" class="bodytext" />'
5139  ],
5140  'keygen_selfclosing' => [
5141  'input' => 'keygen',
5142  'expected' => '<keygen id="myId" class="bodytext" />'
5143  ],
5144  'link_selfclosing' => [
5145  'input' => 'link',
5146  'expected' => '<link id="myId" class="bodytext" />'
5147  ],
5148  'meta_selfclosing' => [
5149  'input' => 'meta',
5150  'expected' => '<meta id="myId" class="bodytext" />'
5151  ],
5152  'param_selfclosing' => [
5153  'input' => 'param',
5154  'expected' => '<param id="myId" class="bodytext" />'
5155  ],
5156  'source_selfclosing' => [
5157  'input' => 'source',
5158  'expected' => '<source id="myId" class="bodytext" />'
5159  ],
5160  'track_selfclosing' => [
5161  'input' => 'track',
5162  'expected' => '<track id="myId" class="bodytext" />'
5163  ],
5164  'wbr_selfclosing' => [
5165  'input' => 'wbr',
5166  'expected' => '<wbr id="myId" class="bodytext" />'
5167  ],
5168  'p_notselfclosing' => [
5169  'input' => 'p',
5170  'expected' => '<p id="myId" class="bodytext"></p>'
5171  ],
5172  'a_notselfclosing' => [
5173  'input' => 'a',
5174  'expected' => '<a id="myId" class="bodytext"></a>'
5175  ],
5176  'strong_notselfclosing' => [
5177  'input' => 'strong',
5178  'expected' => '<strong id="myId" class="bodytext"></strong>'
5179  ],
5180  'span_notselfclosing' => [
5181  'input' => 'span',
5182  'expected' => '<span id="myId" class="bodytext"></span>'
5183  ],
5184  ];
5185  }
5186 
5193  {
5194  $content = $this->getUniqueId('content');
5195  $will = $this->getUniqueId('will');
5196  return [
5197  'standard case calls edit icons' => [
5198  $will, $content, true, 1, $will
5199  ],
5200  'no user login disables call' => [
5201  $content, $content, false, 0, $will
5202  ],
5203  ];
5204  }
5205 
5227  public function stdWrap_editPanel(
5228  $expect,
5229  $content,
5230  $login,
5231  $times,
5232  $will
5233  ) {
5234  $GLOBALS['TSFE']->beUserLogin = $login;
5235  $conf = ['editPanel.' => [$this->getUniqueId('editPanel.')]];
5236  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5237  ->setMethods(['editPanel'])->getMock();
5238  $subject
5239  ->expects($this->exactly($times))
5240  ->method('editPanel')
5241  ->with($content, $conf['editPanel.'])
5242  ->willReturn($will);
5243  $this->assertSame(
5244  $expect,
5245  $subject->stdWrap_editPanel($content, $conf)
5246  );
5247  }
5248 
5255  {
5256  return [
5257  'double quote in string' => [
5258  '\'double\u0020quote\u0022\'', 'double quote"'
5259  ],
5260  'backslash in string' => [
5261  '\'backslash\u0020\u005C\'', 'backslash \\'
5262  ],
5263  'exclamation mark' => [
5264  '\'exclamation\u0021\'', 'exclamation!'
5265  ],
5266  'whitespace tab, newline and carriage return' => [
5267  '\'white\u0009space\u000As\u000D\'', "white\tspace\ns\r"
5268  ],
5269  'single quote in string' => [
5270  '\'single\u0020quote\u0020\u0027\'', 'single quote \''
5271  ],
5272  'tag' => [
5273  '\'\u003Ctag\u003E\'', '<tag>'
5274  ],
5275  'ampersand in string' => [
5276  '\'amper\u0026sand\'', 'amper&sand'
5277  ]
5278  ];
5279  }
5280 
5289  public function stdWrap_encodeForJavaScriptValue($expect, $content)
5290  {
5291  $this->assertSame(
5292  $expect,
5293  $this->subject->stdWrap_encodeForJavaScriptValue($content)
5294  );
5295  }
5296 
5303  {
5304  return [
5305  'numbers' => ['1,2,3', '1,2,3'],
5306  'range' => ['3,4,5', '3-5'],
5307  'numbers and range' => ['1,3,4,5,7', '1,3-5,7']
5308  ];
5309  }
5310 
5324  public function stdWrap_expandList($expected, $content)
5325  {
5326  $this->assertEquals(
5327  $expected,
5328  $this->subject->stdWrap_expandList($content)
5329  );
5330  }
5331 
5342  public function stdWrap_field()
5343  {
5344  $expect = $this->getUniqueId('expect');
5345  $conf = ['field' => $this->getUniqueId('field')];
5346  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5347  ->setMethods(['getFieldVal'])->getMock();
5348  $subject
5349  ->expects($this->once())
5350  ->method('getFieldVal')
5351  ->with($conf['field'])
5352  ->willReturn($expect);
5353  $this->assertSame(
5354  $expect,
5355  $subject->stdWrap_field('discarded', $conf)
5356  );
5357  }
5358 
5365  {
5366  $content = $this->getUniqueId('content');
5367  return [
5368  // resulting in boolean false
5369  'false is false' => [
5370  '', true, $content, ['fieldRequired' => 'false']
5371  ],
5372  'null is false' => [
5373  '', true, $content, ['fieldRequired' => 'null']
5374  ],
5375  'empty string is false' => [
5376  '', true, $content, ['fieldRequired' => 'empty']
5377  ],
5378  'whitespace is false' => [
5379  '', true, $content, ['fieldRequired' => 'whitespace']
5380  ],
5381  'string zero is false' => [
5382  '', true, $content, ['fieldRequired' => 'stringZero']
5383  ],
5384  'string zero with whitespace is false' => [
5385  '', true, $content,
5386  ['fieldRequired' => 'stringZeroWithWhiteSpace']
5387  ],
5388  'zero is false' => [
5389  '', true, $content, ['fieldRequired' => 'zero']
5390  ],
5391  // resulting in boolean true
5392  'true is true' => [
5393  $content, false, $content, ['fieldRequired' => 'true']
5394  ],
5395  'string is true' => [
5396  $content, false, $content, ['fieldRequired' => 'string']
5397  ],
5398  'one is true' => [
5399  $content, false, $content, ['fieldRequired' => 'one']
5400  ]
5401  ];
5402  }
5403 
5423  public function stdWrap_fieldRequired($expect, $stop, $content, $conf)
5424  {
5425  $data = [
5426  'null' => null,
5427  'false' => false,
5428  'empty' => '',
5429  'whitespace' => TAB . ' ',
5430  'stringZero' => '0',
5431  'stringZeroWithWhiteSpace' => TAB . ' 0 ' . TAB,
5432  'zero' => 0,
5433  'string' => 'string',
5434  'true' => true,
5435  'one' => 1
5436  ];
5438  $subject->_set('data', $data);
5439  $subject->_set('stdWrapRecursionLevel', 1);
5440  $subject->_set('stopRendering', [1 => false]);
5441  $this->assertSame(
5442  $expect,
5443  $subject->stdWrap_fieldRequired($content, $conf)
5444  );
5445  $this->assertSame($stop, $subject->_get('stopRendering')[1]);
5446  }
5447 
5460  public function stdWrap_filelink()
5461  {
5462  $content = $this->getUniqueId('content');
5463  $conf = [
5464  'filelink' => $this->getUniqueId('not used'),
5465  'filelink.' => [$this->getUniqueId('filelink.')],
5466  ];
5467  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5468  ->setMethods(['filelink'])->getMock();
5469  $subject->expects($this->once())->method('filelink')
5470  ->with($content, $conf['filelink.'])->willReturn('return');
5471  $this->assertSame(
5472  'return',
5473  $subject->stdWrap_filelink($content, $conf)
5474  );
5475  }
5476 
5488  public function stdWrap_filelist()
5489  {
5490  $conf = [
5491  'filelist' => $this->getUniqueId('filelist'),
5492  'filelist.' => [$this->getUniqueId('not used')],
5493  ];
5494  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5495  ->setMethods(['filelist'])->getMock();
5496  $subject->expects($this->once())->method('filelist')
5497  ->with($conf['filelist'])->willReturn('return');
5498  $this->assertSame(
5499  'return',
5500  $subject->stdWrap_filelist('discard', $conf)
5501  );
5502  }
5503 
5509  public function hashDataProvider()
5510  {
5511  return [
5512  'md5' => [
5513  'bacb98acf97e0b6112b1d1b650b84971',
5514  'joh316',
5515  ['hash' => 'md5']
5516  ],
5517  'sha1' => [
5518  '063b3d108bed9f88fa618c6046de0dccadcf3158',
5519  'joh316',
5520  ['hash' => 'sha1']
5521  ],
5522  'stdWrap capability' => [
5523  'bacb98acf97e0b6112b1d1b650b84971',
5524  'joh316',
5525  [
5526  'hash' => '5',
5527  'hash.' => ['wrap' => 'md|']
5528  ]
5529  ],
5530  'non-existing hashing algorithm' => [
5531  '',
5532  'joh316',
5533  ['hash' => 'non-existing']
5534  ]
5535  ];
5536  }
5537 
5553  public function stdWrap_hash($expect, $content, $conf)
5554  {
5555  $this->assertSame(
5556  $expect,
5557  $this->subject->stdWrap_hash($content, $conf)
5558  );
5559  }
5560 
5567  {
5568  return [
5569  'void conf' => [
5570  '&lt;span&gt;1 &amp;lt; 2&lt;/span&gt;',
5571  '<span>1 &lt; 2</span>',
5572  [],
5573  ],
5574  'void preserveEntities' => [
5575  '&lt;span&gt;1 &amp;lt; 2&lt;/span&gt;',
5576  '<span>1 &lt; 2</span>',
5577  ['htmlSpecialChars.' => []],
5578  ],
5579  'false preserveEntities' => [
5580  '&lt;span&gt;1 &amp;lt; 2&lt;/span&gt;',
5581  '<span>1 &lt; 2</span>',
5582  ['htmlSpecialChars.' => ['preserveEntities' => 0]],
5583  ],
5584  'true preserveEntities' => [
5585  '&lt;span&gt;1 &lt; 2&lt;/span&gt;',
5586  '<span>1 &lt; 2</span>',
5587  ['htmlSpecialChars.' => ['preserveEntities' => 1]],
5588  ],
5589  ];
5590  }
5591 
5601  public function stdWrap_htmlSpecialChars($expected, $input, $conf)
5602  {
5603  $this->assertSame(
5604  $expected,
5605  $this->subject->stdWrap_htmlSpecialChars($input, $conf)
5606  );
5607  }
5608 
5614  public function stdWrap_ifDataProvider()
5615  {
5616  $content = $this->getUniqueId('content');
5617  $conf = ['if.' => [$this->getUniqueId('if.')]];
5618  return [
5619  // evals to true
5620  'empty config' => [
5621  $content, false, $content, [], 0, null
5622  ],
5623  'if. is empty array' => [
5624  $content, false, $content, ['if.' => []], 0, null
5625  ],
5626  'if. is null' => [
5627  $content, false, $content, ['if.' => null], 0, null
5628  ],
5629  'if. is false' => [
5630  $content, false, $content, ['if.' => false], 0, null
5631  ],
5632  'if. is 0' => [
5633  $content, false, $content, ['if.' => false], 0, null
5634  ],
5635  'if. is "0"' => [
5636  $content, false, $content, ['if.' => '0'], 0, null
5637  ],
5638  'checkIf returning true' => [
5639  $content, false, $content, $conf, 1, true
5640  ],
5641  // evals to false
5642  'checkIf returning false' => [
5643  '', true, $content, $conf, 1, false
5644  ],
5645  ];
5646  }
5647 
5668  public function stdWrap_if($expect, $stop, $content, $conf, $times, $will)
5669  {
5670  $subject = $this->getAccessibleMock(
5671  ContentObjectRenderer::class,
5672  ['checkIf']
5673  );
5674  $subject->_set('stdWrapRecursionLevel', 1);
5675  $subject->_set('stopRendering', [1 => false]);
5676  $subject
5677  ->expects($this->exactly($times))
5678  ->method('checkIf')
5679  ->with($conf['if.'])
5680  ->willReturn($will);
5681  $this->assertSame($expect, $subject->stdWrap_if($content, $conf));
5682  $this->assertSame($stop, $subject->_get('stopRendering')[1]);
5683  }
5684 
5691  {
5692  $alt = $this->getUniqueId('alternative content');
5693  $conf = ['ifBlank' => $alt];
5694  return [
5695  // blank cases
5696  'null is blank' => [$alt, null, $conf],
5697  'false is blank' => [$alt, false, $conf],
5698  'empty string is blank' => [$alt, '', $conf],
5699  'whitespace is blank' => [$alt, TAB . '', $conf],
5700  // non-blank cases
5701  'string is not blank' => ['string', 'string', $conf],
5702  'zero is not blank' => [0, 0, $conf],
5703  'zero string is not blank' => ['0', '0', $conf],
5704  'zero float is not blank' => [0.0, 0.0, $conf],
5705  'true is not blank' => [true, true, $conf],
5706  ];
5707  }
5708 
5725  public function stdWrap_ifBlank($expect, $content, $conf)
5726  {
5727  $result = $this->subject->stdWrap_ifBlank($content, $conf);
5728  $this->assertSame($expect, $result);
5729  }
5730 
5737  {
5738  $alt = $this->getUniqueId('alternative content');
5739  $conf = ['ifEmpty' => $alt];
5740  return [
5741  // empty cases
5742  'null is empty' => [$alt, null, $conf ],
5743  'false is empty' => [$alt, false, $conf ],
5744  'zero is empty' => [$alt, 0, $conf ],
5745  'float zero is empty' => [$alt, 0.0, $conf ],
5746  'whitespace is empty' => [$alt, TAB . ' ', $conf ],
5747  'empty string is empty' => [$alt, '', $conf ],
5748  'zero string is empty' => [$alt, '0', $conf ],
5749  'zero string is empty with whitespace' => [
5750  $alt, TAB . ' 0 ' . TAB, $conf
5751  ],
5752  // non-empty cases
5753  'string is not empty' => ['string', 'string', $conf ],
5754  '1 is not empty' => [1, 1, $conf ],
5755  '-1 is not empty' => [-1, -1, $conf ],
5756  '0.1 is not empty' => [0.1, 0.1, $conf ],
5757  '-0.1 is not empty' => [-0.1, -0.1, $conf ],
5758  'true is not empty' => [true, true, $conf ],
5759  ];
5760  }
5761 
5777  public function stdWrap_ifEmpty($expect, $content, $conf)
5778  {
5779  $result = $this->subject->stdWrap_ifEmpty($content, $conf);
5780  $this->assertSame($expect, $result);
5781  }
5782 
5788  public function stdWrap_ifNullDataProvider()
5789  {
5790  $alt = $this->getUniqueId('alternative content');
5791  $conf = ['ifNull' => $alt];
5792  return [
5793  'only null is null' => [$alt, null, $conf],
5794  'zero is not null' => [0, 0, $conf],
5795  'float zero is not null' => [0.0, 0.0, $conf],
5796  'false is not null' => [false, false, $conf],
5797  'zero is not null' => [0, 0, $conf],
5798  'zero string is not null' => ['0', '0', $conf],
5799  'empty string is not null' => ['', '', $conf],
5800  'whitespace is not null' => [TAB . '', TAB . '', $conf],
5801  ];
5802  }
5803 
5819  public function stdWrap_ifNull($expect, $content, $conf)
5820  {
5821  $result = $this->subject->stdWrap_ifNull($content, $conf);
5822  $this->assertSame($expect, $result);
5823  }
5824 
5831  {
5832  return [
5833  'no conf' => [
5834  'XXX',
5835  'XXX',
5836  [],
5837  ],
5838  'simple' => [
5839  '<wrap>XXX</wrap>',
5840  'XXX',
5841  ['innerWrap' => '<wrap>|</wrap>'],
5842  ],
5843  'missing pipe puts wrap before' => [
5844  '<pre>XXX',
5845  'XXX',
5846  ['innerWrap' => '<pre>'],
5847  ],
5848  'trims whitespace' => [
5849  '<wrap>XXX</wrap>',
5850  'XXX',
5851  ['innerWrap' => '<wrap>' . TAB . ' | ' . TAB . '</wrap>'],
5852  ],
5853  'split char change is not possible' => [
5854  '<wrap> # </wrap>XXX',
5855  'XXX',
5856  [
5857  'innerWrap' => '<wrap> # </wrap>',
5858  'innerWrap.' => ['splitChar' => '#'],
5859  ],
5860  ],
5861  ];
5862  }
5863 
5873  public function stdWrap_innerWrap($expected, $input, $conf)
5874  {
5875  $this->assertSame(
5876  $expected,
5877  $this->subject->stdWrap_innerWrap($input, $conf)
5878  );
5879  }
5880 
5887  {
5888  return [
5889  'no conf' => [
5890  'XXX',
5891  'XXX',
5892  [],
5893  ],
5894  'simple' => [
5895  '<wrap>XXX</wrap>',
5896  'XXX',
5897  ['innerWrap2' => '<wrap>|</wrap>'],
5898  ],
5899  'missing pipe puts wrap before' => [
5900  '<pre>XXX',
5901  'XXX',
5902  ['innerWrap2' => '<pre>'],
5903  ],
5904  'trims whitespace' => [
5905  '<wrap>XXX</wrap>',
5906  'XXX',
5907  ['innerWrap2' => '<wrap>' . TAB . ' | ' . TAB . '</wrap>'],
5908  ],
5909  'split char change is not possible' => [
5910  '<wrap> # </wrap>XXX',
5911  'XXX',
5912  [
5913  'innerWrap2' => '<wrap> # </wrap>',
5914  'innerWrap2.' => ['splitChar' => '#'],
5915  ],
5916  ],
5917  ];
5918  }
5919 
5929  public function stdWrap_innerWrap2($expected, $input, $conf)
5930  {
5931  $this->assertSame(
5932  $expected,
5933  $this->subject->stdWrap_innerWrap2($input, $conf)
5934  );
5935  }
5936 
5948  public function stdWrap_insertData()
5949  {
5950  $content = $this->getUniqueId('content');
5951  $conf = [$this->getUniqueId('conf not used')];
5952  $return = $this->getUniqueId('return');
5953  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5954  ->setMethods(['insertData'])->getMock();
5955  $subject->expects($this->once())->method('insertData')
5956  ->with($content)->willReturn($return);
5957  $this->assertSame(
5958  $return,
5959  $subject->stdWrap_insertData($content, $conf)
5960  );
5961  }
5962 
5968  public function stdWrap_insertDataProvider()
5969  {
5970  return [
5971  'empty' => ['', ''],
5972  'notFoundData' => ['any=1', 'any{$string}=1'],
5973  'queryParameter' => ['any{#string}=1', 'any{#string}=1'],
5974  ];
5975  }
5976 
5985  public function stdWrap_insertDataAndInputExamples($expect, $content)
5986  {
5987  $this->assertSame($expect, $this->subject->stdWrap_insertData($content));
5988  }
5989 
5995  public function stdWrap_intvalDataProvider()
5996  {
5997  return [
5998  // numbers
5999  'int' => [123, 123],
6000  'float' => [123, 123.45],
6001  'float does not round up' => [123, 123.55],
6002  // negative numbers
6003  'negative int' => [-123, -123],
6004  'negative float' => [-123, -123.45],
6005  'negative float does not round down' => [-123, -123.55],
6006  // strings
6007  'word string' => [0, 'string'],
6008  'empty string' => [0, ''],
6009  'zero string' => [0, '0'],
6010  'int string' => [123, '123'],
6011  'float string' => [123, '123.55'],
6012  'negative float string' => [-123, '-123.55'],
6013  // other types
6014  'null' => [0, null],
6015  'true' => [1, true],
6016  'false' => [0, false]
6017  ];
6018  }
6019 
6039  public function stdWrap_intval($expect, $content)
6040  {
6041  $this->assertSame($expect, $this->subject->stdWrap_intval($content));
6042  }
6043 
6050  {
6051  return [
6052  'empty string' => ['', ''],
6053  'blank' => ['', ' '],
6054  'tab' => ['', "\t"],
6055  'single semicolon' => [',', ' ; '],
6056  'single comma' => [',', ' , '],
6057  'single nl' => [',', ' ' . PHP_EOL . ' '],
6058  'double semicolon' => [',,', ' ; ; '],
6059  'double comma' => [',,', ' , , '],
6060  'double nl' => [',,', ' ' . PHP_EOL . ' ' . PHP_EOL . ' '],
6061  'simple word' => ['one', ' one '],
6062  'simple word trimmed' => ['one', 'one'],
6063  ', separated' => ['one,two', ' one , two '],
6064  '; separated' => ['one,two', ' one ; two '],
6065  'nl separated' => ['one,two', ' one ' . PHP_EOL . ' two '],
6066  ', typical' => ['one,two,three', 'one, two, three'],
6067  '; typical' => ['one,two,three', ' one; two; three'],
6068  'nl typical' => [
6069  'one,two,three',
6070  'one' . PHP_EOL . 'two' . PHP_EOL . 'three'
6071  ],
6072  ', sourounded' => [',one,two,', ' , one , two , '],
6073  '; sourounded' => [',one,two,', ' ; one ; two ; '],
6074  'nl sourounded' => [
6075  ',one,two,',
6076  ' ' . PHP_EOL . ' one ' . PHP_EOL . ' two ' . PHP_EOL . ' '
6077  ],
6078  'mixed' => [
6079  'one,two,three,four',
6080  ' one, two; three' . PHP_EOL . 'four'
6081  ],
6082  'keywods with blanks in words' => [
6083  'one plus,two minus',
6084  ' one plus , two minus ',
6085  ]
6086  ];
6087  }
6088 
6097  public function stdWrap_keywords($expected, $input)
6098  {
6099  $this->assertSame($expected, $this->subject->stdWrap_keywords($input));
6100  }
6101 
6107  public function stdWrap_langDataProvider()
6108  {
6109  return [
6110  'empty conf' => [
6111  'original',
6112  'original',
6113  [],
6114  'de',
6115  ],
6116  'translation de' => [
6117  'Ãœbersetzung',
6118  'original',
6119  [
6120  'lang.' => [
6121  'de' => 'Ãœbersetzung',
6122  'it' => 'traduzione',
6123  ]
6124  ],
6125  'de',
6126  ],
6127  'translation it' => [
6128  'traduzione',
6129  'original',
6130  [
6131  'lang.' => [
6132  'de' => 'Ãœbersetzung',
6133  'it' => 'traduzione',
6134  ]
6135  ],
6136  'it',
6137  ],
6138  'no translation' => [
6139  'original',
6140  'original',
6141  [
6142  'lang.' => [
6143  'de' => 'Ãœbersetzung',
6144  'it' => 'traduzione',
6145  ]
6146  ],
6147  '',
6148  ],
6149  'missing label' => [
6150  'original',
6151  'original',
6152  [
6153  'lang.' => [
6154  'de' => 'Ãœbersetzung',
6155  'it' => 'traduzione',
6156  ]
6157  ],
6158  'fr',
6159  ],
6160  ];
6161  }
6162 
6173  public function stdWrap_lang($expected, $input, $conf, $language)
6174  {
6175  if ($language) {
6176  $this->frontendControllerMock
6177  ->config['config']['language'] = $language;
6178  }
6179  $this->assertSame(
6180  $expected,
6181  $this->subject->stdWrap_lang($input, $conf)
6182  );
6183  }
6184 
6198  public function stdWrap_listNum()
6199  {
6200  $content = $this->getUniqueId('content');
6201  $conf = [
6202  'listNum' => $this->getUniqueId('listNum'),
6203  'listNum.' => [
6204  'splitChar' => $this->getUniqueId('splitChar')
6205  ],
6206  ];
6207  $return = $this->getUniqueId('return');
6208  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6209  ->setMethods(['listNum'])->getMock();
6210  $subject
6211  ->expects($this->once())
6212  ->method('listNum')
6213  ->with(
6214  $content,
6215  $conf['listNum'],
6216  $conf['listNum.']['splitChar']
6217  )
6218  ->willReturn($return);
6219  $this->assertSame(
6220  $return,
6221  $subject->stdWrap_listNum($content, $conf)
6222  );
6223  }
6224 
6231  {
6232  return [
6233  'Standard case' => [
6234  ' left middle right ',
6235  'middle',
6236  [
6237  'noTrimWrap' => '| left | right |',
6238  ],
6239  ],
6240  'Tabs as whitespace' => [
6241  TAB . 'left' . TAB . 'middle' . TAB . 'right' . TAB,
6242  'middle',
6243  [
6244  'noTrimWrap' =>
6245  '|' . TAB . 'left' . TAB . '|' . TAB . 'right' . TAB . '|',
6246  ],
6247  ],
6248  'Split char is 0' => [
6249  ' left middle right ',
6250  'middle',
6251  [
6252  'noTrimWrap' => '0 left 0 right 0',
6253  'noTrimWrap.' => ['splitChar' => '0'],
6254  ],
6255  ],
6256  'Split char is pipe (default)' => [
6257  ' left middle right ',
6258  'middle',
6259  [
6260  'noTrimWrap' => '| left | right |',
6261  'noTrimWrap.' => ['splitChar' => '|'],
6262  ],
6263  ],
6264  'Split char is a' => [
6265  ' left middle right ',
6266  'middle',
6267  [
6268  'noTrimWrap' => 'a left a right a',
6269  'noTrimWrap.' => ['splitChar' => 'a'],
6270  ],
6271  ],
6272  'Split char is a word (ab)' => [
6273  ' left middle right ',
6274  'middle',
6275  [
6276  'noTrimWrap' => 'ab left ab right ab',
6277  'noTrimWrap.' => ['splitChar' => 'ab'],
6278  ],
6279  ],
6280  'Split char accepts stdWrap' => [
6281  ' left middle right ',
6282  'middle',
6283  [
6284  'noTrimWrap' => 'abc left abc right abc',
6285  'noTrimWrap.' => [
6286  'splitChar' => 'b',
6287  'splitChar.' => ['wrap' => 'a|c'],
6288  ],
6289  ],
6290  ],
6291  ];
6292  }
6293 
6303  public function stdWrap_noTrimWrap($expect, $content, $conf)
6304  {
6305  $this->assertSame(
6306  $expect,
6307  $this->subject->stdWrap_noTrimWrap($content, $conf)
6308  );
6309  }
6310 
6322  public function stdWrap_numRows()
6323  {
6324  $conf = [
6325  'numRows' => $this->getUniqueId('numRows'),
6326  'numRows.' => [$this->getUniqueId('numRows')],
6327  ];
6328  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6329  ->setMethods(['numRows'])->getMock();
6330  $subject->expects($this->once())->method('numRows')
6331  ->with($conf['numRows.'])->willReturn('return');
6332  $this->assertSame(
6333  'return',
6334  $subject->stdWrap_numRows('discard', $conf)
6335  );
6336  }
6337 
6350  public function stdWrap_numberFormat()
6351  {
6352  $content = $this->getUniqueId('content');
6353  $conf = [
6354  'numberFormat' => $this->getUniqueId('not used'),
6355  'numberFormat.' => [$this->getUniqueId('numberFormat.')],
6356  ];
6357  $return = $this->getUniqueId('return');
6358  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6359  ->setMethods(['numberFormat'])->getMock();
6360  $subject
6361  ->expects($this->once())
6362  ->method('numberFormat')
6363  ->with($content, $conf['numberFormat.'])
6364  ->willReturn($return);
6365  $this->assertSame(
6366  $return,
6367  $subject->stdWrap_numberFormat($content, $conf)
6368  );
6369  }
6370 
6377  {
6378  return [
6379  'no conf' => [
6380  'XXX',
6381  'XXX',
6382  [],
6383  ],
6384  'simple' => [
6385  '<wrap>XXX</wrap>',
6386  'XXX',
6387  ['outerWrap' => '<wrap>|</wrap>'],
6388  ],
6389  'missing pipe puts wrap before' => [
6390  '<pre>XXX',
6391  'XXX',
6392  ['outerWrap' => '<pre>'],
6393  ],
6394  'trims whitespace' => [
6395  '<wrap>XXX</wrap>',
6396  'XXX',
6397  ['outerWrap' => '<wrap>' . TAB . ' | ' . TAB . '</wrap>'],
6398  ],
6399  'split char change is not possible' => [
6400  '<wrap> # </wrap>XXX',
6401  'XXX',
6402  [
6403  'outerWrap' => '<wrap> # </wrap>',
6404  'outerWrap.' => ['splitChar' => '#'],
6405  ],
6406  ],
6407  ];
6408  }
6409 
6419  public function stdWrap_outerWrap($expected, $input, $conf)
6420  {
6421  $this->assertSame(
6422  $expected,
6423  $this->subject->stdWrap_outerWrap($input, $conf)
6424  );
6425  }
6426 
6433  {
6434  return [
6435  'standard case' => [
6436  'override', 'content', ['override' => 'override']
6437  ],
6438  'empty conf does not override' => [
6439  'content', 'content', []
6440  ],
6441  'empty string does not override' => [
6442  'content', 'content', ['override' => '']
6443  ],
6444  'whitespace does not override' => [
6445  'content', 'content', ['override' => ' ' . TAB]
6446  ],
6447  'zero does not override' => [
6448  'content', 'content', ['override' => 0]
6449  ],
6450  'false does not override' => [
6451  'content', 'content', ['override' => false]
6452  ],
6453  'null does not override' => [
6454  'content', 'content', ['override' => null]
6455  ],
6456  'one does override' => [
6457  1, 'content', ['override' => 1]
6458  ],
6459  'minus one does override' => [
6460  -1, 'content', ['override' => -1]
6461  ],
6462  'float does override' => [
6463  -0.1, 'content', ['override' => -0.1]
6464  ],
6465  'true does override' => [
6466  true, 'content', ['override' => true]
6467  ],
6468  'the value is not trimmed' => [
6469  TAB . 'override', 'content', ['override' => TAB . 'override']
6470  ],
6471  ];
6472  }
6473 
6482  public function stdWrap_override($expect, $content, $conf)
6483  {
6484  $this->assertSame(
6485  $expect,
6486  $this->subject->stdWrap_override($content, $conf)
6487  );
6488  }
6489 
6503  public function stdWrap_parseFunc()
6504  {
6505  $content = $this->getUniqueId('content');
6506  $conf = [
6507  'parseFunc' => $this->getUniqueId('parseFunc'),
6508  'parseFunc.' => [$this->getUniqueId('parseFunc.')],
6509  ];
6510  $return = $this->getUniqueId('return');
6511  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6512  ->setMethods(['parseFunc'])->getMock();
6513  $subject
6514  ->expects($this->once())
6515  ->method('parseFunc')
6516  ->with($content, $conf['parseFunc.'], $conf['parseFunc'])
6517  ->willReturn($return);
6518  $this->assertSame(
6519  $return,
6520  $subject->stdWrap_parseFunc($content, $conf)
6521  );
6522  }
6523 
6537  public function stdWrap_postCObject()
6538  {
6539  $debugKey = '/stdWrap/.postCObject';
6540  $content = $this->getUniqueId('content');
6541  $conf = [
6542  'postCObject' => $this->getUniqueId('postCObject'),
6543  'postCObject.' => [$this->getUniqueId('postCObject.')],
6544  ];
6545  $return = $this->getUniqueId('return');
6546  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6547  ->setMethods(['cObjGetSingle'])->getMock();
6548  $subject
6549  ->expects($this->once())
6550  ->method('cObjGetSingle')
6551  ->with($conf['postCObject'], $conf['postCObject.'], $debugKey)
6552  ->willReturn($return);
6553  $this->assertSame(
6554  $content . $return,
6555  $subject->stdWrap_postCObject($content, $conf)
6556  );
6557  }
6558 
6570  public function stdWrap_postUserFunc()
6571  {
6572  $content = $this->getUniqueId('content');
6573  $conf = [
6574  'postUserFunc' => $this->getUniqueId('postUserFunc'),
6575  'postUserFunc.' => [$this->getUniqueId('postUserFunc.')],
6576  ];
6577  $return = $this->getUniqueId('return');
6578  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6579  ->setMethods(['callUserFunction'])->getMock();
6580  $subject
6581  ->expects($this->once())
6582  ->method('callUserFunction')
6583  ->with($conf['postUserFunc'], $conf['postUserFunc.'])
6584  ->willReturn($return);
6585  $this->assertSame(
6586  $return,
6587  $subject->stdWrap_postUserFunc($content, $conf)
6588  );
6589  }
6590 
6609  public function stdWrap_postUserFuncInt()
6610  {
6611  $uniqueHash = $this->getUniqueId('uniqueHash');
6612  $substKey = 'INT_SCRIPT.' . $uniqueHash;
6613  $content = $this->getUniqueId('content');
6614  $conf = [
6615  'postUserFuncInt' => $this->getUniqueId('function'),
6616  'postUserFuncInt.' => [$this->getUniqueId('function array')],
6617  ];
6618  $expect = '<!--' . $substKey . '-->';
6619  $frontend = $this->getMockBuilder(TypoScriptFrontendController::class)
6620  ->disableOriginalConstructor()->setMethods(['uniqueHash'])
6621  ->getMock();
6622  $frontend->expects($this->once())->method('uniqueHash')
6623  ->with()->willReturn($uniqueHash);
6624  $frontend->config = [];
6625  $subject = $this->getAccessibleMock(
6626  ContentObjectRenderer::class,
6627  null,
6628  [$frontend]
6629  );
6630  $this->assertSame(
6631  $expect,
6632  $subject->stdWrap_postUserFuncInt($content, $conf)
6633  );
6634  $array = [
6635  'content' => $content,
6636  'postUserFunc' => $conf['postUserFuncInt'],
6637  'conf' => $conf['postUserFuncInt.'],
6638  'type' => 'POSTUSERFUNC',
6639  'cObj' => serialize($subject)
6640  ];
6641  $this->assertSame(
6642  $array,
6643  $frontend->config['INTincScript'][$substKey]
6644  );
6645  }
6646 
6660  public function stdWrap_preCObject()
6661  {
6662  $debugKey = '/stdWrap/.preCObject';
6663  $content = $this->getUniqueId('content');
6664  $conf = [
6665  'preCObject' => $this->getUniqueId('preCObject'),
6666  'preCObject.' => [$this->getUniqueId('preCObject.')],
6667  ];
6668  $return = $this->getUniqueId('return');
6669  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6670  ->setMethods(['cObjGetSingle'])->getMock();
6671  $subject
6672  ->expects($this->once())
6673  ->method('cObjGetSingle')
6674  ->with($conf['preCObject'], $conf['preCObject.'], $debugKey)
6675  ->willReturn($return);
6676  $this->assertSame(
6677  $return . $content,
6678  $subject->stdWrap_preCObject($content, $conf)
6679  );
6680  }
6681 
6695  public function stdWrap_preIfEmptyListNum()
6696  {
6697  $content = $this->getUniqueId('content');
6698  $conf = [
6699  'preIfEmptyListNum' => $this->getUniqueId('preIfEmptyListNum'),
6700  'preIfEmptyListNum.' => [
6701  'splitChar' => $this->getUniqueId('splitChar')
6702  ],
6703  ];
6704  $return = $this->getUniqueId('return');
6705  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6706  ->setMethods(['listNum'])->getMock();
6707  $subject
6708  ->expects($this->once())
6709  ->method('listNum')
6710  ->with(
6711  $content,
6712  $conf['preIfEmptyListNum'],
6713  $conf['preIfEmptyListNum.']['splitChar']
6714  )
6715  ->willReturn($return);
6716  $this->assertSame(
6717  $return,
6718  $subject->stdWrap_preIfEmptyListNum($content, $conf)
6719  );
6720  }
6721 
6728  {
6729  $content = $this->getUniqueId('content');
6730  $will = $this->getUniqueId('will');
6731  $conf['prefixComment'] = $this->getUniqueId('prefixComment');
6732  $emptyConf1 = [];
6733  $emptyConf2['prefixComment'] = '';
6734  return [
6735  'standard case' => [$will, $content, $conf, false, 1, $will],
6736  'emptyConf1' => [$content, $content, $emptyConf1, false, 0, $will],
6737  'emptyConf2' => [$content, $content, $emptyConf2, false, 0, $will],
6738  'disabled by bool' => [$content, $content, $conf, true, 0, $will],
6739  'disabled by int' => [$content, $content, $conf, 1, 0, $will],
6740  ];
6741  }
6742 
6760  public function stdWrap_prefixComment(
6761  $expect,
6762  $content,
6763  $conf,
6764  $disable,
6765  $times,
6766  $will
6767  ) {
6768  $this->frontendControllerMock
6769  ->config['config']['disablePrefixComment'] = $disable;
6770  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6771  ->setMethods(['prefixComment'])->getMock();
6772  $subject
6773  ->expects($this->exactly($times))
6774  ->method('prefixComment')
6775  ->with($conf['prefixComment'], [], $content)
6776  ->willReturn($will);
6777  $this->assertSame(
6778  $expect,
6779  $subject->stdWrap_prefixComment($content, $conf)
6780  );
6781  }
6782 
6796  public function stdWrap_prepend()
6797  {
6798  $debugKey = '/stdWrap/.prepend';
6799  $content = $this->getUniqueId('content');
6800  $conf = [
6801  'prepend' => $this->getUniqueId('prepend'),
6802  'prepend.' => [$this->getUniqueId('prepend.')],
6803  ];
6804  $return = $this->getUniqueId('return');
6805  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6806  ->setMethods(['cObjGetSingle'])->getMock();
6807  $subject
6808  ->expects($this->once())
6809  ->method('cObjGetSingle')
6810  ->with($conf['prepend'], $conf['prepend.'], $debugKey)
6811  ->willReturn($return);
6812  $this->assertSame(
6813  $return . $content,
6814  $subject->stdWrap_prepend($content, $conf)
6815  );
6816  }
6817 
6824  {
6825  return [
6826  'priority of *' => ['7', '1 + 2 * 3', []],
6827  'priority of parentheses' => ['9', '(1 + 2) * 3', []],
6828  'float' => ['1.5', '3/2', []],
6829  'intval casts to int' => [1, '3/2', ['prioriCalc' => 'intval']],
6830  'intval does not round' => [2, '2.7', ['prioriCalc' => 'intval']],
6831  ];
6832  }
6833 
6854  public function stdWrap_prioriCalc($expect, $content, $conf)
6855  {
6856  $result = $this->subject->stdWrap_prioriCalc($content, $conf);
6857  $this->assertSame($expect, $result);
6858  }
6859 
6873  public function stdWrap_preUserFunc()
6874  {
6875  $content = $this->getUniqueId('content');
6876  $conf = [
6877  'preUserFunc' => $this->getUniqueId('preUserFunc'),
6878  'preUserFunc.' => [$this->getUniqueId('preUserFunc.')],
6879  ];
6880  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6881  ->setMethods(['callUserFunction'])->getMock();
6882  $subject->expects($this->once())->method('callUserFunction')
6883  ->with($conf['preUserFunc'], $conf['preUserFunc.'], $content)
6884  ->willReturn('return');
6885  $this->assertSame(
6886  'return',
6887  $subject->stdWrap_preUserFunc($content, $conf)
6888  );
6889  }
6890 
6897  {
6898  return [
6899  'https://typo3.org?id=10' => [
6900  'https%3A%2F%2Ftypo3.org%3Fid%3D10',
6901  'https://typo3.org?id=10',
6902  ],
6903  'https://typo3.org?id=10&foo=bar' => [
6904  'https%3A%2F%2Ftypo3.org%3Fid%3D10%26foo%3Dbar',
6905  'https://typo3.org?id=10&foo=bar',
6906  ],
6907  ];
6908  }
6909 
6918  public function stdWrap_rawUrlEncode($expect, $content)
6919  {
6920  $this->assertSame(
6921  $expect,
6922  $this->subject->stdWrap_rawUrlEncode($content)
6923  );
6924  }
6925 
6938  public function stdWrap_replacement()
6939  {
6940  $content = $this->getUniqueId('content');
6941  $conf = [
6942  'replacement' => $this->getUniqueId('not used'),
6943  'replacement.' => [$this->getUniqueId('replacement.')],
6944  ];
6945  $return = $this->getUniqueId('return');
6946  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6947  ->setMethods(['replacement'])->getMock();
6948  $subject
6949  ->expects($this->once())
6950  ->method('replacement')
6951  ->with($content, $conf['replacement.'])
6952  ->willReturn($return);
6953  $this->assertSame(
6954  $return,
6955  $subject->stdWrap_replacement($content, $conf)
6956  );
6957  }
6958 
6965  {
6966  return [
6967  // empty content
6968  'empty string is empty' => ['', true, ''],
6969  'null is empty' => ['', true, null],
6970  'false is empty' => ['', true, false],
6971 
6972  // non-empty content
6973  'blank is not empty' => [' ', false, ' '],
6974  'tab is not empty' => [TAB, false, TAB],
6975  'linebreak is not empty' => [PHP_EOL, false, PHP_EOL],
6976  '"0" is not empty' => ['0', false, '0'],
6977  '0 is not empty' => [0, false, 0],
6978  '1 is not empty' => [1, false, 1],
6979  'true is not empty' => [true, false, true],
6980  ];
6981  }
6982 
6998  public function stdWrap_required($expect, $stop, $content)
6999  {
7001  $subject->_set('stdWrapRecursionLevel', 1);
7002  $subject->_set('stopRendering', [1 => false]);
7003  $this->assertSame($expect, $subject->stdWrap_required($content));
7004  $this->assertSame($stop, $subject->_get('stopRendering')[1]);
7005  }
7006 
7019  public function stdWrap_round()
7020  {
7021  $content = $this->getUniqueId('content');
7022  $conf = [
7023  'round' => $this->getUniqueId('not used'),
7024  'round.' => [$this->getUniqueId('round.')],
7025  ];
7026  $return = $this->getUniqueId('return');
7027  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7028  ->setMethods(['round'])->getMock();
7029  $subject
7030  ->expects($this->once())
7031  ->method('round')
7032  ->with($content, $conf['round.'])
7033  ->willReturn($return);
7034  $this->assertSame($return, $subject->stdWrap_round($content, $conf));
7035  }
7036 
7043  {
7044  $content = $this->getUniqueId('content');
7045  $this->assertNotSame($content, $this->subject->getData('current'));
7046  $this->assertSame(
7047  $content,
7048  $this->subject->stdWrap_setContentToCurrent($content)
7049  );
7050  $this->assertSame($content, $this->subject->getData('current'));
7051  }
7052 
7059  {
7060  return [
7061  'no conf' => [
7062  'content',
7063  [],
7064  ],
7065  'empty string' => [
7066  'content',
7067  ['setCurrent' => ''],
7068  ],
7069  'non-empty string' => [
7070  'content',
7071  ['setCurrent' => 'xxx'],
7072  ],
7073  'integer null' => [
7074  'content',
7075  ['setCurrent' => 0],
7076  ],
7077  'integer not null' => [
7078  'content',
7079  ['setCurrent' => 1],
7080  ],
7081  'boolean true' => [
7082  'content',
7083  ['setCurrent' => true],
7084  ],
7085  'boolean false' => [
7086  'content',
7087  ['setCurrent' => false],
7088  ],
7089  ];
7090  }
7091 
7100  public function stdWrap_setCurrent($input, $conf)
7101  {
7102  if (isset($conf['setCurrent'])) {
7103  $this->assertNotSame($conf['setCurrent'], $this->subject->getData('current'));
7104  }
7105  $this->assertSame($input, $this->subject->stdWrap_setCurrent($input, $conf));
7106  if (isset($conf['setCurrent'])) {
7107  $this->assertSame($conf['setCurrent'], $this->subject->getData('current'));
7108  }
7109  }
7110 
7125  public function stdWrap_space()
7126  {
7127  $content = $this->getUniqueId('content');
7128  $trimmed = $this->getUniqueId('space trimmed');
7129  $conf = [
7130  'space' => TAB . ' ' . $trimmed . ' ' . TAB,
7131  'space.' => [$this->getUniqueId('space.')],
7132  ];
7133  $return = $this->getUniqueId('return');
7134  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7135  ->setMethods(['wrapSpace'])->getMock();
7136  $subject
7137  ->expects($this->once())
7138  ->method('wrapSpace')
7139  ->with($content, $trimmed, $conf['space.'])
7140  ->willReturn($return);
7141  $this->assertSame($return, $subject->stdWrap_space($content, $conf));
7142  }
7143 
7159  public function stdWrap_spaceAfter()
7160  {
7161  $content = $this->getUniqueId('content');
7162  $trimmed = $this->getUniqueId('spaceAfter trimmed');
7163  $conf = [
7164  'spaceAfter' => TAB . ' ' . $trimmed . ' ' . TAB,
7165  'space.' => [$this->getUniqueId('space.')],
7166  ];
7167  $return = $this->getUniqueId('return');
7168  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7169  ->setMethods(['wrapSpace'])->getMock();
7170  $subject
7171  ->expects($this->once())
7172  ->method('wrapSpace')
7173  ->with($content, '|' . $trimmed, $conf['space.'])
7174  ->willReturn($return);
7175  $this->assertSame(
7176  $return,
7177  $subject->stdWrap_spaceAfter($content, $conf)
7178  );
7179  }
7180 
7196  public function stdWrap_spaceBefore()
7197  {
7198  $content = $this->getUniqueId('content');
7199  $trimmed = $this->getUniqueId('spaceBefore trimmed');
7200  $conf = [
7201  'spaceBefore' => TAB . ' ' . $trimmed . ' ' . TAB,
7202  'space.' => [$this->getUniqueId('space.')],
7203  ];
7204  $return = $this->getUniqueId('return');
7205  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7206  ->setMethods(['wrapSpace'])->getMock();
7207  $subject
7208  ->expects($this->once())
7209  ->method('wrapSpace')
7210  ->with($content, $trimmed . '|', $conf['space.'])
7211  ->willReturn($return);
7212  $this->assertSame(
7213  $return,
7214  $subject->stdWrap_spaceBefore($content, $conf)
7215  );
7216  }
7217 
7230  public function stdWrap_split()
7231  {
7232  $content = $this->getUniqueId('content');
7233  $conf = [
7234  'split' => $this->getUniqueId('not used'),
7235  'split.' => [$this->getUniqueId('split.')],
7236  ];
7237  $return = $this->getUniqueId('return');
7238  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7239  ->setMethods(['splitObj'])->getMock();
7240  $subject
7241  ->expects($this->once())
7242  ->method('splitObj')
7243  ->with($content, $conf['split.'])
7244  ->willReturn($return);
7245  $this->assertSame(
7246  $return,
7247  $subject->stdWrap_split($content, $conf)
7248  );
7249  }
7250 
7262  public function stdWrap_stdWrap()
7263  {
7264  $content = $this->getUniqueId('content');
7265  $conf = [
7266  'stdWrap' => $this->getUniqueId('not used'),
7267  'stdWrap.' => [$this->getUniqueId('stdWrap.')],
7268  ];
7269  $return = $this->getUniqueId('return');
7270  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7271  ->setMethods(['stdWrap'])->getMock();
7272  $subject
7273  ->expects($this->once())
7274  ->method('stdWrap')
7275  ->with($content, $conf['stdWrap.'])
7276  ->willReturn($return);
7277  $this->assertSame($return, $subject->stdWrap_stdWrap($content, $conf));
7278  }
7279 
7286  {
7287  return [
7288  'only key returns value' => [
7289  'ifNull',
7290  [
7291  'ifNull' => '1',
7292  ],
7293  '',
7294  '1',
7295  ],
7296  'array without key returns empty string' => [
7297  'ifNull',
7298  [
7299  'ifNull.' => '1',
7300  ],
7301  '',
7302  '',
7303  ],
7304  'array without key returns default' => [
7305  'ifNull',
7306  [
7307  'ifNull.' => '1',
7308  ],
7309  'default',
7310  'default',
7311  ],
7312  'non existing key returns default' => [
7313  'ifNull',
7314  [
7315  'noTrimWrap' => 'test',
7316  'noTrimWrap.' => '1',
7317  ],
7318  'default',
7319  'default',
7320  ],
7321  'existing key and array returns stdWrap' => [
7322  'test',
7323  [
7324  'test' => 'value',
7325  'test.' => ['case' => 'upper'],
7326  ],
7327  'default',
7328  'VALUE'
7329  ],
7330  ];
7331  }
7332 
7341  public function stdWrap_stdWrapValue($key, array $configuration, $defaultValue, $expected)
7342  {
7343  $result = $this->subject->stdWrapValue($key, $configuration, $defaultValue);
7344  $this->assertEquals($expected, $result);
7345  }
7346 
7352  public function stdWrap_strPadDataProvider()
7353  {
7354  return [
7355  'pad string with default settings and length 10' => [
7356  'Alien ',
7357  'Alien',
7358  [
7359  'length' => '10',
7360  ],
7361  ],
7362  'pad string with padWith -= and type left and length 10' => [
7363  '-=-=-Alien',
7364  'Alien',
7365  [
7366  'length' => '10',
7367  'padWith' => '-=',
7368  'type' => 'left',
7369  ],
7370  ],
7371  'pad string with padWith _ and type both and length 10' => [
7372  '__Alien___',
7373  'Alien',
7374  [
7375  'length' => '10',
7376  'padWith' => '_',
7377  'type' => 'both',
7378  ],
7379  ],
7380  'pad string with padWith 0 and type both and length 10' => [
7381  '00Alien000',
7382  'Alien',
7383  [
7384  'length' => '10',
7385  'padWith' => '0',
7386  'type' => 'both',
7387  ],
7388  ],
7389  'pad string with padWith ___ and type both and length 6' => [
7390  'Alien_',
7391  'Alien',
7392  [
7393  'length' => '6',
7394  'padWith' => '___',
7395  'type' => 'both',
7396  ],
7397  ],
7398  'pad string with padWith _ and type both and length 12, using stdWrap for length' => [
7399  '___Alien____',
7400  'Alien',
7401  [
7402  'length' => '1',
7403  'length.' => [
7404  'wrap' => '|2',
7405  ],
7406  'padWith' => '_',
7407  'type' => 'both',
7408  ],
7409  ],
7410  'pad string with padWith _ and type both and length 12, using stdWrap for padWidth' => [
7411  '-_=Alien-_=-',
7412  'Alien',
7413  [
7414  'length' => '12',
7415  'padWith' => '_',
7416  'padWith.' => [
7417  'wrap' => '-|=',
7418  ],
7419  'type' => 'both',
7420  ],
7421  ],
7422  'pad string with padWith _ and type both and length 12, using stdWrap for type' => [
7423  '_______Alien',
7424  'Alien',
7425  [
7426  'length' => '12',
7427  'padWith' => '_',
7428  'type' => 'both',
7429  // make type become "left"
7430  'type.' => [
7431  'substring' => '2,1',
7432  'wrap' => 'lef|',
7433  ],
7434  ],
7435  ],
7436  ];
7437  }
7438 
7448  public function stdWrap_strPad($expect, $content, $conf)
7449  {
7450  $conf = ['strPad.' => $conf];
7451  $result = $this->subject->stdWrap_strPad($content, $conf);
7452  $this->assertSame($expect, $result);
7453  }
7454 
7461  {
7462  // Fictive execution time is 2012-09-01 12:00 in UTC/GMT.
7463  $now = 1346500800;
7464  return [
7465  'given timestamp' => [
7466  '01-09-2012',
7467  $now,
7468  ['strftime' => '%d-%m-%Y'],
7469  $now
7470  ],
7471  'empty string' => [
7472  '01-09-2012',
7473  '',
7474  ['strftime' => '%d-%m-%Y'],
7475  $now
7476  ],
7477  'testing null' => [
7478  '01-09-2012',
7479  null,
7480  ['strftime' => '%d-%m-%Y'],
7481  $now
7482  ]
7483  ];
7484  }
7485 
7496  public function stdWrap_strftime($expect, $content, $conf, $now)
7497  {
7498  // Save current timezone and set to UTC to make the system under test
7499  // behave the same in all server timezone settings
7500  $timezoneBackup = date_default_timezone_get();
7501  date_default_timezone_set('UTC');
7502 
7503  $GLOBALS['EXEC_TIME'] = $now;
7504  $result = $this->subject->stdWrap_strftime($content, $conf);
7505 
7506  // Reset timezone
7507  date_default_timezone_set($timezoneBackup);
7508 
7509  $this->assertSame($expect, $result);
7510  }
7511 
7517  public function stdWrap_stripHtml()
7518  {
7519  $content = '<html><p>Hello <span class="inline">inline tag<span>!</p><p>Hello!</p></html>';
7520  $expected = 'Hello inline tag!Hello!';
7521  $this->assertSame($expected, $this->subject->stdWrap_stripHtml($content));
7522  }
7523 
7530  {
7531  return [
7532  'date from content' => [
7533  1417651200, '2014-12-04',
7534  ['strtotime' => '1']
7535  ],
7536  'manipulation of date from content' => [
7537  1417996800, '2014-12-04',
7538  ['strtotime' => '+ 2 weekdays']
7539  ],
7540  'date from configuration' => [
7541  1417651200, '',
7542  ['strtotime' => '2014-12-04']
7543  ],
7544  'manipulation of date from configuration' => [
7545  1417996800, '',
7546  ['strtotime' => '2014-12-04 + 2 weekdays']
7547  ],
7548  'empty input' => [
7549  false, '',
7550  ['strtotime' => '1']
7551  ],
7552  'date from content and configuration' => [
7553  false, '2014-12-04',
7554  ['strtotime' => '2014-12-05']
7555  ]
7556  ];
7557  }
7558 
7568  public function stdWrap_strtotime($expect, $content, $conf)
7569  {
7570  // Set exec_time to a hard timestamp
7571  $GLOBALS['EXEC_TIME'] = 1417392000;
7572  // Save current timezone and set to UTC to make the system under test
7573  // behave the same in all server timezone settings
7574  $timezoneBackup = date_default_timezone_get();
7575  date_default_timezone_set('UTC');
7576 
7577  $result = $this->subject->stdWrap_strtotime($content, $conf);
7578 
7579  // Reset timezone
7580  date_default_timezone_set($timezoneBackup);
7581 
7582  $this->assertEquals($expect, $result);
7583  }
7584 
7597  public function stdWrap_substring()
7598  {
7599  $content = $this->getUniqueId('content');
7600  $conf = [
7601  'substring' => $this->getUniqueId('substring'),
7602  'substring.' => $this->getUniqueId('not used'),
7603  ];
7604  $return = $this->getUniqueId('return');
7605  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7606  ->setMethods(['substring'])->getMock();
7607  $subject
7608  ->expects($this->once())
7609  ->method('substring')
7610  ->with($content, $conf['substring'])
7611  ->willReturn($return);
7612  $this->assertSame(
7613  $return,
7614  $subject->stdWrap_substring($content, $conf)
7615  );
7616  }
7617 
7623  public function stdWrap_trimDataProvider()
7624  {
7625  return [
7626  // string not trimmed
7627  'empty string' => ['', ''],
7628  'string without whitespace' => ['xxx', 'xxx'],
7629  'string with whitespace inside' => [
7630  'xx ' . TAB . ' xx',
7631  'xx ' . TAB . ' xx',
7632  ],
7633  'string with newlines inside' => [
7634  'xx ' . PHP_EOL . ' xx',
7635  'xx ' . PHP_EOL . ' xx',
7636  ],
7637  // string trimmed
7638  'blanks around' => ['xxx', ' xxx '],
7639  'tabs around' => ['xxx', TAB . 'xxx' . TAB],
7640  'newlines around' => ['xxx', PHP_EOL . 'xxx' . PHP_EOL],
7641  'mixed case' => ['xxx', TAB . ' xxx ' . PHP_EOL],
7642  // non strings
7643  'null' => ['', null],
7644  'false' => ['', false],
7645  'true' => ['1', true],
7646  'zero' => ['0', 0],
7647  'one' => ['1', 1],
7648  '-1' => ['-1', -1],
7649  '0.0' => ['0', 0.0],
7650  '1.0' => ['1', 1.0],
7651  '-1.0' => ['-1', -1.0],
7652  '1.1' => ['1.1', 1.1],
7653  ];
7654  }
7655 
7676  public function stdWrap_trim($expect, $content)
7677  {
7678  $result = $this->subject->stdWrap_trim($content);
7679  $this->assertSame($expect, $result);
7680  }
7681 
7693  public function stdWrap_typolink()
7694  {
7695  $content = $this->getUniqueId('content');
7696  $conf = [
7697  'typolink' => $this->getUniqueId('not used'),
7698  'typolink.' => [$this->getUniqueId('typolink.')],
7699  ];
7700  $return = $this->getUniqueId('return');
7701  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7702  ->setMethods(['typolink'])->getMock();
7703  $subject
7704  ->expects($this->once())
7705  ->method('typolink')
7706  ->with($content, $conf['typolink.'])
7707  ->willReturn($return);
7708  $this->assertSame($return, $subject->stdWrap_typolink($content, $conf));
7709  }
7710 
7716  public function stdWrap_wrapDataProvider()
7717  {
7718  return [
7719  'no conf' => [
7720  'XXX',
7721  'XXX',
7722  [],
7723  ],
7724  'simple' => [
7725  '<wrapper>XXX</wrapper>',
7726  'XXX',
7727  ['wrap' => '<wrapper>|</wrapper>'],
7728  ],
7729  'trims whitespace' => [
7730  '<wrapper>XXX</wrapper>',
7731  'XXX',
7732  ['wrap' => '<wrapper>' . TAB . ' | ' . TAB . '</wrapper>'],
7733  ],
7734  'missing pipe puts wrap before' => [
7735  '<pre>XXX',
7736  'XXX',
7737  [
7738  'wrap' => '<pre>',
7739  ],
7740  ],
7741  'split char change' => [
7742  '<wrapper>XXX</wrapper>',
7743  'XXX',
7744  [
7745  'wrap' => '<wrapper> # </wrapper>',
7746  'wrap.' => ['splitChar' => '#'],
7747  ],
7748  ],
7749  'split by pattern' => [
7750  '<wrapper>XXX</wrapper>',
7751  'XXX',
7752  [
7753  'wrap' => '<wrapper> ###splitter### </wrapper>',
7754  'wrap.' => ['splitChar' => '###splitter###'],
7755  ],
7756  ],
7757  ];
7758  }
7759 
7769  public function stdWrap_wrap($expected, $input, $conf)
7770  {
7771  $this->assertSame(
7772  $expected,
7773  $this->subject->stdWrap_wrap($input, $conf)
7774  );
7775  }
7776 
7782  public function stdWrap_wrap2DataProvider()
7783  {
7784  return [
7785  'no conf' => [
7786  'XXX',
7787  'XXX',
7788  [],
7789  ],
7790  'simple' => [
7791  '<wrapper>XXX</wrapper>',
7792  'XXX',
7793  ['wrap2' => '<wrapper>|</wrapper>'],
7794  ],
7795  'trims whitespace' => [
7796  '<wrapper>XXX</wrapper>',
7797  'XXX',
7798  ['wrap2' => '<wrapper>' . TAB . ' | ' . TAB . '</wrapper>'],
7799  ],
7800  'missing pipe puts wrap2 before' => [
7801  '<pre>XXX',
7802  'XXX',
7803  [
7804  'wrap2' => '<pre>',
7805  ],
7806  ],
7807  'split char change' => [
7808  '<wrapper>XXX</wrapper>',
7809  'XXX',
7810  [
7811  'wrap2' => '<wrapper> # </wrapper>',
7812  'wrap2.' => ['splitChar' => '#'],
7813  ],
7814  ],
7815  'split by pattern' => [
7816  '<wrapper>XXX</wrapper>',
7817  'XXX',
7818  [
7819  'wrap2' => '<wrapper> ###splitter### </wrapper>',
7820  'wrap2.' => ['splitChar' => '###splitter###'],
7821  ],
7822  ],
7823  ];
7824  }
7825 
7835  public function stdWrap_wrap2($expected, $input, $conf)
7836  {
7837  $this->assertSame($expected, $this->subject->stdWrap_wrap2($input, $conf));
7838  }
7839 
7845  public function stdWrap_wrap3DataProvider()
7846  {
7847  return [
7848  'no conf' => [
7849  'XXX',
7850  'XXX',
7851  [],
7852  ],
7853  'simple' => [
7854  '<wrapper>XXX</wrapper>',
7855  'XXX',
7856  ['wrap3' => '<wrapper>|</wrapper>'],
7857  ],
7858  'trims whitespace' => [
7859  '<wrapper>XXX</wrapper>',
7860  'XXX',
7861  ['wrap3' => '<wrapper>' . TAB . ' | ' . TAB . '</wrapper>'],
7862  ],
7863  'missing pipe puts wrap3 before' => [
7864  '<pre>XXX',
7865  'XXX',
7866  [
7867  'wrap3' => '<pre>',
7868  ],
7869  ],
7870  'split char change' => [
7871  '<wrapper>XXX</wrapper>',
7872  'XXX',
7873  [
7874  'wrap3' => '<wrapper> # </wrapper>',
7875  'wrap3.' => ['splitChar' => '#'],
7876  ],
7877  ],
7878  'split by pattern' => [
7879  '<wrapper>XXX</wrapper>',
7880  'XXX',
7881  [
7882  'wrap3' => '<wrapper> ###splitter### </wrapper>',
7883  'wrap3.' => ['splitChar' => '###splitter###'],
7884  ],
7885  ],
7886  ];
7887  }
7888 
7898  public function stdWrap_wrap3($expected, $input, $conf)
7899  {
7900  $this->assertSame($expected, $this->subject->stdWrap_wrap3($input, $conf));
7901  }
7902 
7909  {
7910  $format = '<div style="text-align:%s;">%s</div>';
7911  $content = $this->getUniqueId('content');
7912  $wrapAlign = $this->getUniqueId('wrapAlign');
7913  $expect = sprintf($format, $wrapAlign, $content);
7914  return [
7915  'standard case' => [$expect, $content, $wrapAlign],
7916  'empty conf' => [$content, $content, null],
7917  'empty string' => [$content, $content, ''],
7918  'whitespaced zero string' => [$content, $content, ' 0 '],
7919  ];
7920  }
7921 
7938  public function stdWrap_wrapAlign($expect, $content, $wrapAlignConf)
7939  {
7940  $conf = [];
7941  if ($wrapAlignConf !== null) {
7942  $conf['wrapAlign'] = $wrapAlignConf;
7943  }
7944  $this->assertSame(
7945  $expect,
7946  $this->subject->stdWrap_wrapAlign($content, $conf)
7947  );
7948  }
7949 
7950  /***************************************************************************
7951  * End of tests of stdWrap in alphabetical order
7952  ***************************************************************************/
7953 
7954  /***************************************************************************
7955  * Begin: Mixed tests
7956  *
7957  * - Add new tests here that still don't have a better place in this class.
7958  * - Place tests in alphabetical order.
7959  * - Place data provider above test method.
7960  ***************************************************************************/
7961 
7967  public function getCurrentTable()
7968  {
7969  $this->assertEquals('tt_content', $this->subject->getCurrentTable());
7970  }
7971 
7977  public function linkWrapDataProvider()
7978  {
7979  $content = $this->getUniqueId();
7980  return [
7981  'Handles a tag as wrap.' => [
7982  '<tag>' . $content . '</tag>',
7983  $content,
7984  '<tag>|</tag>'
7985  ],
7986  'Handles simple text as wrap.' => [
7987  'alpha' . $content . 'omega',
7988  $content,
7989  'alpha|omega'
7990  ],
7991  'Trims whitespace around tags.' => [
7992  '<tag>' . $content . '</tag>',
7993  $content,
7994  "\t <tag>\t |\t </tag>\t "
7995  ],
7996  'A wrap without pipe is placed before the content.' => [
7997  '<tag>' . $content,
7998  $content,
7999  '<tag>'
8000  ],
8001  'For an empty string as wrap the content is returned as is.' => [
8002  $content,
8003  $content,
8004  ''
8005  ],
8006  'For null as wrap the content is returned as is.' => [
8007  $content,
8008  $content,
8009  null
8010  ],
8011  'For a valid rootline level the uid will be inserted.' => [
8012  '<a href="?id=55">' . $content . '</a>',
8013  $content,
8014  '<a href="?id={3}"> | </a>'
8015  ],
8016  'For an invalid rootline level there is no replacement.' => [
8017  '<a href="?id={4}">' . $content . '</a>',
8018  $content,
8019  '<a href="?id={4}"> | </a>'
8020  ],
8021  ];
8022  }
8023 
8033  public function linkWrap($expected, $content, $wrap)
8034  {
8035  $this->templateServiceMock->rootLine = [3 => ['uid' => 55]];
8036  $actual = $this->subject->linkWrap($content, $wrap);
8037  $this->assertEquals($expected, $actual);
8038  }
8039 
8045  public function prefixCommentDataProvider()
8046  {
8047  $comment = $this->getUniqueId();
8048  $content = $this->getUniqueId();
8049  $format = '%s';
8050  $format .= '%%s<!-- %%s [begin] -->%s';
8051  $format .= '%%s%s%%s%s';
8052  $format .= '%%s<!-- %%s [end] -->%s';
8053  $format .= '%%s%s';
8054  $format = sprintf($format, LF, LF, TAB, LF, LF, TAB);
8055  $indent1 = TAB;
8056  $indent2 = TAB . TAB;
8057  return [
8058  'indent one tab' => [
8059  sprintf(
8060  $format,
8061  $indent1,
8062  $comment,
8063  $indent1,
8064  $content,
8065  $indent1,
8066  $comment,
8067  $indent1
8068  ),
8069  '1|' . $comment, $content ],
8070  'indent two tabs' => [
8071  sprintf(
8072  $format,
8073  $indent2,
8074  $comment,
8075  $indent2,
8076  $content,
8077  $indent2,
8078  $comment,
8079  $indent2
8080  ),
8081  '2|' . $comment, $content ],
8082  'htmlspecialchars applies for comment only' => [
8083  sprintf(
8084  $format,
8085  $indent1,
8086  '&lt;' . $comment . '&gt;',
8087  $indent1,
8088  '<' . $content . '>',
8089  $indent1,
8090  '&lt;' . $comment . '&gt;',
8091  $indent1
8092  ),
8093  '1|' . '<' . $comment . '>', '<' . $content . '>' ],
8094  ];
8095  }
8096 
8106  public function prefixComment($expect, $comment, $content)
8107  {
8108  // The parameter $conf is never used. Just provide null.
8109  // Consider to improve the signature and deprecate the old one.
8110  $result = $this->subject->prefixComment($comment, null, $content);
8111  $this->assertEquals($expect, $result);
8112  }
8113 
8120  {
8121  $storageMock = $this->createMock(ResourceStorage::class);
8122  $file = new File(['testfile'], $storageMock);
8123  $this->subject->setCurrentFile($file);
8124  $this->assertSame($file, $this->subject->getCurrentFile());
8125  }
8126 
8137  {
8138  $key = $this->getUniqueId();
8139  $value = $this->getUniqueId();
8140  $this->subject->currentValKey = $key;
8141  $this->subject->setCurrentVal($value);
8142  $this->assertEquals($value, $this->subject->getCurrentVal());
8143  $this->assertEquals($value, $this->subject->data[$key]);
8144  }
8145 
8152  {
8153  $value = $this->getUniqueId();
8154  $this->subject->setUserObjectType($value);
8155  $this->assertEquals($value, $this->subject->getUserObjectType());
8156  }
8157 
8158  /***************************************************************************
8159  * End: Mixed tests
8160  ***************************************************************************/
8161 }
static unlink_tempfile($uploadedTempFileName)
static addInstance($className, $instance)
stdWrap_prefixComment( $expect, $content, $conf, $disable, $times, $will)
static useAnsiColor($ansiColorUsage)
static setSingletonInstance($className, SingletonInterface $instance)
typoLinkEncodesMailAddressForSpamProtection(array $settings, $linkText, $mailAddress, $expected)
typolinkReturnsCorrectLinksForFilesWithAbsRefPrefix($linkText, $configuration, $absRefPrefix, $expectedResult)
isGetOneSourceCollectionCalledCallback($sourceRenderConfiguration, $sourceConfiguration, $oneSourceCollection, $parent)
stdWrap_stdWrapValue($key, array $configuration, $defaultValue, $expected)
$fields
Definition: pages.php:4
static resetSingletonInstances(array $newSingletonInstances)
typolinkReturnsCorrectLinksForEmailsAndUrls($linkText, $configuration, $expectedResult)
stdWrap_editIcons( $expect, $content, $conf, $login, $times, $param3, $will)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']