TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
Unit/ContentObject/ContentObjectRendererTest.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Frontend\Tests\Unit\ContentObject;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
17 use Psr\Log\LoggerInterface;
19 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface as CacheFrontendInterface;
54 
59 {
60 
64  protected $singletonInstances = [];
65 
69  protected $subject = null;
70 
74  protected $frontendControllerMock = null;
75 
79  protected $templateServiceMock = null;
80 
86  protected $contentObjectMap = [
87  'TEXT' => TextContentObject::class,
88  'CASE' => CaseContentObject::class,
89  'COBJ_ARRAY' => ContentObjectArrayContentObject::class,
90  'COA' => ContentObjectArrayContentObject::class,
91  'COA_INT' => ContentObjectArrayInternalContentObject::class,
92  'USER' => UserContentObject::class,
93  'USER_INT' => UserInternalContentObject::class,
94  'FILE' => FileContentObject::class,
95  'FILES' => FilesContentObject::class,
96  'IMAGE' => ImageContentObject::class,
97  'IMG_RESOURCE' => ImageResourceContentObject::class,
98  'CONTENT' => ContentContentObject::class,
99  'RECORDS' => RecordsContentObject::class,
100  'HMENU' => HierarchicalMenuContentObject::class,
101  'CASEFUNC' => CaseContentObject::class,
102  'LOAD_REGISTER' => LoadRegisterContentObject::class,
103  'RESTORE_REGISTER' => RestoreRegisterContentObject::class,
104  'TEMPLATE' => TemplateContentObject::class,
105  'FLUIDTEMPLATE' => FluidTemplateContentObject::class,
106  'SVG' => ScalableVectorGraphicsContentObject::class,
107  'EDITPANEL' => EditPanelContentObject::class
108  ];
109 
113  protected function setUp()
114  {
115  $this->singletonInstances = GeneralUtility::getSingletonInstances();
117 
118  $this->templateServiceMock =
119  $this->getMockBuilder(TemplateService::class)
120  ->setMethods(['getFileName', 'linkData'])->getMock();
121  $pageRepositoryMock =
122  $this->getMockBuilder(PageRepositoryFixture::class)
123  ->setMethods(['getRawRecord', 'getMountPointInfo'])->getMock();
124  $this->frontendControllerMock =
125  $this->getAccessibleMock(TypoScriptFrontendController::class,
126  ['dummy'], [], '', false);
127  $this->frontendControllerMock->tmpl = $this->templateServiceMock;
128  $this->frontendControllerMock->config = [];
129  $this->frontendControllerMock->page = [];
130  $this->frontendControllerMock->sys_page = $pageRepositoryMock;
132 
133  $this->subject = $this->getAccessibleMock(
134  ContentObjectRenderer::class,
135  ['getResourceFactory', 'getEnvironmentVariable'],
136  [$this->frontendControllerMock]
137  );
138  $this->subject->setContentObjectClassMap($this->contentObjectMap);
139  $this->subject->start([], 'tt_content');
140  }
141 
142  protected function tearDown()
143  {
144  GeneralUtility::resetSingletonInstances($this->singletonInstances);
145  parent::tearDown();
146  }
147 
149  // Utility functions
151 
155  protected function getFrontendController()
156  {
157  return $GLOBALS['TSFE'];
158  }
159 
163  protected function createMockedLoggerAndLogManager()
164  {
165  $logManagerMock = $this->getMockBuilder(LogManager::class)->getMock();
166  $loggerMock = $this->getMockBuilder(LoggerInterface::class)->getMock();
167  $logManagerMock->expects($this->any())
168  ->method('getLogger')
169  ->willReturn($loggerMock);
170  GeneralUtility::setSingletonInstance(LogManager::class, $logManagerMock);
171  }
172 
179  protected function handleCharset(&$subject, &$expected)
180  {
181  $charsetConverter = new CharsetConverter();
182  $subject = $charsetConverter->conv($subject, 'iso-8859-1', 'utf-8');
183  $expected = $charsetConverter->conv($expected, 'iso-8859-1', 'utf-8');
184  }
185 
187  // Tests concerning the getImgResource hook
189 
193  {
194  $this->templateServiceMock
195  ->expects($this->atLeastOnce())
196  ->method('getFileName')
197  ->with('typo3/clear.gif')
198  ->will($this->returnValue('typo3/clear.gif'));
199 
200  $resourceFactory = $this->createMock(ResourceFactory::class);
201  $this->subject->expects($this->any())->method('getResourceFactory')->will($this->returnValue($resourceFactory));
202 
203  $className = $this->getUniqueId('tx_coretest');
204  $getImgResourceHookMock = $this->getMockBuilder(\TYPO3\CMS\Frontend\ContentObject\ContentObjectGetImageResourceHookInterface::class)
205  ->setMethods(['getImgResourcePostProcess'])
206  ->setMockClassName($className)
207  ->getMock();
208  $getImgResourceHookMock
209  ->expects($this->once())
210  ->method('getImgResourcePostProcess')
211  ->will($this->returnCallback([$this, 'isGetImgResourceHookCalledCallback']));
212  $getImgResourceHookObjects = [$getImgResourceHookMock];
213  $this->subject->_setRef('getImgResourceHookObjects', $getImgResourceHookObjects);
214  $this->subject->getImgResource('typo3/clear.gif', []);
215  }
216 
227  public function isGetImgResourceHookCalledCallback($file, $fileArray, $imageResource, $parent)
228  {
229  $this->assertEquals('typo3/clear.gif', $file);
230  $this->assertEquals('typo3/clear.gif', $imageResource['origFile']);
231  $this->assertTrue(is_array($fileArray));
232  $this->assertTrue($parent instanceof ContentObjectRenderer);
233  return $imageResource;
234  }
235 
237  // Tests concerning getContentObject
239 
241  {
242  $dataProvider = [];
243  foreach ($this->contentObjectMap as $name => $className) {
244  $dataProvider[] = [$name, $className];
245  }
246  return $dataProvider;
247  }
248 
256  {
257  $contentObjectInstance = $this->createMock($fullClassName);
258  GeneralUtility::addInstance($fullClassName, $contentObjectInstance);
259  $this->assertSame($contentObjectInstance, $this->subject->getContentObject($name));
260  }
261 
263  // Tests concerning getQueryArguments()
265 
269  {
270  $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
271  $this->returnValue('key1=value1&key2=value2&key3[key31]=value31&key3[key32][key321]=value321&key3[key32][key322]=value322')
272  );
273  $getQueryArgumentsConfiguration = [];
274  $getQueryArgumentsConfiguration['exclude'] = [];
275  $getQueryArgumentsConfiguration['exclude'][] = 'key1';
276  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
277  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
278  $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
279  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2&key3[key32][key322]=value322');
280  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
281  $this->assertEquals($expectedResult, $actualResult);
282  }
283 
288  {
289  $_GET = [
290  'key1' => 'value1',
291  'key2' => 'value2',
292  'key3' => [
293  'key31' => 'value31',
294  'key32' => [
295  'key321' => 'value321',
296  'key322' => 'value322'
297  ]
298  ]
299  ];
300  $getQueryArgumentsConfiguration = [];
301  $getQueryArgumentsConfiguration['method'] = 'GET';
302  $getQueryArgumentsConfiguration['exclude'] = [];
303  $getQueryArgumentsConfiguration['exclude'][] = 'key1';
304  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
305  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
306  $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
307  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2&key3[key32][key322]=value322');
308  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
309  $this->assertEquals($expectedResult, $actualResult);
310  }
311 
316  {
317  $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
318  $this->returnValue('key1=value1')
319  );
320  $getQueryArgumentsConfiguration = [];
321  $overruleArguments = [
322  // Should be overridden
323  'key1' => 'value1Overruled',
324  // Shouldn't be set: Parameter doesn't exist in source array and is not forced
325  'key2' => 'value2Overruled'
326  ];
327  $expectedResult = '&key1=value1Overruled';
328  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments);
329  $this->assertEquals($expectedResult, $actualResult);
330  }
331 
336  {
337  $_POST = [
338  'key1' => 'value1',
339  'key2' => 'value2',
340  'key3' => [
341  'key31' => 'value31',
342  'key32' => [
343  'key321' => 'value321',
344  'key322' => 'value322'
345  ]
346  ]
347  ];
348  $getQueryArgumentsConfiguration = [];
349  $getQueryArgumentsConfiguration['method'] = 'POST';
350  $getQueryArgumentsConfiguration['exclude'] = [];
351  $getQueryArgumentsConfiguration['exclude'][] = 'key1';
352  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
353  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
354  $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
355  $overruleArguments = [
356  // Should be overriden
357  'key2' => 'value2Overruled',
358  'key3' => [
359  'key32' => [
360  // Shouldn't be set: Parameter is excluded and not forced
361  'key321' => 'value321Overruled',
362  // Should be overriden: Parameter is not excluded
363  'key322' => 'value322Overruled',
364  // Shouldn't be set: Parameter doesn't exist in source array and is not forced
365  'key323' => 'value323Overruled'
366  ]
367  ]
368  ];
369  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2Overruled&key3[key32][key322]=value322Overruled');
370  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments);
371  $this->assertEquals($expectedResult, $actualResult);
372  }
373 
378  {
379  $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
380  $this->returnValue('key1=value1&key2=value2&key3[key31]=value31&key3[key32][key321]=value321&key3[key32][key322]=value322')
381  );
382  $_POST = [
383  'key1' => 'value1',
384  'key2' => 'value2',
385  'key3' => [
386  'key31' => 'value31',
387  'key32' => [
388  'key321' => 'value321',
389  'key322' => 'value322'
390  ]
391  ]
392  ];
393  $getQueryArgumentsConfiguration = [];
394  $getQueryArgumentsConfiguration['exclude'] = [];
395  $getQueryArgumentsConfiguration['exclude'][] = 'key1';
396  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
397  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
398  $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key322]';
399  $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
400  $overruleArguments = [
401  // Should be overriden
402  'key2' => 'value2Overruled',
403  'key3' => [
404  'key32' => [
405  // Should be set: Parameter is excluded but forced
406  'key321' => 'value321Overruled',
407  // Should be set: Parameter doesn't exist in source array but is forced
408  'key323' => 'value323Overruled'
409  ]
410  ]
411  ];
412  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2Overruled&key3[key32][key321]=value321Overruled&key3[key32][key323]=value323Overruled');
413  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments, true);
414  $this->assertEquals($expectedResult, $actualResult);
415  $getQueryArgumentsConfiguration['method'] = 'POST';
416  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments, true);
417  $this->assertEquals($expectedResult, $actualResult);
418  }
419 
424  {
425  $_POST = [
426  'key1' => 'POST1',
427  'key2' => 'POST2',
428  'key3' => [
429  'key31' => 'POST31',
430  'key32' => 'POST32',
431  'key33' => [
432  'key331' => 'POST331',
433  'key332' => 'POST332',
434  ]
435  ]
436  ];
437  $_GET = [
438  'key2' => 'GET2',
439  'key3' => [
440  'key32' => 'GET32',
441  'key33' => [
442  'key331' => 'GET331',
443  ]
444  ]
445  ];
446  $getQueryArgumentsConfiguration = [];
447  $getQueryArgumentsConfiguration['method'] = 'POST,GET';
448  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key1=POST1&key2=GET2&key3[key31]=POST31&key3[key32]=GET32&key3[key33][key331]=GET331&key3[key33][key332]=POST332');
449  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
450  $this->assertEquals($expectedResult, $actualResult);
451  }
452 
457  {
458  $_GET = [
459  'key1' => 'GET1',
460  'key2' => 'GET2',
461  'key3' => [
462  'key31' => 'GET31',
463  'key32' => 'GET32',
464  'key33' => [
465  'key331' => 'GET331',
466  'key332' => 'GET332',
467  ]
468  ]
469  ];
470  $_POST = [
471  'key2' => 'POST2',
472  'key3' => [
473  'key32' => 'POST32',
474  'key33' => [
475  'key331' => 'POST331',
476  ]
477  ]
478  ];
479  $getQueryArgumentsConfiguration = [];
480  $getQueryArgumentsConfiguration['method'] = 'GET,POST';
481  $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key1=GET1&key2=POST2&key3[key31]=GET31&key3[key32]=POST32&key3[key33][key331]=POST331&key3[key33][key332]=GET332');
482  $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
483  $this->assertEquals($expectedResult, $actualResult);
484  }
485 
492  private function rawUrlEncodeSquareBracketsInUrl($string)
493  {
494  return str_replace(['[', ']'], ['%5B', '%5D'], $string);
495  }
496 
498  // Tests concerning crop
500 
503  public function cropIsMultibyteSafe()
504  {
505  $this->assertEquals('бла', $this->subject->crop('бла', '3|...'));
506  }
507 
509 
511  // Tests concerning cropHTML
513 
521  public function cropHTMLDataProvider()
522  {
523  $plainText = 'Kasper Sk' . chr(229) . 'rh' . chr(248)
524  . 'j implemented the original version of the crop function.';
525  $textWithMarkup = '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
526  . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong> the '
527  . 'original version of the crop function.';
528  $textWithEntities = 'Kasper Sk&aring;rh&oslash;j implemented the; '
529  . 'original ' . 'version of the crop function.';
530  $textWithLinebreaks = "Lorem ipsum dolor sit amet,\n"
531  . "consetetur sadipscing elitr,\n"
532  . 'sed diam nonumy eirmod tempor invidunt ut labore e'
533  . 't dolore magna aliquyam';
534 
535  return [
536  'plain text; 11|...' => [
537  'Kasper Sk' . chr(229) . 'r...',
538  $plainText, '11|...',
539  ],
540  'plain text; -58|...' => [
541  '...h' . chr(248) . 'j implemented the original version of '
542  . 'the crop function.',
543  $plainText, '-58|...',
544  ],
545  'plain text; 4|...|1' => [
546  'Kasp...',
547  $plainText, '4|...|1',
548  ],
549  'plain text; 20|...|1' => [
550  'Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j...',
551  $plainText, '20|...|1',
552  ],
553  'plain text; -5|...|1' => [
554  '...tion.',
555  $plainText, '-5|...|1',
556  ],
557  'plain text; -49|...|1' => [
558  '...the original version of the crop function.',
559  $plainText, '-49|...|1',
560  ],
561  'text with markup; 11|...' => [
562  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
563  . chr(229) . 'r...</a></strong>',
564  $textWithMarkup, '11|...',
565  ],
566  'text with markup; 13|...' => [
567  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
568  . chr(229) . 'rh' . chr(248) . '...</a></strong>',
569  $textWithMarkup, '13|...',
570  ],
571  'text with markup; 14|...' => [
572  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
573  . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>',
574  $textWithMarkup, '14|...',
575  ],
576  'text with markup; 15|...' => [
577  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
578  . chr(229) . 'rh' . chr(248) . 'j</a> ...</strong>',
579  $textWithMarkup, '15|...',
580  ],
581  'text with markup; 29|...' => [
582  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
583  . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong> '
584  . 'th...',
585  $textWithMarkup, '29|...',
586  ],
587  'text with markup; -58|...' => [
588  '<strong><a href="mailto:kasper@typo3.org">...h' . chr(248)
589  . 'j</a> implemented</strong> the original version of the crop '
590  . 'function.',
591  $textWithMarkup, '-58|...',
592  ],
593  'text with markup 4|...|1' => [
594  '<strong><a href="mailto:kasper@typo3.org">Kasp...</a>'
595  . '</strong>',
596  $textWithMarkup, '4|...|1',
597  ],
598  'text with markup; 11|...|1' => [
599  '<strong><a href="mailto:kasper@typo3.org">Kasper...</a>'
600  . '</strong>',
601  $textWithMarkup, '11|...|1',
602  ],
603  'text with markup; 13|...|1' => [
604  '<strong><a href="mailto:kasper@typo3.org">Kasper...</a>'
605  . '</strong>',
606  $textWithMarkup, '13|...|1',
607  ],
608  'text with markup; 14|...|1' => [
609  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
610  . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>',
611  $textWithMarkup, '14|...|1',
612  ],
613  'text with markup; 15|...|1' => [
614  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
615  . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>',
616  $textWithMarkup, '15|...|1',
617  ],
618  'text with markup; 29|...|1' => [
619  '<strong><a href="mailto:kasper@typo3.org">Kasper Sk'
620  . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong>...',
621  $textWithMarkup, '29|...|1',
622  ],
623  'text with markup; -66|...|1' => [
624  '<strong><a href="mailto:kasper@typo3.org">...Sk' . chr(229)
625  . 'rh' . chr(248) . 'j</a> implemented</strong> the original v'
626  . 'ersion of the crop function.',
627  $textWithMarkup, '-66|...|1',
628  ],
629  'text with entities 9|...' => [
630  'Kasper Sk...',
631  $textWithEntities, '9|...',
632  ],
633  'text with entities 10|...' => [
634  'Kasper Sk&aring;...',
635  $textWithEntities, '10|...',
636  ],
637  'text with entities 11|...' => [
638  'Kasper Sk&aring;r...',
639  $textWithEntities, '11|...',
640  ],
641  'text with entities 13|...' => [
642  'Kasper Sk&aring;rh&oslash;...',
643  $textWithEntities, '13|...',
644  ],
645  'text with entities 14|...' => [
646  'Kasper Sk&aring;rh&oslash;j...',
647  $textWithEntities, '14|...',
648  ],
649  'text with entities 15|...' => [
650  'Kasper Sk&aring;rh&oslash;j ...',
651  $textWithEntities, '15|...',
652  ],
653  'text with entities 16|...' => [
654  'Kasper Sk&aring;rh&oslash;j i...',
655  $textWithEntities, '16|...',
656  ],
657  'text with entities -57|...' => [
658  '...j implemented the; original version of the crop function.',
659  $textWithEntities, '-57|...',
660  ],
661  'text with entities -58|...' => [
662  '...&oslash;j implemented the; original version of the crop '
663  . 'function.',
664  $textWithEntities, '-58|...',
665  ],
666  'text with entities -59|...' => [
667  '...h&oslash;j implemented the; original version of the crop '
668  . 'function.',
669  $textWithEntities, '-59|...',
670  ],
671  'text with entities 4|...|1' => [
672  'Kasp...',
673  $textWithEntities, '4|...|1',
674  ],
675  'text with entities 9|...|1' => [
676  'Kasper...',
677  $textWithEntities, '9|...|1',
678  ],
679  'text with entities 10|...|1' => [
680  'Kasper...',
681  $textWithEntities, '10|...|1',
682  ],
683  'text with entities 11|...|1' => [
684  'Kasper...',
685  $textWithEntities, '11|...|1',
686  ],
687  'text with entities 13|...|1' => [
688  'Kasper...',
689  $textWithEntities, '13|...|1',
690  ],
691  'text with entities 14|...|1' => [
692  'Kasper Sk&aring;rh&oslash;j...',
693  $textWithEntities, '14|...|1',
694  ],
695  'text with entities 15|...|1' => [
696  'Kasper Sk&aring;rh&oslash;j...',
697  $textWithEntities, '15|...|1',
698  ],
699  'text with entities 16|...|1' => [
700  'Kasper Sk&aring;rh&oslash;j...',
701  $textWithEntities, '16|...|1',
702  ],
703  'text with entities -57|...|1' => [
704  '...implemented the; original version of the crop function.',
705  $textWithEntities, '-57|...|1',
706  ],
707  'text with entities -58|...|1' => [
708  '...implemented the; original version of the crop function.',
709  $textWithEntities, '-58|...|1',
710  ],
711  'text with entities -59|...|1' => [
712  '...implemented the; original version of the crop function.',
713  $textWithEntities, '-59|...|1',
714  ],
715  'text with dash in html-element 28|...|1' => [
716  'Some text with a link to <link email.address@example.org - '
717  . 'mail "Open email window">my...</link>',
718  'Some text with a link to <link email.address@example.org - m'
719  . 'ail "Open email window">my email.address@example.org<'
720  . '/link> and text after it',
721  '28|...|1',
722  ],
723  'html elements with dashes in attributes' => [
724  '<em data-foo="x">foobar</em>foo',
725  '<em data-foo="x">foobar</em>foobaz',
726  '9',
727  ],
728  'html elements with iframe embedded 24|...|1' => [
729  'Text with iframe <iframe src="//what.ever/"></iframe> and...',
730  'Text with iframe <iframe src="//what.ever/">'
731  . '</iframe> and text after it',
732  '24|...|1',
733  ],
734  'html elements with script tag embedded 24|...|1' => [
735  'Text with script <script>alert(\'foo\');</script> and...',
736  'Text with script <script>alert(\'foo\');</script> '
737  . 'and text after it',
738  '24|...|1',
739  ],
740  'text with linebreaks' => [
741  "Lorem ipsum dolor sit amet,\nconsetetur sadipscing elitr,\ns"
742  . 'ed diam nonumy eirmod tempor invidunt ut labore e'
743  . 't dolore magna',
744  $textWithLinebreaks, '121',
745  ],
746  ];
747  }
748 
759  public function cropHTML($expect, $content, $conf)
760  {
761  $this->handleCharset($content, $expect);
762  $this->assertSame($expect,
763  $this->subject->cropHTML($content, $conf));
764  }
765 
771  public function roundDataProvider()
772  {
773  return [
774  // floats
775  'down' => [1.0, 1.11, []],
776  'up' => [2.0, 1.51, []],
777  'rounds up from x.50' => [2.0, 1.50, []],
778  'down with decimals' => [0.12, 0.1231, ['decimals' => 2]],
779  'up with decimals' => [0.13, 0.1251, ['decimals' => 2]],
780  'ceil' => [1.0, 0.11, ['roundType' => 'ceil']],
781  'ceil does not accept decimals' => [
782  1.0, 0.111, [
783  'roundType' => 'ceil',
784  'decimals' => 2,
785  ],
786  ],
787  'floor' => [2.0, 2.99, ['roundType' => 'floor']],
788  'floor does not accept decimals' => [
789  2.0, 2.999, [
790  'roundType' => 'floor',
791  'decimals' => 2,
792  ],
793  ],
794  'round, down' => [1.0, 1.11, ['roundType' => 'round']],
795  'round, up' => [2.0, 1.55, ['roundType' => 'round']],
796  'round does accept decimals' => [
797  5.56, 5.5555, [
798  'roundType' => 'round',
799  'decimals' => 2,
800  ],
801  ],
802  // strings
803  'emtpy string' => [0.0, '', []],
804  'word string' => [0.0, 'word', []],
805  'float string' => [1.0, '1.123456789', []],
806  // other types
807  'null' => [0.0, null, []],
808  'false' => [0.0, false, []],
809  'true' => [1.0, true, []]
810  ];
811  }
812 
831  public function round($expect, $content, $conf)
832  {
833  $this->assertSame($expect,
834  $this->subject->_call('round', $content, $conf));
835  }
836 
841  {
842  $stdWrapConfiguration = [
843  'noTrimWrap' => '|| 123|',
844  'stdWrap.' => [
845  'wrap' => '<b>|</b>'
846  ]
847  ];
848  $this->assertSame(
849  '<b>Test</b> 123',
850  $this->subject->stdWrap('Test', $stdWrapConfiguration)
851  );
852  }
853 
858  {
859  $stdWrapConfiguration = [
860  'append' => 'TEXT',
861  'append.' => [
862  'data' => 'register:Counter'
863  ],
864  'stdWrap.' => [
865  'append' => 'LOAD_REGISTER',
866  'append.' => [
867  'Counter.' => [
868  'prioriCalc' => 'intval',
869  'cObject' => 'TEXT',
870  'cObject.' => [
871  'data' => 'register:Counter',
872  'wrap' => '|+1',
873  ]
874  ]
875  ]
876  ]
877  ];
878  $this->assertSame(
879  'Counter:1',
880  $this->subject->stdWrap('Counter:', $stdWrapConfiguration)
881  );
882  }
883 
889  public function numberFormatDataProvider()
890  {
891  return [
892  'testing decimals' => [
893  '0.80', 0.8,
894  ['decimals' => 2]
895  ],
896  'testing decimals with input as string' => [
897  '0.80', '0.8',
898  ['decimals' => 2]
899  ],
900  'testing dec_point' => [
901  '0,8', 0.8,
902  ['decimals' => 1, 'dec_point' => ',']
903  ],
904  'testing thousands_sep' => [
905  '1.000', 999.99,
906  [
907  'decimals' => 0,
908  'thousands_sep.' => ['char' => 46]
909  ]
910  ],
911  'testing mixture' => [
912  '1.281.731,5', 1281731.45,
913  [
914  'decimals' => 1,
915  'dec_point.' => ['char' => 44],
916  'thousands_sep.' => ['char' => 46]
917  ]
918  ]
919  ];
920  }
921 
928  public function numberFormat($expects, $content, $conf)
929  {
930  $this->assertSame($expects,
931  $this->subject->numberFormat($content, $conf));
932  }
933 
939  public function replacementDataProvider()
940  {
941  return [
942  'multiple replacements, including regex' => [
943  'There is an animal, an animal and an animal around the block! Yeah!',
944  'There_is_a_cat,_a_dog_and_a_tiger_in_da_hood!_Yeah!',
945  [
946  '20.' => [
947  'search' => '_',
948  'replace.' => ['char' => '32']
949  ],
950  '120.' => [
951  'search' => 'in da hood',
952  'replace' => 'around the block'
953  ],
954  '130.' => [
955  'search' => '#a (Cat|Dog|Tiger)#i',
956  'replace' => 'an animal',
957  'useRegExp' => '1'
958  ]
959  ]
960  ],
961  'replacement with optionSplit, normal pattern' => [
962  'There1is2a3cat,3a3dog3and3a3tiger3in3da3hood!3Yeah!',
963  'There_is_a_cat,_a_dog_and_a_tiger_in_da_hood!_Yeah!',
964  [
965  '10.' => [
966  'search' => '_',
967  'replace' => '1 || 2 || 3',
968  'useOptionSplitReplace' => '1'
969  ]
970  ]
971  ],
972  'replacement with optionSplit, using regex' => [
973  'There is a tiny cat, a midsized dog and a big tiger in da hood! Yeah!',
974  'There is a cat, a dog and a tiger in da hood! Yeah!',
975  [
976  '10.' => [
977  'search' => '#(a) (Cat|Dog|Tiger)#i',
978  'replace' => '${1} tiny ${2} || ${1} midsized ${2} || ${1} big ${2}',
979  'useOptionSplitReplace' => '1',
980  'useRegExp' => '1'
981  ]
982  ]
983  ]
984  ];
985  }
986 
997  public function replacement($expects, $content, $conf)
998  {
999  $this->assertSame($expects,
1000  $this->subject->_call('replacement', $content, $conf));
1001  }
1002 
1008  public function calcAgeDataProvider()
1009  {
1010  return [
1011  'minutes' => [
1012  '2 min', 120, ' min| hrs| days| yrs',
1013  ],
1014  'hours' => [
1015  '2 hrs', 7200, ' min| hrs| days| yrs',
1016  ],
1017  'days' => [
1018  '7 days', 604800, ' min| hrs| days| yrs',
1019  ],
1020  'day with provided singular labels' => [
1021  '1 day', 86400, ' min| hrs| days| yrs| min| hour| day| year',
1022  ],
1023  'years' => [
1024  '45 yrs', 1417997800, ' min| hrs| days| yrs',
1025  ],
1026  'different labels' => [
1027  '2 Minutes', 120, ' Minutes| Hrs| Days| Yrs',
1028  ],
1029  'negative values' => [
1030  '-7 days', -604800, ' min| hrs| days| yrs',
1031  ],
1032  'default label values for wrong label input' => [
1033  '2 min', 121, 10,
1034  ],
1035  'default singular label values for wrong label input' => [
1036  '1 year', 31536000, 10,
1037  ]
1038  ];
1039  }
1040 
1051  public function calcAge($expect, $timestamp, $labels)
1052  {
1053  $this->assertSame($expect,
1054  $this->subject->calcAge($timestamp, $labels));
1055  }
1056 
1061  {
1062  return [
1063  'Prevent silent bool conversion' => [
1064  '1+1',
1065  [
1066  'prioriCalc.' => [
1067  'wrap' => '|',
1068  ],
1069  ],
1070  '1+1',
1071  ],
1072  ];
1073  }
1074 
1082  public function stdWrapReturnsExpectation($content, array $configuration, $expectation)
1083  {
1084  $this->assertSame($expectation, $this->subject->stdWrap($content, $configuration));
1085  }
1086 
1092  public function substringDataProvider()
1093  {
1094  return [
1095  'sub -1' => ['g', 'substring', '-1'],
1096  'sub -1,0' => ['g', 'substring', '-1,0'],
1097  'sub -1,-1' => ['', 'substring', '-1,-1'],
1098  'sub -1,1' => ['g', 'substring', '-1,1'],
1099  'sub 0' => ['substring', 'substring', '0'],
1100  'sub 0,0' => ['substring', 'substring', '0,0'],
1101  'sub 0,-1' => ['substrin', 'substring', '0,-1'],
1102  'sub 0,1' => ['s', 'substring', '0,1'],
1103  'sub 1' => ['ubstring', 'substring', '1'],
1104  'sub 1,0' => ['ubstring', 'substring', '1,0'],
1105  'sub 1,-1' => ['ubstrin', 'substring', '1,-1'],
1106  'sub 1,1' => ['u', 'substring', '1,1'],
1107  'sub' => ['substring', 'substring', ''],
1108  ];
1109  }
1110 
1121  public function substring($expect, $content, $conf)
1122  {
1123  $this->assertSame($expect, $this->subject->substring($content, $conf));
1124  }
1125 
1127  // Tests concerning getData()
1129 
1134  {
1135  return [
1136  'Value in get-data' => ['onlyInGet', 'GetValue'],
1137  'Value in post-data' => ['onlyInPost', 'PostValue'],
1138  'Value in post-data overriding get-data' => ['inGetAndPost', 'ValueInPost'],
1139  ];
1140  }
1141 
1148  public function getDataWithTypeGp($key, $expectedValue)
1149  {
1150  $_GET = [
1151  'onlyInGet' => 'GetValue',
1152  'inGetAndPost' => 'ValueInGet',
1153  ];
1154  $_POST = [
1155  'onlyInPost' => 'PostValue',
1156  'inGetAndPost' => 'ValueInPost',
1157  ];
1158  $this->assertEquals($expectedValue, $this->subject->getData('gp:' . $key));
1159  }
1160 
1166  public function getDataWithTypeTsfe()
1167  {
1168  $this->assertEquals($GLOBALS['TSFE']->metaCharset, $this->subject->getData('tsfe:metaCharset'));
1169  }
1170 
1176  public function getDataWithTypeGetenv()
1177  {
1178  $envName = $this->getUniqueId('frontendtest');
1179  $value = $this->getUniqueId('someValue');
1180  putenv($envName . '=' . $value);
1181  $this->assertEquals($value, $this->subject->getData('getenv:' . $envName));
1182  }
1183 
1189  public function getDataWithTypeGetindpenv()
1190  {
1191  $this->subject->expects($this->once())->method('getEnvironmentVariable')
1192  ->with($this->equalTo('SCRIPT_FILENAME'))->will($this->returnValue('dummyPath'));
1193  $this->assertEquals('dummyPath', $this->subject->getData('getindpenv:SCRIPT_FILENAME'));
1194  }
1195 
1201  public function getDataWithTypeField()
1202  {
1203  $key = 'someKey';
1204  $value = 'someValue';
1205  $field = [$key => $value];
1206 
1207  $this->assertEquals($value, $this->subject->getData('field:' . $key, $field));
1208  }
1209 
1217  {
1218  $key = 'somekey|level1|level2';
1219  $value = 'somevalue';
1220  $field = ['somekey' => ['level1' => ['level2' => 'somevalue']]];
1221 
1222  $this->assertEquals($value, $this->subject->getData('field:' . $key, $field));
1223  }
1224 
1231  {
1232  $uid = $this->getUniqueId();
1233  $file = $this->createMock(File::class);
1234  $file->expects($this->once())->method('getUid')->will($this->returnValue($uid));
1235  $this->subject->setCurrentFile($file);
1236  $this->assertEquals($uid, $this->subject->getData('file:current:uid'));
1237  }
1238 
1244  public function getDataWithTypeParameters()
1245  {
1246  $key = $this->getUniqueId('someKey');
1247  $value = $this->getUniqueId('someValue');
1248  $this->subject->parameters[$key] = $value;
1249 
1250  $this->assertEquals($value, $this->subject->getData('parameters:' . $key));
1251  }
1252 
1258  public function getDataWithTypeRegister()
1259  {
1260  $key = $this->getUniqueId('someKey');
1261  $value = $this->getUniqueId('someValue');
1262  $GLOBALS['TSFE']->register[$key] = $value;
1263 
1264  $this->assertEquals($value, $this->subject->getData('register:' . $key));
1265  }
1266 
1272  public function getDataWithTypeLevel()
1273  {
1274  $rootline = [
1275  0 => ['uid' => 1, 'title' => 'title1'],
1276  1 => ['uid' => 2, 'title' => 'title2'],
1277  2 => ['uid' => 3, 'title' => 'title3'],
1278  ];
1279 
1280  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1281  $this->assertEquals(2, $this->subject->getData('level'));
1282  }
1283 
1289  public function getDataWithTypeGlobal()
1290  {
1291  $this->assertEquals($GLOBALS['TSFE']->metaCharset, $this->subject->getData('global:TSFE|metaCharset'));
1292  }
1293 
1299  public function getDataWithTypeLeveltitle()
1300  {
1301  $rootline = [
1302  0 => ['uid' => 1, 'title' => 'title1'],
1303  1 => ['uid' => 2, 'title' => 'title2'],
1304  2 => ['uid' => 3, 'title' => ''],
1305  ];
1306 
1307  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1308  $this->assertEquals('', $this->subject->getData('leveltitle:-1'));
1309  // since "title3" is not set, it will slide to "title2"
1310  $this->assertEquals('title2', $this->subject->getData('leveltitle:-1,slide'));
1311  }
1312 
1318  public function getDataWithTypeLevelmedia()
1319  {
1320  $rootline = [
1321  0 => ['uid' => 1, 'title' => 'title1', 'media' => 'media1'],
1322  1 => ['uid' => 2, 'title' => 'title2', 'media' => 'media2'],
1323  2 => ['uid' => 3, 'title' => 'title3', 'media' => ''],
1324  ];
1325 
1326  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1327  $this->assertEquals('', $this->subject->getData('levelmedia:-1'));
1328  // since "title3" is not set, it will slide to "title2"
1329  $this->assertEquals('media2', $this->subject->getData('levelmedia:-1,slide'));
1330  }
1331 
1337  public function getDataWithTypeLeveluid()
1338  {
1339  $rootline = [
1340  0 => ['uid' => 1, 'title' => 'title1'],
1341  1 => ['uid' => 2, 'title' => 'title2'],
1342  2 => ['uid' => 3, 'title' => 'title3'],
1343  ];
1344 
1345  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1346  $this->assertEquals(3, $this->subject->getData('leveluid:-1'));
1347  // every element will have a uid - so adding slide doesn't really make sense, just for completeness
1348  $this->assertEquals(3, $this->subject->getData('leveluid:-1,slide'));
1349  }
1350 
1356  public function getDataWithTypeLevelfield()
1357  {
1358  $rootline = [
1359  0 => ['uid' => 1, 'title' => 'title1', 'testfield' => 'field1'],
1360  1 => ['uid' => 2, 'title' => 'title2', 'testfield' => 'field2'],
1361  2 => ['uid' => 3, 'title' => 'title3', 'testfield' => ''],
1362  ];
1363 
1364  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1365  $this->assertEquals('', $this->subject->getData('levelfield:-1,testfield'));
1366  $this->assertEquals('field2', $this->subject->getData('levelfield:-1,testfield,slide'));
1367  }
1368 
1375  {
1376  $rootline1 = [
1377  0 => ['uid' => 1, 'title' => 'title1', 'testfield' => 'field1'],
1378  ];
1379  $rootline2 = [
1380  0 => ['uid' => 1, 'title' => 'title1', 'testfield' => 'field1'],
1381  1 => ['uid' => 2, 'title' => 'title2', 'testfield' => 'field2'],
1382  2 => ['uid' => 3, 'title' => 'title3', 'testfield' => 'field3'],
1383  ];
1384 
1385  $GLOBALS['TSFE']->tmpl->rootLine = $rootline1;
1386  $GLOBALS['TSFE']->rootLine = $rootline2;
1387  $this->assertEquals('field2', $this->subject->getData('fullrootline:-1,testfield'));
1388  }
1389 
1395  public function getDataWithTypeDate()
1396  {
1397  $format = 'Y-M-D';
1398  $defaultFormat = 'd/m Y';
1399 
1400  $this->assertEquals(date($format, $GLOBALS['EXEC_TIME']), $this->subject->getData('date:' . $format));
1401  $this->assertEquals(date($defaultFormat, $GLOBALS['EXEC_TIME']), $this->subject->getData('date'));
1402  }
1403 
1409  public function getDataWithTypePage()
1410  {
1411  $uid = rand();
1412  $GLOBALS['TSFE']->page['uid'] = $uid;
1413  $this->assertEquals($uid, $this->subject->getData('page:uid'));
1414  }
1415 
1421  public function getDataWithTypeCurrent()
1422  {
1423  $key = $this->getUniqueId('someKey');
1424  $value = $this->getUniqueId('someValue');
1425  $this->subject->data[$key] = $value;
1426  $this->subject->currentValKey = $key;
1427  $this->assertEquals($value, $this->subject->getData('current'));
1428  }
1429 
1435  public function getDataWithTypeDb()
1436  {
1437  $dummyRecord = ['uid' => 5, 'title' => 'someTitle'];
1438 
1439  $GLOBALS['TSFE']->sys_page->expects($this->atLeastOnce())->method('getRawRecord')->with('tt_content', '106')->will($this->returnValue($dummyRecord));
1440  $this->assertEquals($dummyRecord['title'], $this->subject->getData('db:tt_content:106:title'));
1441  }
1442 
1448  public function getDataWithTypeLll()
1449  {
1450  $key = $this->getUniqueId('someKey');
1451  $value = $this->getUniqueId('someValue');
1452  $language = $this->getUniqueId('someLanguage');
1453  $GLOBALS['TSFE']->LL_labels_cache[$language]['LLL:' . $key] = $value;
1454  $GLOBALS['TSFE']->lang = $language;
1455 
1456  $this->assertEquals($value, $this->subject->getData('lll:' . $key));
1457  }
1458 
1464  public function getDataWithTypePath()
1465  {
1466  $filenameIn = $this->getUniqueId('someValue');
1467  $filenameOut = $this->getUniqueId('someValue');
1468  $this->templateServiceMock->expects($this->atLeastOnce())->method('getFileName')->with($filenameIn)->will($this->returnValue($filenameOut));
1469  $this->assertEquals($filenameOut, $this->subject->getData('path:' . $filenameIn));
1470  }
1471 
1478  {
1479  $recordNumber = rand();
1480  $this->subject->parentRecordNumber = $recordNumber;
1481  $this->assertEquals($recordNumber, $this->subject->getData('cobj:parentRecordNumber'));
1482  }
1483 
1490  {
1491  $rootline = [
1492  0 => ['uid' => 1, 'title' => 'title1'],
1493  1 => ['uid' => 2, 'title' => 'title2'],
1494  2 => ['uid' => 3, 'title' => ''],
1495  ];
1496  $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)';
1497  $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1498 
1500  $result = $this->subject->getData('debug:rootLine');
1501  $cleanedResult = str_replace("\r", '', $result);
1502  $cleanedResult = str_replace("\n", '', $cleanedResult);
1503  $cleanedResult = str_replace("\t", '', $cleanedResult);
1504  $cleanedResult = str_replace(' ', '', $cleanedResult);
1505 
1506  $this->assertEquals($expectedResult, $cleanedResult);
1507  }
1508 
1515  {
1516  $rootline = [
1517  0 => ['uid' => 1, 'title' => 'title1'],
1518  1 => ['uid' => 2, 'title' => 'title2'],
1519  2 => ['uid' => 3, 'title' => ''],
1520  ];
1521  $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)';
1522  $GLOBALS['TSFE']->rootLine = $rootline;
1523 
1525  $result = $this->subject->getData('debug:fullRootLine');
1526  $cleanedResult = str_replace("\r", '', $result);
1527  $cleanedResult = str_replace("\n", '', $cleanedResult);
1528  $cleanedResult = str_replace("\t", '', $cleanedResult);
1529  $cleanedResult = str_replace(' ', '', $cleanedResult);
1530 
1531  $this->assertEquals($expectedResult, $cleanedResult);
1532  }
1533 
1539  public function getDataWithTypeDebugData()
1540  {
1541  $key = $this->getUniqueId('someKey');
1542  $value = $this->getUniqueId('someValue');
1543  $this->subject->data = [$key => $value];
1544 
1545  $expectedResult = 'array(1item)' . $key . '=>"' . $value . '"(' . strlen($value) . 'chars)';
1546 
1548  $result = $this->subject->getData('debug:data');
1549  $cleanedResult = str_replace("\r", '', $result);
1550  $cleanedResult = str_replace("\n", '', $cleanedResult);
1551  $cleanedResult = str_replace("\t", '', $cleanedResult);
1552  $cleanedResult = str_replace(' ', '', $cleanedResult);
1553 
1554  $this->assertEquals($expectedResult, $cleanedResult);
1555  }
1556 
1563  {
1564  $key = $this->getUniqueId('someKey');
1565  $value = $this->getUniqueId('someValue');
1566  $GLOBALS['TSFE']->register = [$key => $value];
1567 
1568  $expectedResult = 'array(1item)' . $key . '=>"' . $value . '"(' . strlen($value) . 'chars)';
1569 
1571  $result = $this->subject->getData('debug:register');
1572  $cleanedResult = str_replace("\r", '', $result);
1573  $cleanedResult = str_replace("\n", '', $cleanedResult);
1574  $cleanedResult = str_replace("\t", '', $cleanedResult);
1575  $cleanedResult = str_replace(' ', '', $cleanedResult);
1576 
1577  $this->assertEquals($expectedResult, $cleanedResult);
1578  }
1579 
1585  public function getDataWithTypeDebugPage()
1586  {
1587  $uid = rand();
1588  $GLOBALS['TSFE']->page = ['uid' => $uid];
1589 
1590  $expectedResult = 'array(1item)uid=>' . $uid . '(integer)';
1591 
1593  $result = $this->subject->getData('debug:page');
1594  $cleanedResult = str_replace("\r", '', $result);
1595  $cleanedResult = str_replace("\n", '', $cleanedResult);
1596  $cleanedResult = str_replace("\t", '', $cleanedResult);
1597  $cleanedResult = str_replace(' ', '', $cleanedResult);
1598 
1599  $this->assertEquals($expectedResult, $cleanedResult);
1600  }
1601 
1606  {
1607  $aTagParams = $this->subject->getATagParams(['ATagParams' => 'data-test="testdata"']);
1608  $this->assertEquals(' data-test="testdata"', $aTagParams);
1609  }
1610 
1615  {
1616  $GLOBALS['TSFE']->ATagParams = 'data-global="dataglobal"';
1617  $aTagParams = $this->subject->getATagParams(['ATagParams' => 'data-test="testdata"']);
1618  $this->assertEquals(' data-global="dataglobal" data-test="testdata"', $aTagParams);
1619  }
1620 
1625  {
1626  // make sure global ATagParams are empty
1627  $GLOBALS['TSFE']->ATagParams = '';
1628  $aTagParams = $this->subject->getATagParams(['ATagParams' => '']);
1629  $this->assertEquals('', $aTagParams);
1630  }
1631 
1636  {
1637  return [
1638  [null, null],
1639  ['', null],
1640  ['', []],
1641  ['fooo', ['foo' => 'bar']]
1642  ];
1643  }
1644 
1654  {
1655  $defaultImgTagTemplate = '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>';
1656  $result = $this->subject->getImageTagTemplate($key, $configuration);
1657  $this->assertEquals($result, $defaultImgTagTemplate);
1658  }
1659 
1664  {
1665  return [
1666  [
1667  'foo',
1668  [
1669  'layout.' => [
1670  'foo.' => [
1671  'element' => '<img src="###SRC###" srcset="###SOURCES###" ###PARAMS### ###ALTPARAMS### ###FOOBAR######SELFCLOSINGTAGSLASH###>'
1672  ]
1673  ]
1674  ],
1675  '<img src="###SRC###" srcset="###SOURCES###" ###PARAMS### ###ALTPARAMS### ###FOOBAR######SELFCLOSINGTAGSLASH###>'
1676  ]
1677 
1678  ];
1679  }
1680 
1690  public function getImageTagTemplateReturnTemplateElementIdentifiedByKey($key, $configuration, $expectation)
1691  {
1692  $result = $this->subject->getImageTagTemplate($key, $configuration);
1693  $this->assertEquals($result, $expectation);
1694  }
1695 
1700  {
1701  return [
1702  [null, null, null],
1703  ['foo', null, null],
1704  ['foo', ['sourceCollection.' => 1], 'bar']
1705  ];
1706  }
1707 
1717  public function getImageSourceCollectionReturnsEmptyStringIfNoSourcesAreDefined($layoutKey, $configuration, $file)
1718  {
1719  $result = $this->subject->getImageSourceCollection($layoutKey, $configuration, $file);
1720  $this->assertSame($result, '');
1721  }
1722 
1728  public function getImageSourceCollectionRendersDefinedSources()
1729  {
1731  $cObj = $this->getMockBuilder(ContentObjectRenderer::class)
1732  ->setMethods(['stdWrap', 'getImgResource'])
1733  ->getMock();
1734 
1735  $cObj->start([], 'tt_content');
1736 
1737  $layoutKey = 'test';
1738 
1739  $configuration = [
1740  'layoutKey' => 'test',
1741  'layout.' => [
1742  'test.' => [
1743  'element' => '<img ###SRC### ###SRCCOLLECTION### ###SELFCLOSINGTAGSLASH###>',
1744  'source' => '---###SRC###---'
1745  ]
1746  ],
1747  'sourceCollection.' => [
1748  '1.' => [
1749  'width' => '200'
1750  ]
1751  ]
1752  ];
1753 
1754  $file = 'testImageName';
1755 
1756  // Avoid calling of stdWrap
1757  $cObj
1758  ->expects($this->any())
1759  ->method('stdWrap')
1760  ->will($this->returnArgument(0));
1761 
1762  // Avoid calling of imgResource
1763  $cObj
1764  ->expects($this->exactly(1))
1765  ->method('getImgResource')
1766  ->with($this->equalTo('testImageName'))
1767  ->will($this->returnValue([100, 100, null, 'bar']));
1768 
1769  $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
1770 
1771  $this->assertEquals('---bar---', $result);
1772  }
1773 
1781  {
1785  $sourceCollectionArray = [
1786  'small.' => [
1787  'width' => 200,
1788  'srcsetCandidate' => '600w',
1789  'mediaQuery' => '(max-device-width: 600px)',
1790  'dataKey' => 'small',
1791  ],
1792  'smallRetina.' => [
1793  'if.directReturn' => 0,
1794  'width' => 200,
1795  'pixelDensity' => '2',
1796  'srcsetCandidate' => '600w 2x',
1797  'mediaQuery' => '(max-device-width: 600px) AND (min-resolution: 192dpi)',
1798  'dataKey' => 'smallRetina',
1799  ]
1800  ];
1801  return [
1802  [
1803  'default',
1804  [
1805  'layoutKey' => 'default',
1806  'layout.' => [
1807  'default.' => [
1808  'element' => '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>',
1809  'source' => ''
1810  ]
1811  ],
1812  'sourceCollection.' => $sourceCollectionArray
1813  ]
1814  ],
1815  ];
1816  }
1817 
1826  public function getImageSourceCollectionRendersDefinedLayoutKeyDefault($layoutKey, $configuration)
1827  {
1829  $cObj = $this->getMockBuilder(ContentObjectRenderer::class)
1830  ->setMethods(['stdWrap', 'getImgResource'])
1831  ->getMock();
1832 
1833  $cObj->start([], 'tt_content');
1834 
1835  $file = 'testImageName';
1836 
1837  // Avoid calling of stdWrap
1838  $cObj
1839  ->expects($this->any())
1840  ->method('stdWrap')
1841  ->will($this->returnArgument(0));
1842 
1843  $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
1844 
1845  $this->assertEmpty($result);
1846  }
1847 
1855  {
1859  $sourceCollectionArray = [
1860  'small.' => [
1861  'width' => 200,
1862  'srcsetCandidate' => '600w',
1863  'mediaQuery' => '(max-device-width: 600px)',
1864  'dataKey' => 'small',
1865  ],
1866  'smallRetina.' => [
1867  'if.directReturn' => 1,
1868  'width' => 200,
1869  'pixelDensity' => '2',
1870  'srcsetCandidate' => '600w 2x',
1871  'mediaQuery' => '(max-device-width: 600px) AND (min-resolution: 192dpi)',
1872  'dataKey' => 'smallRetina',
1873  ]
1874  ];
1875  return [
1876  [
1877  'srcset',
1878  [
1879  'layoutKey' => 'srcset',
1880  'layout.' => [
1881  'srcset.' => [
1882  'element' => '<img src="###SRC###" srcset="###SOURCECOLLECTION###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
1883  'source' => '|*|###SRC### ###SRCSETCANDIDATE###,|*|###SRC### ###SRCSETCANDIDATE###'
1884  ]
1885  ],
1886  'sourceCollection.' => $sourceCollectionArray
1887  ],
1888  'xhtml_strict',
1889  'bar-file.jpg 600w,bar-file.jpg 600w 2x',
1890  ],
1891  [
1892  'picture',
1893  [
1894  'layoutKey' => 'picture',
1895  'layout.' => [
1896  'picture.' => [
1897  'element' => '<picture>###SOURCECOLLECTION###<img src="###SRC###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###></picture>',
1898  'source' => '<source src="###SRC###" media="###MEDIAQUERY###"###SELFCLOSINGTAGSLASH###>'
1899  ]
1900  ],
1901  'sourceCollection.' => $sourceCollectionArray,
1902  ],
1903  'xhtml_strict',
1904  '<source src="bar-file.jpg" media="(max-device-width: 600px)" /><source src="bar-file.jpg" media="(max-device-width: 600px) AND (min-resolution: 192dpi)" />',
1905  ],
1906  [
1907  'picture',
1908  [
1909  'layoutKey' => 'picture',
1910  'layout.' => [
1911  'picture.' => [
1912  'element' => '<picture>###SOURCECOLLECTION###<img src="###SRC###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###></picture>',
1913  'source' => '<source src="###SRC###" media="###MEDIAQUERY###"###SELFCLOSINGTAGSLASH###>'
1914  ]
1915  ],
1916  'sourceCollection.' => $sourceCollectionArray,
1917  ],
1918  '',
1919  '<source src="bar-file.jpg" media="(max-device-width: 600px)"><source src="bar-file.jpg" media="(max-device-width: 600px) AND (min-resolution: 192dpi)">',
1920  ],
1921  [
1922  'data',
1923  [
1924  'layoutKey' => 'data',
1925  'layout.' => [
1926  'data.' => [
1927  'element' => '<img src="###SRC###" ###SOURCECOLLECTION### ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
1928  'source' => 'data-###DATAKEY###="###SRC###"'
1929  ]
1930  ],
1931  'sourceCollection.' => $sourceCollectionArray
1932  ],
1933  'xhtml_strict',
1934  'data-small="bar-file.jpg"data-smallRetina="bar-file.jpg"',
1935  ],
1936  ];
1937  }
1938 
1949  public function getImageSourceCollectionRendersDefinedLayoutKeyData($layoutKey, $configuration, $xhtmlDoctype, $expectedHtml)
1950  {
1952  $cObj = $this->getMockBuilder(ContentObjectRenderer::class)
1953  ->setMethods(['stdWrap', 'getImgResource'])
1954  ->getMock();
1955 
1956  $cObj->start([], 'tt_content');
1957 
1958  $file = 'testImageName';
1959 
1960  $GLOBALS['TSFE']->xhtmlDoctype = $xhtmlDoctype;
1961 
1962  // Avoid calling of stdWrap
1963  $cObj
1964  ->expects($this->any())
1965  ->method('stdWrap')
1966  ->will($this->returnArgument(0));
1967 
1968  // Avoid calling of imgResource
1969  $cObj
1970  ->expects($this->exactly(2))
1971  ->method('getImgResource')
1972  ->with($this->equalTo('testImageName'))
1973  ->will($this->returnValue([100, 100, null, 'bar-file.jpg']));
1974 
1975  $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
1976 
1977  $this->assertEquals($expectedHtml, $result);
1978  }
1979 
1986  {
1987  $this->subject = $this->getAccessibleMock(ContentObjectRenderer::class,
1988  ['getResourceFactory', 'stdWrap', 'getImgResource']
1989  );
1990  $this->subject->start([], 'tt_content');
1991 
1992  // Avoid calling stdwrap and getImgResource
1993  $this->subject->expects($this->any())
1994  ->method('stdWrap')
1995  ->will($this->returnArgument(0));
1996 
1997  $this->subject->expects($this->any())
1998  ->method('getImgResource')
1999  ->will($this->returnValue([100, 100, null, 'bar-file.jpg']));
2000 
2001  $resourceFactory = $this->createMock(ResourceFactory::class);
2002  $this->subject->expects($this->any())->method('getResourceFactory')->will($this->returnValue($resourceFactory));
2003 
2004  $className = $this->getUniqueId('tx_coretest_getImageSourceCollectionHookCalled');
2005  $getImageSourceCollectionHookMock = $this->getMockBuilder(
2006  ContentObjectOneSourceCollectionHookInterface::class)
2007  ->setMethods(['getOneSourceCollection'])
2008  ->setMockClassName($className)
2009  ->getMock();
2010  GeneralUtility::addInstance($className, $getImageSourceCollectionHookMock);
2011  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'][] = $className;
2012 
2013  $getImageSourceCollectionHookMock
2014  ->expects($this->exactly(1))
2015  ->method('getOneSourceCollection')
2016  ->will($this->returnCallback([$this, 'isGetOneSourceCollectionCalledCallback']));
2017 
2018  $configuration = [
2019  'layoutKey' => 'data',
2020  'layout.' => [
2021  'data.' => [
2022  'element' => '<img src="###SRC###" ###SOURCECOLLECTION### ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
2023  'source' => 'data-###DATAKEY###="###SRC###"'
2024  ]
2025  ],
2026  'sourceCollection.' => [
2027  'small.' => [
2028  'width' => 200,
2029  'srcsetCandidate' => '600w',
2030  'mediaQuery' => '(max-device-width: 600px)',
2031  'dataKey' => 'small',
2032  ],
2033  ],
2034  ];
2035 
2036  $result = $this->subject->getImageSourceCollection('data', $configuration, $this->getUniqueId('testImage-'));
2037 
2038  $this->assertSame($result, 'isGetOneSourceCollectionCalledCallback');
2039  }
2040 
2051  public function isGetOneSourceCollectionCalledCallback($sourceRenderConfiguration, $sourceConfiguration, $oneSourceCollection, $parent)
2052  {
2053  $this->assertTrue(is_array($sourceRenderConfiguration));
2054  $this->assertTrue(is_array($sourceConfiguration));
2055  return 'isGetOneSourceCollectionCalledCallback';
2056  }
2057 
2065  public function forceAbsoluteUrlReturnsCorrectAbsoluteUrl($expected, $url, array $configuration)
2066  {
2067  // Force hostname
2068  $this->subject->expects($this->any())->method('getEnvironmentVariable')->will($this->returnValueMap(
2069  [
2070  ['HTTP_HOST', 'localhost'],
2071  ['TYPO3_SITE_PATH', '/'],
2072  ]
2073  ));
2074  $GLOBALS['TSFE']->absRefPrefix = '';
2075 
2076  $this->assertEquals($expected, $this->subject->_call('forceAbsoluteUrl', $url, $configuration));
2077  }
2078 
2083  {
2084  return [
2085  'Missing forceAbsoluteUrl leaves URL untouched' => [
2086  'foo',
2087  'foo',
2088  []
2089  ],
2090  'Absolute URL stays unchanged' => [
2091  'http://example.org/',
2092  'http://example.org/',
2093  [
2094  'forceAbsoluteUrl' => '1'
2095  ]
2096  ],
2097  'Absolute URL stays unchanged 2' => [
2098  'http://example.org/resource.html',
2099  'http://example.org/resource.html',
2100  [
2101  'forceAbsoluteUrl' => '1'
2102  ]
2103  ],
2104  'Scheme and host w/o ending slash stays unchanged' => [
2105  'http://example.org',
2106  'http://example.org',
2107  [
2108  'forceAbsoluteUrl' => '1'
2109  ]
2110  ],
2111  'Scheme can be forced' => [
2112  'typo3://example.org',
2113  'http://example.org',
2114  [
2115  'forceAbsoluteUrl' => '1',
2116  'forceAbsoluteUrl.' => [
2117  'scheme' => 'typo3'
2118  ]
2119  ]
2120  ],
2121  'Relative path old-style' => [
2122  'http://localhost/fileadmin/dummy.txt',
2123  '/fileadmin/dummy.txt',
2124  [
2125  'forceAbsoluteUrl' => '1',
2126  ]
2127  ],
2128  'Relative path' => [
2129  'http://localhost/fileadmin/dummy.txt',
2130  'fileadmin/dummy.txt',
2131  [
2132  'forceAbsoluteUrl' => '1',
2133  ]
2134  ],
2135  'Scheme can be forced with pseudo-relative path' => [
2136  'typo3://localhost/fileadmin/dummy.txt',
2137  '/fileadmin/dummy.txt',
2138  [
2139  'forceAbsoluteUrl' => '1',
2140  'forceAbsoluteUrl.' => [
2141  'scheme' => 'typo3'
2142  ]
2143  ]
2144  ],
2145  'Hostname only is not treated as valid absolute URL' => [
2146  'http://localhost/example.org',
2147  'example.org',
2148  [
2149  'forceAbsoluteUrl' => '1'
2150  ]
2151  ],
2152  'Scheme and host is added to local file path' => [
2153  'typo3://localhost/fileadmin/my.pdf',
2154  'fileadmin/my.pdf',
2155  [
2156  'forceAbsoluteUrl' => '1',
2157  'forceAbsoluteUrl.' => [
2158  'scheme' => 'typo3'
2159  ]
2160  ]
2161  ]
2162  ];
2163  }
2164 
2169  {
2170  $this->expectException(\LogicException::class);
2171  $this->expectExceptionCode(1414513947);
2172  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2173  $this->subject->render($contentObjectFixture, []);
2174  }
2175 
2180  {
2181  $backupApplicationContext = GeneralUtility::getApplicationContext();
2183 
2184  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2185  $this->subject->render($contentObjectFixture, []);
2186 
2187  Fixtures\GeneralUtilityFixture::setApplicationContext($backupApplicationContext);
2188  }
2189 
2194  {
2195  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2196 
2197  $configuration = [
2198  'exceptionHandler' => '1'
2199  ];
2200  $this->subject->render($contentObjectFixture, $configuration);
2201  }
2202 
2207  {
2208  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2209 
2210  $this->frontendControllerMock->config['config']['contentObjectExceptionHandler'] = '1';
2211  $this->subject->render($contentObjectFixture, []);
2212  }
2213 
2218  {
2219  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2220  $this->expectException(\LogicException::class);
2221  $this->expectExceptionCode(1414513947);
2222  $this->frontendControllerMock->config['config']['contentObjectExceptionHandler'] = '1';
2223  $configuration = [
2224  'exceptionHandler' => '0'
2225  ];
2226  $this->subject->render($contentObjectFixture, $configuration);
2227  }
2228 
2233  {
2234  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2235 
2236  $configuration = [
2237  'exceptionHandler' => '1',
2238  'exceptionHandler.' => [
2239  'errorMessage' => 'New message for testing',
2240  ]
2241  ];
2242 
2243  $this->assertSame('New message for testing', $this->subject->render($contentObjectFixture, $configuration));
2244  }
2245 
2250  {
2251  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2252 
2253  $this->frontendControllerMock
2254  ->config['config']['contentObjectExceptionHandler.'] = [
2255  'errorMessage' => 'Global message for testing',
2256  ];
2257  $configuration = [
2258  'exceptionHandler' => '1',
2259  'exceptionHandler.' => [
2260  'errorMessage' => 'New message for testing',
2261  ]
2262  ];
2263 
2264  $this->assertSame('New message for testing', $this->subject->render($contentObjectFixture, $configuration));
2265  }
2266 
2271  {
2272  $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2273 
2274  $configuration = [
2275  'exceptionHandler' => '1',
2276  'exceptionHandler.' => [
2277  'ignoreCodes.' => ['10.' => '1414513947'],
2278  ]
2279  ];
2280  $this->expectException(\LogicException::class);
2281  $this->expectExceptionCode(1414513947);
2282  $this->subject->render($contentObjectFixture, $configuration);
2283  }
2284 
2289  {
2290  $contentObjectFixture = $this->getMockBuilder(AbstractContentObject::class)
2291  ->setConstructorArgs([$this->subject])
2292  ->getMock();
2293  $contentObjectFixture->expects($this->once())
2294  ->method('render')
2295  ->willReturnCallback(function () {
2296  throw new \LogicException('Exception during rendering', 1414513947);
2297  });
2298  return $contentObjectFixture;
2299  }
2300 
2305  {
2306  // Force hostname and subfolder
2307  $this->subject->expects($this->any())->method('getEnvironmentVariable')->will($this->returnValueMap(
2308  [
2309  ['HTTP_HOST', 'localhost'],
2310  ['TYPO3_SITE_PATH', '/subfolder/'],
2311  ]
2312  ));
2313 
2314  $expected = 'http://localhost/subfolder/fileadmin/my.pdf';
2315  $url = 'fileadmin/my.pdf';
2316  $configuration = [
2317  'forceAbsoluteUrl' => '1'
2318  ];
2319 
2320  $this->assertEquals($expected, $this->subject->_call('forceAbsoluteUrl', $url, $configuration));
2321  }
2322 
2326  protected function getLibParseTarget()
2327  {
2328  return [
2329  'override' => '',
2330  'override.' => [
2331  'if.' => [
2332  'isTrue.' => [
2333  'data' => 'TSFE:dtdAllowsFrames',
2334  ],
2335  ],
2336  ],
2337  ];
2338  }
2339 
2343  protected function getLibParseFunc()
2344  {
2345  return [
2346  'makelinks' => '1',
2347  'makelinks.' => [
2348  'http.' => [
2349  'keep' => '{$styles.content.links.keep}',
2350  'extTarget' => '',
2351  'extTarget.' => $this->getLibParseTarget(),
2352  'mailto.' => [
2353  'keep' => 'path',
2354  ],
2355  ],
2356  ],
2357  'tags' => [
2358  'link' => 'TEXT',
2359  'link.' => [
2360  'current' => '1',
2361  'typolink.' => [
2362  'parameter.' => [
2363  'data' => 'parameters : allParams',
2364  ],
2365  'extTarget.' => $this->getLibParseTarget(),
2366  'target.' => $this->getLibParseTarget(),
2367  ],
2368  'parseFunc.' => [
2369  'constants' => '1',
2370  ],
2371  ],
2372  ],
2373 
2374  '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',
2375  'denyTags' => '*',
2376  'sword' => '<span class="csc-sword">|</span>',
2377  'constants' => '1',
2378  'nonTypoTagStdWrap.' => [
2379  'HTMLparser' => '1',
2380  'HTMLparser.' => [
2381  'keepNonMatchedTags' => '1',
2382  'htmlSpecialChars' => '2',
2383  ],
2384  ],
2385  ];
2386  }
2387 
2391  protected function getLibParseFunc_RTE()
2392  {
2393  return [
2394  'parseFunc' => '',
2395  'parseFunc.' => [
2396  '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',
2397  'constants' => '1',
2398  'denyTags' => '*',
2399  'externalBlocks' => 'article, aside, blockquote, div, dd, dl, footer, header, nav, ol, section, table, ul, pre',
2400  'externalBlocks.' => [
2401  'article.' => [
2402  'callRecursive' => '1',
2403  'stripNL' => '1',
2404  ],
2405  'aside.' => [
2406  'callRecursive' => '1',
2407  'stripNL' => '1',
2408  ],
2409  'blockquote.' => [
2410  'callRecursive' => '1',
2411  'stripNL' => '1',
2412  ],
2413  'dd.' => [
2414  'callRecursive' => '1',
2415  'stripNL' => '1',
2416  ],
2417  'div.' => [
2418  'callRecursive' => '1',
2419  'stripNL' => '1',
2420  ],
2421  'dl.' => [
2422  'callRecursive' => '1',
2423  'stripNL' => '1',
2424  ],
2425  'footer.' => [
2426  'callRecursive' => '1',
2427  'stripNL' => '1',
2428  ],
2429  'header.' => [
2430  'callRecursive' => '1',
2431  'stripNL' => '1',
2432  ],
2433  'nav.' => [
2434  'callRecursive' => '1',
2435  'stripNL' => '1',
2436  ],
2437  'ol.' => [
2438  'callRecursive' => '1',
2439  'stripNL' => '1',
2440  ],
2441  'section.' => [
2442  'callRecursive' => '1',
2443  'stripNL' => '1',
2444  ],
2445  'table.' => [
2446  'HTMLtableCells' => '1',
2447  'HTMLtableCells.' => [
2448  'addChr10BetweenParagraphs' => '1',
2449  'default.' => [
2450  'stdWrap.' => [
2451  'parseFunc' => '=< lib.parseFunc_RTE',
2452  'parseFunc.' => [
2453  'nonTypoTagStdWrap.' => [
2454  'encapsLines.' => [
2455  'nonWrappedTag' => '',
2456  ],
2457  ],
2458  ],
2459  ],
2460  ],
2461  ],
2462  'stdWrap.' => [
2463  'HTMLparser' => '1',
2464  'HTMLparser.' => [
2465  'keepNonMatchedTags' => '1',
2466  'tags.' => [
2467  'table.' => [
2468  'fixAttrib.' => [
2469  'class.' => [
2470  'always' => '1',
2471  'default' => 'contenttable',
2472  'list' => 'contenttable',
2473  ],
2474  ],
2475  ],
2476  ],
2477  ],
2478  ],
2479  'stripNL' => '1',
2480  ],
2481  'ul.' => [
2482  'callRecursive' => '1',
2483  'stripNL' => '1',
2484  ],
2485  ],
2486  'makelinks' => '1',
2487  'makelinks.' => [
2488  'http.' => [
2489  'extTarget.' => [
2490  'override' => '_blank',
2491  'override.' => [
2492  'if.' => [
2493  'isTrue.' => [
2494  'data' => 'TSFE:dtdAllowsFrames',
2495  ],
2496  ],
2497  ],
2498  ],
2499  'keep' => 'path',
2500  ],
2501  ],
2502  'nonTypoTagStdWrap.' => [
2503  'encapsLines.' => [
2504  'addAttributes.' => [
2505  'P.' => [
2506  'class' => 'bodytext',
2507  'class.' => [
2508  'setOnly' => 'blank',
2509  ],
2510  ],
2511  ],
2512  'encapsTagList' => 'p,pre,h1,h2,h3,h4,h5,h6,hr,dt,li',
2513  'innerStdWrap_all.' => [
2514  'ifBlank' => '&nbsp;',
2515  ],
2516  'nonWrappedTag' => 'P',
2517  'remapTag.' => [
2518  'DIV' => 'P',
2519  ],
2520  ],
2521  'HTMLparser' => '1',
2522  'HTMLparser.' => [
2523  'htmlSpecialChars' => '2',
2524  'keepNonMatchedTags' => '1',
2525  ],
2526  ],
2527  'sword' => '<span class="csc-sword">|</span>',
2528  'tags.' => [
2529  'link' => 'TEXT',
2530  'link.' => [
2531  'current' => '1',
2532  'parseFunc.' => [
2533  'constants' => '1',
2534  ],
2535  'typolink.' => [
2536  'extTarget.' => [
2537  'override' => '',
2538  'override.' => [
2539  'if.' => [
2540  'isTrue.' => [
2541  'data' => 'TSFE:dtdAllowsFrames',
2542  ],
2543  ],
2544  ],
2545  ],
2546  'parameter.' => [
2547  'data' => 'parameters : allParams',
2548  ],
2549  'target.' => [
2550  'override' => '',
2551  'override.' => [
2552  'if.' => [
2553  'isTrue.' => [
2554  'data' => 'TSFE:dtdAllowsFrames',
2555  ],
2556  ],
2557  ],
2558  ],
2559  ],
2560  ],
2561  ],
2562  ],
2563  ];
2564  }
2565 
2570  {
2571  return [
2572  'Text without tag is wrapped with <p> tag' => [
2573  'Text without tag',
2574  $this->getLibParseFunc_RTE(),
2575  '<p class="bodytext">Text without tag</p>',
2576  ],
2577  'Text wrapped with <p> tag remains the same' => [
2578  '<p class="myclass">Text with &lt;p&gt; tag</p>',
2579  $this->getLibParseFunc_RTE(),
2580  '<p class="myclass">Text with &lt;p&gt; tag</p>',
2581  ],
2582  'Text with absolute external link' => [
2583  'Text with <link http://example.com/foo/>external link</link>',
2584  $this->getLibParseFunc_RTE(),
2585  '<p class="bodytext">Text with <a href="http://example.com/foo/">external link</a></p>',
2586  ],
2587  'Empty lines are not duplicated' => [
2588  LF,
2589  $this->getLibParseFunc_RTE(),
2590  '<p class="bodytext">&nbsp;</p>',
2591  ],
2592  'Multiple empty lines with no text' => [
2593  LF . LF . LF,
2594  $this->getLibParseFunc_RTE(),
2595  '<p class="bodytext">&nbsp;</p>' . LF . '<p class="bodytext">&nbsp;</p>' . LF . '<p class="bodytext">&nbsp;</p>',
2596  ],
2597  'Empty lines are not duplicated at the end of content' => [
2598  'test' . LF . LF,
2599  $this->getLibParseFunc_RTE(),
2600  '<p class="bodytext">test</p>' . LF . '<p class="bodytext">&nbsp;</p>',
2601  ],
2602  'Empty lines are not trimmed' => [
2603  LF . 'test' . LF,
2604  $this->getLibParseFunc_RTE(),
2605  '<p class="bodytext">&nbsp;</p>' . LF . '<p class="bodytext">test</p>' . LF . '<p class="bodytext">&nbsp;</p>',
2606  ],
2607  ];
2608  }
2609 
2617  public function stdWrap_parseFuncReturnsParsedHtml($value, $configuration, $expectedResult)
2618  {
2619  $this->assertEquals($expectedResult, $this->subject->stdWrap_parseFunc($value, $configuration));
2620  }
2621 
2626  {
2627  return [
2628  'Link to url' => [
2629  'TYPO3',
2630  [
2631  'parameter' => 'http://typo3.org',
2632  ],
2633  '<a href="http://typo3.org">TYPO3</a>',
2634  ],
2635  'Link to url without schema' => [
2636  'TYPO3',
2637  [
2638  'parameter' => 'typo3.org',
2639  ],
2640  '<a href="http://typo3.org">TYPO3</a>',
2641  ],
2642  'Link to url without link text' => [
2643  '',
2644  [
2645  'parameter' => 'http://typo3.org',
2646  ],
2647  '<a href="http://typo3.org">http://typo3.org</a>',
2648  ],
2649  'Link to url with attributes' => [
2650  'TYPO3',
2651  [
2652  'parameter' => 'http://typo3.org',
2653  'ATagParams' => 'class="url-class"',
2654  'extTarget' => '_blank',
2655  'title' => 'Open new window',
2656  ],
2657  '<a href="http://typo3.org" title="Open new window" target="_blank" class="url-class">TYPO3</a>',
2658  ],
2659  'Link to url with attributes in parameter' => [
2660  'TYPO3',
2661  [
2662  'parameter' => 'http://typo3.org _blank url-class "Open new window"',
2663  ],
2664  '<a href="http://typo3.org" title="Open new window" target="_blank" class="url-class">TYPO3</a>',
2665  ],
2666  'Link to url with script tag' => [
2667  '',
2668  [
2669  'parameter' => 'http://typo3.org<script>alert(123)</script>',
2670  ],
2671  '<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>',
2672  ],
2673  'Link to email address' => [
2674  'Email address',
2675  [
2676  'parameter' => 'foo@bar.org',
2677  ],
2678  '<a href="mailto:foo@bar.org">Email address</a>',
2679  ],
2680  'Link to email address without link text' => [
2681  '',
2682  [
2683  'parameter' => 'foo@bar.org',
2684  ],
2685  '<a href="mailto:foo@bar.org">foo@bar.org</a>',
2686  ],
2687  'Link to email with attributes' => [
2688  'Email address',
2689  [
2690  'parameter' => 'foo@bar.org',
2691  'ATagParams' => 'class="email-class"',
2692  'title' => 'Write an email',
2693  ],
2694  '<a href="mailto:foo@bar.org" title="Write an email" class="email-class">Email address</a>',
2695  ],
2696  'Link to email with attributes in parameter' => [
2697  'Email address',
2698  [
2699  'parameter' => 'foo@bar.org - email-class "Write an email"',
2700  ],
2701  '<a href="mailto:foo@bar.org" title="Write an email" class="email-class">Email address</a>',
2702  ],
2703  ];
2704  }
2705 
2713  public function typolinkReturnsCorrectLinksForEmailsAndUrls($linkText, $configuration, $expectedResult)
2714  {
2715  $templateServiceObjectMock = $this->getMockBuilder(TemplateService::class)
2716  ->setMethods(['dummy'])
2717  ->getMock();
2718  $templateServiceObjectMock->setup = [
2719  'lib.' => [
2720  'parseFunc.' => $this->getLibParseFunc(),
2721  ],
2722  ];
2723  $typoScriptFrontendControllerMockObject = $this->createMock(TypoScriptFrontendController::class);
2724  $typoScriptFrontendControllerMockObject->config = [
2725  'config' => [],
2726  'mainScript' => 'index.php',
2727  ];
2728  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
2729  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
2730  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
2731 
2732  $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
2733  }
2734 
2743  public function typoLinkEncodesMailAddressForSpamProtection(array $settings, $linkText, $mailAddress, $expected)
2744  {
2745  $this->getFrontendController()->spamProtectEmailAddresses = $settings['spamProtectEmailAddresses'];
2746  $this->getFrontendController()->config['config'] = $settings;
2747  $typoScript = ['parameter' => $mailAddress];
2748 
2749  $this->assertEquals($expected, $this->subject->typoLink($linkText, $typoScript));
2750  }
2751 
2756  {
2757  return [
2758  'plain mail without mailto scheme' => [
2759  [
2760  'spamProtectEmailAddresses' => '',
2761  'spamProtectEmailAddresses_atSubst' => '',
2762  'spamProtectEmailAddresses_lastDotSubst' => '',
2763  ],
2764  'some.body@test.typo3.org',
2765  'some.body@test.typo3.org',
2766  '<a href="mailto:some.body@test.typo3.org">some.body@test.typo3.org</a>',
2767  ],
2768  'plain mail with mailto scheme' => [
2769  [
2770  'spamProtectEmailAddresses' => '',
2771  'spamProtectEmailAddresses_atSubst' => '',
2772  'spamProtectEmailAddresses_lastDotSubst' => '',
2773  ],
2774  'some.body@test.typo3.org',
2775  'mailto:some.body@test.typo3.org',
2776  '<a href="mailto:some.body@test.typo3.org">some.body@test.typo3.org</a>',
2777  ],
2778  'plain with at and dot substitution' => [
2779  [
2780  'spamProtectEmailAddresses' => '0',
2781  'spamProtectEmailAddresses_atSubst' => '(at)',
2782  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
2783  ],
2784  'some.body@test.typo3.org',
2785  'mailto:some.body@test.typo3.org',
2786  '<a href="mailto:some.body@test.typo3.org">some.body@test.typo3.org</a>',
2787  ],
2788  'mono-alphabetic substitution offset +1' => [
2789  [
2790  'spamProtectEmailAddresses' => '1',
2791  'spamProtectEmailAddresses_atSubst' => '',
2792  'spamProtectEmailAddresses_lastDotSubst' => '',
2793  ],
2794  'some.body@test.typo3.org',
2795  'mailto:some.body@test.typo3.org',
2796  '<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body(at)test.typo3.org</a>',
2797  ],
2798  'mono-alphabetic substitution offset +1 with at substitution' => [
2799  [
2800  'spamProtectEmailAddresses' => '1',
2801  'spamProtectEmailAddresses_atSubst' => '@',
2802  'spamProtectEmailAddresses_lastDotSubst' => '',
2803  ],
2804  'some.body@test.typo3.org',
2805  'mailto:some.body@test.typo3.org',
2806  '<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body@test.typo3.org</a>',
2807  ],
2808  'mono-alphabetic substitution offset +1 with at and dot substitution' => [
2809  [
2810  'spamProtectEmailAddresses' => '1',
2811  'spamProtectEmailAddresses_atSubst' => '(at)',
2812  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
2813  ],
2814  'some.body@test.typo3.org',
2815  'mailto:some.body@test.typo3.org',
2816  '<a href="javascript:linkTo_UnCryptMailto(\'nbjmup+tpnf\/cpezAuftu\/uzqp4\/psh\');">some.body(at)test.typo3(dot)org</a>',
2817  ],
2818  'mono-alphabetic substitution offset -1 with at and dot substitution' => [
2819  [
2820  'spamProtectEmailAddresses' => '-1',
2821  'spamProtectEmailAddresses_atSubst' => '(at)',
2822  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
2823  ],
2824  'some.body@test.typo3.org',
2825  'mailto:some.body@test.typo3.org',
2826  '<a href="javascript:linkTo_UnCryptMailto(\'lzhksn9rnld-ancxZsdrs-sxon2-nqf\');">some.body(at)test.typo3(dot)org</a>',
2827  ],
2828  'entity substitution with at and dot substitution' => [
2829  [
2830  'spamProtectEmailAddresses' => 'ascii',
2831  'spamProtectEmailAddresses_atSubst' => '',
2832  'spamProtectEmailAddresses_lastDotSubst' => '',
2833  ],
2834  'some.body@test.typo3.org',
2835  'mailto:some.body@test.typo3.org',
2836  '<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>',
2837  ],
2838  'entity substitution with at and dot substitution with at and dot substitution' => [
2839  [
2840  'spamProtectEmailAddresses' => 'ascii',
2841  'spamProtectEmailAddresses_atSubst' => '(at)',
2842  'spamProtectEmailAddresses_lastDotSubst' => '(dot)',
2843  ],
2844  'some.body@test.typo3.org',
2845  'mailto:some.body@test.typo3.org',
2846  '<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>',
2847  ],
2848  ];
2849  }
2850 
2855  {
2856  return [
2857  'Link to file' => [
2858  'My file',
2859  [
2860  'parameter' => 'fileadmin/foo.bar',
2861  ],
2862  '<a href="fileadmin/foo.bar">My file</a>',
2863  ],
2864  'Link to file without link text' => [
2865  '',
2866  [
2867  'parameter' => 'fileadmin/foo.bar',
2868  ],
2869  '<a href="fileadmin/foo.bar">fileadmin/foo.bar</a>',
2870  ],
2871  'Link to file with attributes' => [
2872  'My file',
2873  [
2874  'parameter' => 'fileadmin/foo.bar',
2875  'ATagParams' => 'class="file-class"',
2876  'fileTarget' => '_blank',
2877  'title' => 'Title of the file',
2878  ],
2879  '<a href="fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
2880  ],
2881  'Link to file with attributes in parameter' => [
2882  'My file',
2883  [
2884  'parameter' => 'fileadmin/foo.bar _blank file-class "Title of the file"',
2885  ],
2886  '<a href="fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
2887  ],
2888  'Link to file with script tag in name' => [
2889  '',
2890  [
2891  'parameter' => 'fileadmin/<script>alert(123)</script>',
2892  ],
2893  '<a href="fileadmin/&lt;script&gt;alert(123)&lt;/script&gt;">fileadmin/&lt;script&gt;alert(123)&lt;/script&gt;</a>',
2894  ],
2895  ];
2896  }
2897 
2905  public function typolinkReturnsCorrectLinksFiles($linkText, $configuration, $expectedResult)
2906  {
2907  $templateServiceObjectMock = $this->getMockBuilder(TemplateService::class)
2908  ->setMethods(['dummy'])
2909  ->getMock();
2910  $templateServiceObjectMock->setup = [
2911  'lib.' => [
2912  'parseFunc.' => $this->getLibParseFunc(),
2913  ],
2914  ];
2915  $typoScriptFrontendControllerMockObject = $this->createMock(TypoScriptFrontendController::class);
2916  $typoScriptFrontendControllerMockObject->config = [
2917  'config' => [],
2918  'mainScript' => 'index.php',
2919  ];
2920  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
2921  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
2922  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
2923 
2924  $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
2925  }
2926 
2931  {
2932  return [
2933  'Link to file' => [
2934  'My file',
2935  [
2936  'parameter' => 'fileadmin/foo.bar',
2937  ],
2938  '/',
2939  '<a href="/fileadmin/foo.bar">My file</a>',
2940  ],
2941  'Link to file with longer absRefPrefix' => [
2942  'My file',
2943  [
2944  'parameter' => 'fileadmin/foo.bar',
2945  ],
2946  '/sub/',
2947  '<a href="/sub/fileadmin/foo.bar">My file</a>',
2948  ],
2949  'Link to absolute file' => [
2950  'My file',
2951  [
2952  'parameter' => '/images/foo.bar',
2953  ],
2954  '/',
2955  '<a href="/images/foo.bar">My file</a>',
2956  ],
2957  'Link to absolute file with longer absRefPrefix' => [
2958  'My file',
2959  [
2960  'parameter' => '/images/foo.bar',
2961  ],
2962  '/sub/',
2963  '<a href="/images/foo.bar">My file</a>',
2964  ],
2965  'Link to absolute file with identical longer absRefPrefix' => [
2966  'My file',
2967  [
2968  'parameter' => '/sub/fileadmin/foo.bar',
2969  ],
2970  '/sub/',
2971  '<a href="/sub/fileadmin/foo.bar">My file</a>',
2972  ],
2973  'Link to file with empty absRefPrefix' => [
2974  'My file',
2975  [
2976  'parameter' => 'fileadmin/foo.bar',
2977  ],
2978  '',
2979  '<a href="fileadmin/foo.bar">My file</a>',
2980  ],
2981  'Link to absolute file with empty absRefPrefix' => [
2982  'My file',
2983  [
2984  'parameter' => '/fileadmin/foo.bar',
2985  ],
2986  '',
2987  '<a href="/fileadmin/foo.bar">My file</a>',
2988  ],
2989  'Link to file with attributes with absRefPrefix' => [
2990  'My file',
2991  [
2992  'parameter' => 'fileadmin/foo.bar',
2993  'ATagParams' => 'class="file-class"',
2994  'fileTarget' => '_blank',
2995  'title' => 'Title of the file',
2996  ],
2997  '/',
2998  '<a href="/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
2999  ],
3000  'Link to file with attributes with longer absRefPrefix' => [
3001  'My file',
3002  [
3003  'parameter' => 'fileadmin/foo.bar',
3004  'ATagParams' => 'class="file-class"',
3005  'fileTarget' => '_blank',
3006  'title' => 'Title of the file',
3007  ],
3008  '/sub/',
3009  '<a href="/sub/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
3010  ],
3011  'Link to absolute file with attributes with absRefPrefix' => [
3012  'My file',
3013  [
3014  'parameter' => '/images/foo.bar',
3015  'ATagParams' => 'class="file-class"',
3016  'fileTarget' => '_blank',
3017  'title' => 'Title of the file',
3018  ],
3019  '/',
3020  '<a href="/images/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
3021  ],
3022  'Link to absolute file with attributes with longer absRefPrefix' => [
3023  'My file',
3024  [
3025  'parameter' => '/images/foo.bar',
3026  'ATagParams' => 'class="file-class"',
3027  'fileTarget' => '_blank',
3028  'title' => 'Title of the file',
3029  ],
3030  '/sub/',
3031  '<a href="/images/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
3032  ],
3033  'Link to absolute file with attributes with identical longer absRefPrefix' => [
3034  'My file',
3035  [
3036  'parameter' => '/sub/fileadmin/foo.bar',
3037  'ATagParams' => 'class="file-class"',
3038  'fileTarget' => '_blank',
3039  'title' => 'Title of the file',
3040  ],
3041  '/sub/',
3042  '<a href="/sub/fileadmin/foo.bar" title="Title of the file" target="_blank" class="file-class">My file</a>',
3043  ],
3044  ];
3045  }
3046 
3055  public function typolinkReturnsCorrectLinksForFilesWithAbsRefPrefix($linkText, $configuration, $absRefPrefix, $expectedResult)
3056  {
3057  $templateServiceObjectMock = $this->getMockBuilder(TemplateService::class)
3058  ->setMethods(['dummy'])
3059  ->getMock();
3060  $templateServiceObjectMock->setup = [
3061  'lib.' => [
3062  'parseFunc.' => $this->getLibParseFunc(),
3063  ],
3064  ];
3065  $typoScriptFrontendControllerMockObject = $this->createMock(TypoScriptFrontendController::class);
3066  $typoScriptFrontendControllerMockObject->config = [
3067  'config' => [],
3068  'mainScript' => 'index.php',
3069  ];
3070  $typoScriptFrontendControllerMockObject->tmpl = $templateServiceObjectMock;
3071  $GLOBALS['TSFE'] = $typoScriptFrontendControllerMockObject;
3072  $GLOBALS['TSFE']->absRefPrefix = $absRefPrefix;
3073  $this->subject->_set('typoScriptFrontendController', $typoScriptFrontendControllerMockObject);
3074 
3075  $this->assertEquals($expectedResult, $this->subject->typoLink($linkText, $configuration));
3076  }
3077 
3082  {
3083  $conf = [
3084  'token' => ',',
3085  'returnCount' => 1
3086  ];
3087  $expectedResult = 5;
3088  $amountOfEntries = $this->subject->splitObj('1, 2, 3, 4, 5', $conf);
3089  $this->assertSame(
3090  $expectedResult,
3091  $amountOfEntries
3092  );
3093  }
3094 
3096  // Test concerning link generation
3098 
3103  {
3104  $fileNameAndPath = PATH_site . 'typo3temp/var/tests/phpunitJumpUrlTestFile with spaces & amps.txt';
3105  file_put_contents($fileNameAndPath, 'Some test data');
3106  $relativeFileNameAndPath = substr($fileNameAndPath, strlen(PATH_site));
3107  $fileName = substr($fileNameAndPath, strlen(PATH_site . 'typo3temp/var/tests/'));
3108 
3109  $expectedLink = str_replace('%2F', '/', rawurlencode($relativeFileNameAndPath));
3110  $result = $this->subject->filelink($fileName, ['path' => 'typo3temp/var/tests/']);
3111  $this->assertEquals('<a href="' . $expectedLink . '">' . $fileName . '</a>', $result);
3112 
3113  GeneralUtility::unlink_tempfile($fileNameAndPath);
3114  }
3115 
3120  {
3121  return [
3122  'no markers defined' => [
3123  'dummy content with ###UNREPLACED### marker',
3124  [],
3125  [],
3126  [],
3127  'dummy content with ###UNREPLACED### marker',
3128  false,
3129  false
3130  ],
3131  'no markers used' => [
3132  'dummy content with no marker',
3133  [
3134  '###REPLACED###' => '_replaced_'
3135  ],
3136  [],
3137  [],
3138  'dummy content with no marker',
3139  true,
3140  false
3141  ],
3142  'one marker' => [
3143  'dummy content with ###REPLACED### marker',
3144  [
3145  '###REPLACED###' => '_replaced_'
3146  ],
3147  [],
3148  [],
3149  'dummy content with _replaced_ marker'
3150  ],
3151  'one marker with lots of chars' => [
3152  'dummy content with ###RE.:##-=_()LACED### marker',
3153  [
3154  '###RE.:##-=_()LACED###' => '_replaced_'
3155  ],
3156  [],
3157  [],
3158  'dummy content with _replaced_ marker'
3159  ],
3160  'markers which are special' => [
3161  'dummy ###aa##.#######A### ######',
3162  [
3163  '###aa##.###' => 'content ',
3164  '###A###' => 'is',
3165  '######' => '-is not considered-'
3166  ],
3167  [],
3168  [],
3169  'dummy content #is ######'
3170  ],
3171  'two markers in content, but more defined' => [
3172  'dummy ###CONTENT### with ###REPLACED### marker',
3173  [
3174  '###REPLACED###' => '_replaced_',
3175  '###CONTENT###' => 'content',
3176  '###NEVERUSED###' => 'bar'
3177  ],
3178  [],
3179  [],
3180  'dummy content with _replaced_ marker'
3181  ],
3182  'one subpart' => [
3183  'dummy content with ###ASUBPART### around some text###ASUBPART###.',
3184  [],
3185  [
3186  '###ASUBPART###' => 'some other text'
3187  ],
3188  [],
3189  'dummy content with some other text.'
3190  ],
3191  'one wrapped subpart' => [
3192  'dummy content with ###AWRAPPEDSUBPART### around some text###AWRAPPEDSUBPART###.',
3193  [],
3194  [],
3195  [
3196  '###AWRAPPEDSUBPART###' => [
3197  'more content',
3198  'content'
3199  ]
3200  ],
3201  'dummy content with more content around some textcontent.'
3202  ],
3203  'one subpart with markers, not replaced recursively' => [
3204  'dummy ###CONTENT### with ###ASUBPART### around ###SOME### text###ASUBPART###.',
3205  [
3206  '###CONTENT###' => 'content',
3207  '###SOME###' => '-this should never make it into output-',
3208  '###OTHER_NOT_REPLACED###' => '-this should never make it into output-'
3209  ],
3210  [
3211  '###ASUBPART###' => 'some ###OTHER_NOT_REPLACED### text'
3212  ],
3213  [],
3214  'dummy content with some ###OTHER_NOT_REPLACED### text.'
3215  ],
3216  ];
3217  }
3218 
3231  public function substituteMarkerArrayCachedReturnsExpectedContent($content, array $markContentArray, array $subpartContentArray, array $wrappedSubpartContentArray, $expectedContent, $shouldQueryCache = true, $shouldStoreCache = true)
3232  {
3234  $pageRepo = $this->frontendControllerMock->sys_page;
3235  $pageRepo->resetCallCount();
3236 
3237  $resultContent = $this->subject->substituteMarkerArrayCached($content, $markContentArray, $subpartContentArray, $wrappedSubpartContentArray);
3238 
3239  $this->assertSame((int)$shouldQueryCache, $pageRepo::$getHashCallCount, 'getHash call count mismatch');
3240  $this->assertSame((int)$shouldStoreCache, $pageRepo::$storeHashCallCount, 'storeHash call count mismatch');
3241  $this->assertSame($expectedContent, $resultContent);
3242  }
3243 
3247  public function substituteMarkerArrayCachedRetrievesCachedValueFromRuntimeCache()
3248  {
3250  $pageRepo = $this->frontendControllerMock->sys_page;
3251  $pageRepo->resetCallCount();
3252 
3253  $content = 'Please tell me this ###FOO###.';
3254  $markContentArray = [
3255  '###FOO###' => 'foo',
3256  '###NOTUSED###' => 'blub'
3257  ];
3258  $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize([$content, array_keys($markContentArray)]));
3259  $this->subject->substMarkerCache[$storeKey] = [
3260  'c' => [
3261  'Please tell me this ',
3262  '.'
3263  ],
3264  'k' => [
3265  '###FOO###'
3266  ],
3267  ];
3268  $resultContent = $this->subject->substituteMarkerArrayCached($content, $markContentArray);
3269  $this->assertSame(0, $pageRepo::$getHashCallCount);
3270  $this->assertSame('Please tell me this foo.', $resultContent);
3271  }
3272 
3276  public function substituteMarkerArrayCachedRetrievesCachedValueFromDbCache()
3277  {
3279  $pageRepo = $this->frontendControllerMock->sys_page;
3280  $pageRepo->resetCallCount();
3281 
3282  $content = 'Please tell me this ###FOO###.';
3283  $markContentArray = [
3284  '###FOO###' => 'foo',
3285  '###NOTUSED###' => 'blub'
3286  ];
3287  $pageRepo::$dbCacheContent = [
3288  'c' => [
3289  'Please tell me this ',
3290  '.'
3291  ],
3292  'k' => [
3293  '###FOO###'
3294  ],
3295  ];
3296  $resultContent = $this->subject->substituteMarkerArrayCached($content, $markContentArray);
3297  $this->assertSame(1, $pageRepo::$getHashCallCount, 'getHash call count mismatch');
3298  $this->assertSame(0, $pageRepo::$storeHashCallCount, 'storeHash call count mismatch');
3299  $this->assertSame('Please tell me this foo.', $resultContent);
3300  }
3301 
3305  public function substituteMarkerArrayCachedStoresResultInCaches()
3306  {
3308  $pageRepo = $this->frontendControllerMock->sys_page;
3309  $pageRepo->resetCallCount();
3310 
3311  $content = 'Please tell me this ###FOO###.';
3312  $markContentArray = [
3313  '###FOO###' => 'foo',
3314  '###NOTUSED###' => 'blub'
3315  ];
3316  $resultContent = $this->subject->substituteMarkerArrayCached($content, $markContentArray);
3317 
3318  $storeKey = md5('substituteMarkerArrayCached_storeKey:' . serialize([$content, array_keys($markContentArray)]));
3319  $storeArr = [
3320  'c' => [
3321  'Please tell me this ',
3322  '.'
3323  ],
3324  'k' => [
3325  '###FOO###'
3326  ],
3327  ];
3328  $this->assertSame(1, $pageRepo::$getHashCallCount);
3329  $this->assertSame('Please tell me this foo.', $resultContent);
3330  $this->assertSame($storeArr, $this->subject->substMarkerCache[$storeKey]);
3331  $this->assertSame(1, $pageRepo::$storeHashCallCount);
3332  }
3333 
3340  {
3341  $value = $this->getUniqueId('value');
3342  $wrap = [$this->getUniqueId('wrap')];
3343  $valueConf = ['key' => $value];
3344  $wrapConf = ['key.' => $wrap];
3345  $conf = array_merge($valueConf, $wrapConf);
3346  $will = $this->getUniqueId('stdWrap');
3347 
3348  return [
3349  'no conf' => [
3350  '',
3351  [],
3352  0,
3353  null,
3354  null,
3355  null
3356  ],
3357  'value conf only' => [
3358  $value,
3359  $valueConf,
3360  0,
3361  null,
3362  null,
3363  null
3364  ],
3365  'wrap conf only' => [
3366  $will,
3367  $wrapConf,
3368  1,
3369  '',
3370  $wrap,
3371  $will
3372  ],
3373  'full conf' => [
3374  $will,
3375  $conf,
3376  1,
3377  $value,
3378  $wrap,
3379  $will
3380  ],
3381  ];
3382  }
3383 
3399  public function calculateCacheKey($expect, $conf, $times, $with, $withWrap, $will)
3400  {
3401  $subject = $this->getAccessibleMock(ContentObjectRenderer::class, ['stdWrap']);
3402  $subject->expects($this->exactly($times))
3403  ->method('stdWrap')
3404  ->with($with, $withWrap)
3405  ->willReturn($will);
3406 
3407  $result = $subject->_call('calculateCacheKey', $conf);
3408  $this->assertSame($expect, $result);
3409  }
3410 
3416  public function getFromCacheDtataProvider()
3417  {
3418  $conf = [$this->getUniqueId('conf')];
3419  return [
3420  'empty cache key' => [
3421  false, $conf, '', 0, null,
3422  ],
3423  'non-empty cache key' => [
3424  'value', $conf, 'non-empty-key', 1, 'value',
3425  ],
3426  ];
3427  }
3428 
3446  public function getFromCache($expect, $conf, $cacheKey, $times, $cached)
3447  {
3448  $subject = $this->getAccessibleMock(
3449  ContentObjectRenderer::class, ['calculateCacheKey']);
3450  $subject
3451  ->expects($this->exactly(1))
3452  ->method('calculateCacheKey')
3453  ->with($conf)
3454  ->willReturn($cacheKey);
3455  $cacheFrontend = $this->createMock(CacheFrontendInterface::class);
3456  $cacheFrontend
3457  ->expects($this->exactly($times))
3458  ->method('get')
3459  ->with($cacheKey)
3460  ->willReturn($cached);
3461  $cacheManager = $this->createMock(CacheManager::class);
3462  $cacheManager
3463  ->method('getCache')
3464  ->willReturn($cacheFrontend);
3466  CacheManager::class, $cacheManager);
3467  $this->assertSame($expect, $subject->_call('getFromCache', $conf));
3468  }
3469 
3475  public function getFieldValDataProvider()
3476  {
3477  return [
3478  'invalid single key' => [null, 'invalid'],
3479  'single key of null' => [null, 'null'],
3480  'single key of empty string' => ['', 'empty'],
3481  'single key of non-empty string' => ['string 1', 'string1'],
3482  'single key of boolean false' => [false, 'false'],
3483  'single key of boolean true' => [true, 'true'],
3484  'single key of integer 0' => [0, 'zero'],
3485  'single key of integer 1' => [1, 'one'],
3486  'single key to be trimmed' => ['string 1', ' string1 '],
3487 
3488  'split nothing' => ['', '//'],
3489  'split one before' => ['string 1', 'string1//'],
3490  'split one after' => ['string 1', '//string1'],
3491  'split two ' => ['string 1', 'string1//string2'],
3492  'split three ' => ['string 1', 'string1//string2//string3'],
3493  'split to be trimmed' => ['string 1', ' string1 // string2 '],
3494  '0 is not empty' => [0, '// zero'],
3495  '1 is not empty' => [1, '// one'],
3496  'true is not empty' => [true, '// true'],
3497  'false is empty' => ['', '// false'],
3498  'null is empty' => ['', '// null'],
3499  'empty string is empty' => ['', '// empty'],
3500  'string is not empty' => ['string 1', '// string1'],
3501  'first non-empty winns' => [0, 'false//empty//null//zero//one'],
3502  'empty string is fallback' => ['', 'false // empty // null'],
3503  ];
3504  }
3505 
3545  public function getFieldVal($expect, $fields)
3546  {
3547  $data = [
3548  'string1' => 'string 1',
3549  'string2' => 'string 2',
3550  'string3' => 'string 3',
3551  'empty' => '',
3552  'null' => null,
3553  'false' => false,
3554  'true' => true,
3555  'zero' => 0,
3556  'one' => 1,
3557  ];
3558  $this->subject->_set('data', $data);
3559  $this->assertSame($expect, $this->subject->getFieldVal($fields));
3560  }
3561 
3567  public function caseshiftDataProvider()
3568  {
3569  return [
3570  'lower' => ['x y', 'X Y', 'lower'],
3571  'upper' => ['X Y', 'x y', 'upper'],
3572  'capitalize' => ['One Two', 'one two', 'capitalize'],
3573  'ucfirst' => ['One two', 'one two', 'ucfirst'],
3574  'lcfirst' => ['oNE TWO', 'ONE TWO', 'lcfirst'],
3575  'uppercamelcase' => ['CamelCase', 'camel_case', 'uppercamelcase'],
3576  'lowercamelcase' => ['camelCase', 'camel_case', 'lowercamelcase'],
3577  ];
3578  }
3579 
3589  public function caseshift($expect, $content, $case)
3590  {
3591  $this->assertSame($expect,
3592  $this->subject->caseshift($content, $case));
3593  }
3594 
3600  public function HTMLcaseshiftDataProvider()
3601  {
3602  $case = $this->getUniqueId('case');
3603  return [
3604  'simple text' => [
3605  'TEXT', 'text', $case,
3606  [['text', $case]],
3607  ['TEXT']
3608  ],
3609  'simple tag' => [
3610  '<i>TEXT</i>', '<i>text</i>', $case,
3611  [['', $case], ['text', $case]],
3612  ['', 'TEXT']
3613  ],
3614  'multiple nested tags with classes' => [
3615  NL . '<div class="typo3">' .
3616  NL . '<p>A <b>BOLD<\b> WORD.</p>' .
3617  NL . '<p>AN <i>ITALIC<\i> WORD.</p>' .
3618  NL . '</div>',
3619  NL . '<div class="typo3">' .
3620  NL . '<p>A <b>bold<\b> word.</p>' .
3621  NL . '<p>An <i>italic<\i> word.</p>' .
3622  NL . '</div>',
3623  $case,
3624  [
3625  [NL, $case],
3626  [NL, $case],
3627  ['A ', $case],
3628  ['bold', $case],
3629  [' word.', $case],
3630  [NL, $case],
3631  ['An ', $case],
3632  ['italic', $case],
3633  [' word.', $case],
3634  [NL, $case],
3635  ],
3636  [NL, NL, 'A ', 'BOLD', ' WORD.',
3637  NL, 'AN ', 'ITALIC', ' WORD.', NL]
3638  ],
3639  ];
3640  }
3641 
3659  public function HTMLcaseshift($expect, $content, $case, $with, $will)
3660  {
3661  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
3662  ->setMethods(['caseshift'])->getMock();
3663  $subject
3664  ->expects($this->exactly(count($with)))
3665  ->method('caseshift')
3666  ->withConsecutive(...$with)
3667  ->will($this->onConsecutiveCalls(...$will));
3668  $this->assertSame($expect,
3669  $subject->HTMLcaseshift($content, $case));
3670  }
3671 
3672  /***************************************************************************
3673  * General tests for stdWrap_
3674  ***************************************************************************/
3675 
3689  {
3690  $callable = 0;
3691  $notCallable = 0;
3692  $processors = ['invalidProcessor'];
3693  foreach (array_keys($this->subject->_get('stdWrapOrder')) as $key) {
3694  $processors[] = strtr($key, ['.' => '']);
3695  }
3696  foreach (array_unique($processors) as $processor) {
3697  $method = [$this->subject, 'stdWrap_' . $processor];
3698  if (is_callable($method)) {
3699  $callable += 1;
3700  } else {
3701  $notCallable += 1;
3702  }
3703  }
3704  $this->assertSame(1, $notCallable);
3705  $this->assertSame(91, $callable);
3706  }
3707 
3729  {
3730  $expectExceptions = ['numRows', 'split'];
3731  if (!version_compare(PHP_VERSION, '7.1', '<')) {
3732  // PHP >= 7.1 throws "A non-numeric value encountered" in GeneralUtility::formatSize()
3733  // @todo: If that is sanitized in a better way in formatSize(), this call needs adaption
3734  $expectExceptions[] = 'bytes';
3735  }
3736  $count = 0;
3737  $processors = [];
3738  $exceptions = [];
3739  foreach (array_keys($this->subject->_get('stdWrapOrder')) as $key) {
3740  $processors[] = strtr($key, ['.' => '']);
3741  }
3742  foreach (array_unique($processors) as $processor) {
3743  $count += 1;
3744  try {
3745  $conf = [$processor => '', $processor . '.' => ['table' => 'tt_content']];
3746  $method = 'stdWrap_' . $processor;
3747  $this->subject->$method('', $conf);
3748  } catch (\Exception $e) {
3749  $exceptions[] = $processor;
3750  }
3751  }
3752  $this->assertSame($expectExceptions, $exceptions);
3753  $this->assertSame(91, $count);
3754  }
3755 
3756  /***************************************************************************
3757  * End general tests for stdWrap_
3758  ***************************************************************************/
3759 
3760  /***************************************************************************
3761  * Tests for stdWrap_ in alphabetical order (all uppercase before lowercase)
3762  ***************************************************************************/
3763 
3770  {
3771  return [
3772  'preProcess' => [
3773  'stdWrap_stdWrapPreProcess', 'stdWrapPreProcess'
3774  ],
3775  'override' => [
3776  'stdWrap_stdWrapOverride', 'stdWrapOverride'
3777  ],
3778  'process' => [
3779  'stdWrap_stdWrapProcess', 'stdWrapProcess'
3780  ],
3781  'postProcess' => [
3782  'stdWrap_stdWrapPostProcess', 'stdWrapPostProcess'
3783  ],
3784  ];
3785  }
3786 
3804  $stdWrapMethod, $hookObjectCall)
3805  {
3806  $conf = [$this->getUniqueId('conf')];
3807  $content = $this->getUniqueId('content');
3808  $processed1 = $this->getUniqueId('processed1');
3809  $processed2 = $this->getUniqueId('processed2');
3810  $hookObject1 = $this->createMock(
3811  ContentObjectStdWrapHookInterface::class);
3812  $hookObject1->expects($this->once())
3813  ->method($hookObjectCall)
3814  ->with($content, $conf)
3815  ->willReturn($processed1);
3816  $hookObject2 = $this->createMock(
3817  ContentObjectStdWrapHookInterface::class);
3818  $hookObject2->expects($this->once())
3819  ->method($hookObjectCall)
3820  ->with($processed1, $conf)
3821  ->willReturn($processed2);
3822  $this->subject->_set('stdWrapHookObjects',
3823  [$hookObject1, $hookObject2]);
3824  $result = $this->subject->$stdWrapMethod($content, $conf);
3825  $this->assertSame($processed2, $result);
3826  }
3827 
3834  {
3835  $content = $this->getUniqueId('content');
3836  $parsed = $this->getUniqueId('parsed');
3837  return [
3838  'no config' => [
3839  $content, $content, [], 0, $parsed
3840  ],
3841  'no array' => [
3842  $content, $content, ['HTMLparser.' => 1], 0, $parsed
3843  ],
3844  'empty array' => [
3845  $parsed, $content, ['HTMLparser.' => []], 1, $parsed
3846  ],
3847  'non-empty array' => [
3848  $parsed, $content, ['HTMLparser.' => [true]], 1, $parsed
3849  ],
3850  ];
3851  }
3852 
3876  public function stdWrap_HTMLparser(
3877  $expect, $content, $conf, $times, $will)
3878  {
3879  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
3880  ->setMethods(['HTMLparser_TSbridge'])->getMock();
3881  $subject
3882  ->expects($this->exactly($times))
3883  ->method('HTMLparser_TSbridge')
3884  ->with($content, $conf['HTMLparser.'])
3885  ->willReturn($will);
3886  $this->assertSame($expect,
3887  $subject->stdWrap_HTMLparser($content, $conf));
3888  }
3889 
3896  {
3897  $content = $this->getUniqueId('content');
3898  $array = [$this->getUniqueId('TCAselectItem.')];
3899  $will = $this->getUniqueId('will');
3900  return [
3901  'empty conf' => [
3902  $content, $content, [], 0, $will
3903  ],
3904  'no array' => [
3905  $content, $content, ['TCAselectItem.' => true], 0, $will
3906  ],
3907  'empty array' => [
3908  $will, $content, ['TCAselectItem.' => []], 1, $will
3909  ],
3910  'array' => [
3911  $will, $content, ['TCAselectItem.' => $array], 1, $will
3912  ]
3913  ];
3914  }
3915 
3939  public function stdWrap_TCAselectItem(
3940  $expect, $content, $conf, $times, $will)
3941  {
3942  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
3943  ->setMethods(['TCAlookup'])->getMock();
3944  $subject
3945  ->expects($this->exactly($times))
3946  ->method('TCAlookup')
3947  ->with($content, $conf['TCAselectItem.'])
3948  ->willReturn($will);
3949  $this->assertSame($expect,
3950  $subject->stdWrap_TCAselectItem($content, $conf));
3951  }
3952 
3957  {
3958  return [
3959  'No Tag' => [
3960  [],
3961  ['addPageCacheTags' => ''],
3962  ],
3963  'Two expectedTags' => [
3964  ['tag1', 'tag2'],
3965  ['addPageCacheTags' => 'tag1,tag2'],
3966  ],
3967  'Two expectedTags plus one with stdWrap' => [
3968  ['tag1', 'tag2', 'tag3'],
3969  [
3970  'addPageCacheTags' => 'tag1,tag2',
3971  'addPageCacheTags.' => ['wrap' => '|,tag3']
3972  ],
3973  ],
3974  ];
3975  }
3976 
3983  public function stdWrap_addPageCacheTagsAddsPageTags(array $expectedTags, array $configuration)
3984  {
3985  $this->subject->stdWrap_addPageCacheTags('', $configuration);
3986  $this->assertEquals($expectedTags, $this->frontendControllerMock->_get('pageCacheTags'));
3987  }
3988 
4002  public function stdWrap_addParams()
4003  {
4004  $content = $this->getUniqueId('content');
4005  $conf = [
4006  'addParams' => $this->getUniqueId('not used'),
4007  'addParams.' => [$this->getUniqueId('addParams.')],
4008  ];
4009  $return = $this->getUniqueId('return');
4010  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4011  ->setMethods(['addParams'])->getMock();
4012  $subject
4013  ->expects($this->once())
4014  ->method('addParams')
4015  ->with($content, $conf['addParams.'])
4016  ->willReturn($return);
4017  $this->assertSame($return,
4018  $subject->stdWrap_addParams($content, $conf));
4019  }
4020 
4034  public function stdWrap_age()
4035  {
4036  $now = 10;
4037  $content = '9';
4038  $conf = ['age' => $this->getUniqueId('age')];
4039  $return = $this->getUniqueId('return');
4040  $difference = $now - (int)$content;
4041  $GLOBALS['EXEC_TIME'] = $now;
4042  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4043  ->setMethods(['calcAge'])->getMock();
4044  $subject
4045  ->expects($this->once())
4046  ->method('calcAge')
4047  ->with($difference, $conf['age'])
4048  ->willReturn($return);
4049  $this->assertSame($return, $subject->stdWrap_age($content, $conf));
4050  }
4051 
4066  public function stdWrap_append()
4067  {
4068  $debugKey = '/stdWrap/.append';
4069  $content = $this->getUniqueId('content');
4070  $conf = [
4071  'append' => $this->getUniqueId('append'),
4072  'append.' => [$this->getUniqueId('append.')],
4073  ];
4074  $return = $this->getUniqueId('return');
4075  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4076  ->setMethods(['cObjGetSingle'])->getMock();
4077  $subject
4078  ->expects($this->once())
4079  ->method('cObjGetSingle')
4080  ->with($conf['append'], $conf['append.'], $debugKey)
4081  ->willReturn($return);
4082  $this->assertSame($content . $return,
4083  $subject->stdWrap_append($content, $conf));
4084  }
4085 
4091  public function stdWrapBrDataProvider()
4092  {
4093  return [
4094  'no xhtml with LF in between' => [
4095  'one<br>' . LF . 'two',
4096  'one' . LF . 'two',
4097  null
4098  ],
4099  'no xhtml with LF in between and around' => [
4100  '<br>' . LF . 'one<br>' . LF . 'two<br>' . LF,
4101  LF . 'one' . LF . 'two' . LF,
4102  null
4103  ],
4104  'xhtml with LF in between' => [
4105  'one<br />' . LF . 'two',
4106  'one' . LF . 'two',
4107  'xhtml_strict'
4108  ],
4109  'xhtml with LF in between and around' => [
4110  '<br />' . LF . 'one<br />' . LF . 'two<br />' . LF,
4111  LF . 'one' . LF . 'two' . LF,
4112  'xhtml_strict'
4113  ],
4114  ];
4115  }
4116 
4127  public function stdWrap_br($expected, $input, $xhtmlDoctype)
4128  {
4129  $GLOBALS['TSFE']->xhtmlDoctype = $xhtmlDoctype;
4130  $this->assertSame($expected, $this->subject->stdWrap_br($input));
4131  }
4132 
4138  public function stdWrapBrTagDataProvider()
4139  {
4140  $noConfig = [];
4141  $config1 = ['brTag' => '<br/>'];
4142  $config2 = ['brTag' => '<br>'];
4143  return [
4144  'no config: one break at the beginning' => [LF . 'one' . LF . 'two', 'onetwo', $noConfig],
4145  'no config: multiple breaks at the beginning' => [LF . LF . 'one' . LF . 'two', 'onetwo', $noConfig],
4146  'no config: one break at the end' => ['one' . LF . 'two' . LF, 'onetwo', $noConfig],
4147  'no config: multiple breaks at the end' => ['one' . LF . 'two' . LF . LF, 'onetwo', $noConfig],
4148 
4149  'config1: one break at the beginning' => [LF . 'one' . LF . 'two', '<br/>one<br/>two', $config1],
4150  'config1: multiple breaks at the beginning' => [LF . LF . 'one' . LF . 'two', '<br/><br/>one<br/>two', $config1],
4151  'config1: one break at the end' => ['one' . LF . 'two' . LF, 'one<br/>two<br/>', $config1],
4152  'config1: multiple breaks at the end' => ['one' . LF . 'two' . LF . LF, 'one<br/>two<br/><br/>', $config1],
4153 
4154  'config2: one break at the beginning' => [LF . 'one' . LF . 'two', '<br>one<br>two', $config2],
4155  'config2: multiple breaks at the beginning' => [LF . LF . 'one' . LF . 'two', '<br><br>one<br>two', $config2],
4156  'config2: one break at the end' => ['one' . LF . 'two' . LF, 'one<br>two<br>', $config2],
4157  'config2: multiple breaks at the end' => ['one' . LF . 'two' . LF . LF, 'one<br>two<br><br>', $config2],
4158  ];
4159  }
4160 
4167  public function stdWrap_brTag($input, $expected, $config)
4168  {
4169  $this->assertEquals($expected, $this->subject->stdWrap_brTag($input, $config));
4170  }
4171 
4177  public function stdWrap_bytesDataProvider()
4178  {
4179  return [
4180  'value 1234 default' => [
4181  '1.21 Ki', '1234',
4182  ['labels' => '', 'base' => 0],
4183  ],
4184  'value 1234 si' => [
4185  '1.23 k', '1234',
4186  ['labels' => 'si', 'base' => 0],
4187  ],
4188  'value 1234 iec' => [
4189  '1.21 Ki', '1234',
4190  ['labels' => 'iec', 'base' => 0],
4191  ],
4192  'value 1234 a-i' => [
4193  '1.23b', '1234',
4194  ['labels' => 'a|b|c|d|e|f|g|h|i', 'base' => 1000],
4195  ],
4196  'value 1234 a-i invalid base' => [
4197  '1.21b', '1234',
4198  ['labels' => 'a|b|c|d|e|f|g|h|i', 'base' => 54],
4199  ],
4200  'value 1234567890 default' => [
4201  '1.15 Gi', '1234567890',
4202  ['labels' => '', 'base' => 0],
4203  ]
4204  ];
4205  }
4206 
4229  public function stdWrap_bytes($expect, $content, $conf)
4230  {
4231  $locale = 'en_US.UTF-8';
4232  try {
4233  $this->setLocale(LC_NUMERIC, $locale);
4234  } catch (\PHPUnit_Framework_Exception $e) {
4235  $this->markTestSkipped('Locale ' . $locale . ' is not available.');
4236  }
4237  $conf = ['bytes.' => $conf];
4238  $this->assertSame($expect,
4239  $this->subject->stdWrap_bytes($content, $conf));
4240  }
4241 
4256  public function stdWrap_cObject()
4257  {
4258  $debugKey = '/stdWrap/.cObject';
4259  $content = $this->getUniqueId('content');
4260  $conf = [
4261  'cObject' => $this->getUniqueId('cObject'),
4262  'cObject.' => [$this->getUniqueId('cObject.')],
4263  ];
4264  $return = $this->getUniqueId('return');
4265  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4266  ->setMethods(['cObjGetSingle'])->getMock();
4267  $subject
4268  ->expects($this->once())
4269  ->method('cObjGetSingle')
4270  ->with($conf['cObject'], $conf['cObject.'], $debugKey)
4271  ->willReturn($return);
4272  $this->assertSame($return,
4273  $subject->stdWrap_cObject($content, $conf));
4274  }
4275 
4282  {
4283  $confA = [$this->getUniqueId('conf A')];
4284  $confB = [$this->getUniqueId('conf B')];
4285  return [
4286  'standard case: order 1, 2' => [
4287  $confA, $confB, ['1.' => $confA, '2.' => $confB]
4288  ],
4289  'inverted: order 2, 1' => [
4290  $confB, $confA, ['2.' => $confA, '1.' => $confB]
4291  ],
4292  '0 as integer: order 0, 2' => [
4293  $confA, $confB, ['0.' => $confA, '2.' => $confB]
4294  ],
4295  'negative integers: order 2, -2' => [
4296  $confB, $confA, ['2.' => $confA, '-2.' => $confB]
4297  ],
4298  'chars are casted to key 0, that is not in the array' => [
4299  null, $confB, ['2.' => $confB, 'xxx.' => $confA]
4300  ],
4301  ];
4302  }
4303 
4327  public function stdWrap_orderedStdWrap($firstConf, $secondConf, $conf)
4328  {
4329  $content = $this->getUniqueId('content');
4330  $between = $this->getUniqueId('between');
4331  $expect = $this->getUniqueId('expect');
4332  $conf['orderedStdWrap.'] = $conf;
4333  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4334  ->setMethods(['stdWrap'])->getMock();
4335  $subject
4336  ->expects($this->exactly(2))
4337  ->method('stdWrap')
4338  ->withConsecutive([$content, $firstConf], [$between, $secondConf])
4339  ->will($this->onConsecutiveCalls($between, $expect));
4340  $this->assertSame($expect,
4341  $subject->stdWrap_orderedStdWrap($content, $conf));
4342  }
4343 
4350  {
4351  $cacheConf = [$this->getUniqueId('cache.')];
4352  $conf = ['cache.' => $cacheConf];
4353  return [
4354  'no conf' => [
4355  'content', 'content', [],
4356  0, null, null,
4357  ],
4358  'no cache. conf' => [
4359  'content', 'content', ['otherConf' => 1],
4360  0, null, null,
4361  ],
4362  'non-cached simulation' => [
4363  'content', 'content', $conf,
4364  1, $cacheConf, false,
4365  ],
4366  'cached simulation' => [
4367  'cachedContent', 'content', $conf,
4368  1, $cacheConf, 'cachedContent',
4369  ],
4370  ];
4371  }
4372 
4390  public function stdWrap_cacheRead(
4391  $expect, $input, $conf, $times, $with, $will)
4392  {
4393  $subject = $this->getAccessibleMock(
4394  ContentObjectRenderer::class, ['getFromCache']);
4395  $subject
4396  ->expects($this->exactly($times))
4397  ->method('getFromCache')
4398  ->with($with)
4399  ->willReturn($will);
4400  $this->assertSame($expect,
4401  $subject->stdWrap_cacheRead($input, $conf));
4402  }
4403 
4410  {
4411  $confCache = [$this->getUniqueId('cache.')];
4412  $key = [$this->getUniqueId('key')];
4413  return [
4414  'Return immediate with no conf' => [
4415  null, 0, null, 0,
4416  ],
4417  'Return immediate with empty key' => [
4418  $confCache, 1, '0', 0,
4419  ],
4420  'Call all methods' => [
4421  $confCache, 1, $key, 1,
4422  ],
4423  ];
4424  }
4425 
4448  public function stdWrap_cacheStore(
4449  $confCache, $timesCCK, $key, $times)
4450  {
4451  $content = $this->getUniqueId('content');
4452  $conf['cache.'] = $confCache;
4453  $tags = [$this->getUniqueId('tags')];
4454  $lifetime = $this->getUniqueId('lifetime');
4455  $params = ['key' => $key, 'content' => $content,
4456  'lifetime' => $lifetime, 'tags' => $tags];
4457  $subject = $this->getAccessibleMock(
4458  ContentObjectRenderer::class, ['calculateCacheKey',
4459  'calculateCacheTags', 'calculateCacheLifetime']);
4460  $subject
4461  ->expects($this->exactly($timesCCK))
4462  ->method('calculateCacheKey')
4463  ->with($confCache)
4464  ->willReturn($key);
4465  $subject
4466  ->expects($this->exactly($times))
4467  ->method('calculateCacheTags')
4468  ->with($confCache)
4469  ->willReturn($tags);
4470  $subject
4471  ->expects($this->exactly($times))
4472  ->method('calculateCacheLifetime')
4473  ->with($confCache)
4474  ->willReturn($lifetime);
4475  $cacheFrontend = $this->createMock(CacheFrontendInterface::class);
4476  $cacheFrontend
4477  ->expects($this->exactly($times))
4478  ->method('set')
4479  ->with($key, $content, $tags, $lifetime)
4480  ->willReturn($cached);
4481  $cacheManager = $this->createMock(CacheManager::class);
4482  $cacheManager
4483  ->method('getCache')
4484  ->willReturn($cacheFrontend);
4486  CacheManager::class, $cacheManager);
4487  list($countCalls, $test) = [0, $this];
4488  $closure = function ($par1, $par2) use (
4489  $test, $subject, $params, &$countCalls) {
4490  $test->assertSame($params, $par1);
4491  $test->assertSame($subject, $par2);
4492  $countCalls++;
4493  };
4494  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['stdWrap_cacheStore'] = [$closure, $closure, $closure];
4495  $this->assertSame($content,
4496  $subject->stdWrap_cacheStore($content, $conf));
4497  $this->assertSame($times * 3, $countCalls);
4498  }
4499 
4513  public function stdWrap_case()
4514  {
4515  $content = $this->getUniqueId();
4516  $conf = [
4517  'case' => $this->getUniqueId('used'),
4518  'case.' => [$this->getUniqueId('discarded')],
4519  ];
4520  $return = $this->getUniqueId();
4521  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4522  ->setMethods(['HTMLcaseshift'])->getMock();
4523  $subject
4524  ->expects($this->once())
4525  ->method('HTMLcaseshift')
4526  ->with($content, $conf['case'])
4527  ->willReturn($return);
4528  $this->assertSame($return,
4529  $subject->stdWrap_case($content, $conf));
4530  }
4531 
4538  public function stdWrap_char()
4539  {
4540  $input = 'discarded';
4541  $expected = 'C';
4542  $this->assertEquals($expected, $this->subject->stdWrap_char($input, ['char' => '67']));
4543  }
4544 
4558  public function stdWrap_crop()
4559  {
4560  $content = $this->getUniqueId('content');
4561  $conf = [
4562  'crop' => $this->getUniqueId('crop'),
4563  'crop.' => $this->getUniqueId('not used'),
4564  ];
4565  $return = $this->getUniqueId('return');
4566  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4567  ->setMethods(['crop'])->getMock();
4568  $subject
4569  ->expects($this->once())
4570  ->method('crop')
4571  ->with($content, $conf['crop'])
4572  ->willReturn($return);
4573  $this->assertSame($return,
4574  $subject->stdWrap_crop($content, $conf));
4575  }
4576 
4590  public function stdWrap_cropHTML()
4591  {
4592  $content = $this->getUniqueId('content');
4593  $conf = [
4594  'cropHTML' => $this->getUniqueId('cropHTML'),
4595  'cropHTML.' => $this->getUniqueId('not used'),
4596  ];
4597  $return = $this->getUniqueId('return');
4598  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4599  ->setMethods(['cropHTML'])->getMock();
4600  $subject
4601  ->expects($this->once())
4602  ->method('cropHTML')
4603  ->with($content, $conf['cropHTML'])
4604  ->willReturn($return);
4605  $this->assertSame($return,
4606  $subject->stdWrap_cropHTML($content, $conf));
4607  }
4608 
4614  public function stdWrap_csConvDataProvider()
4615  {
4616  return [
4617  'empty string from ISO-8859-15' => [
4618  '',
4619  mb_convert_encoding('', 'ISO-8859-15', 'UTF-8'),
4620  ['csConv' => 'ISO-8859-15']
4621  ],
4622  'empty string from BIG-5' => [
4623  '',
4624  mb_convert_encoding('', 'BIG-5'),
4625  ['csConv' => 'BIG-5']
4626  ],
4627  '"0" from ISO-8859-15' => [
4628  '0',
4629  mb_convert_encoding('0', 'ISO-8859-15', 'UTF-8'),
4630  ['csConv' => 'ISO-8859-15']
4631  ],
4632  '"0" from BIG-5' => [
4633  '0',
4634  mb_convert_encoding('0', 'BIG-5'),
4635  ['csConv' => 'BIG-5']
4636  ],
4637  'euro symbol from ISO-88859-15' => [
4638  '€',
4639  mb_convert_encoding('€', 'ISO-8859-15', 'UTF-8'),
4640  ['csConv' => 'ISO-8859-15']
4641  ],
4642  'good morning from BIG-5' => [
4643  '早安',
4644  mb_convert_encoding('早安', 'BIG-5'),
4645  ['csConv' => 'BIG-5']
4646  ],
4647  ];
4648  }
4649 
4660  public function stdWrap_csConv($expected, $input, $conf)
4661  {
4662  $this->assertSame($expected,
4663  $this->subject->stdWrap_csConv($input, $conf));
4664  }
4665 
4678  public function stdWrap_current()
4679  {
4680  $data = [
4681  'currentValue_kidjls9dksoje' => 'default',
4682  'currentValue_new' => 'new',
4683  ];
4684  $this->subject->_set('data', $data);
4685  $this->assertSame('currentValue_kidjls9dksoje',
4686  $this->subject->_get('currentValKey'));
4687  $this->assertSame('default',
4688  $this->subject->stdWrap_current('discarded', ['discarded']));
4689  $this->subject->_set('currentValKey', 'currentValue_new');
4690  $this->assertSame('new',
4691  $this->subject->stdWrap_current('discarded', ['discarded']));
4692  }
4693 
4699  public function stdWrap_dataDataProvider()
4700  {
4701  $data = [$this->getUniqueId('data')];
4702  $alt = [$this->getUniqueId('alternativeData')];
4703  return [
4704  'default' => [$data, $data, ''],
4705  'alt is array' => [$alt, $data, $alt],
4706  'alt is empty array' => [[], $data, []],
4707  'alt null' => [$data, $data, null],
4708  'alt string' => [$data, $data, 'xxx'],
4709  'alt int' => [$data, $data, 1],
4710  'alt bool' => [$data, $data, true],
4711  ];
4712  }
4713 
4733  public function stdWrap_data($expect, $data, $alt)
4734  {
4735  $conf = ['data' => $this->getUniqueId('conf.data')];
4736  $return = $this->getUniqueId('return');
4737  $subject = $this->getAccessibleMock(
4738  ContentObjectRenderer::class, ['getData']);
4739  $subject->_set('data', $data);
4740  $subject->_set('alternativeData', $alt);
4741  $subject
4742  ->expects($this->once())
4743  ->method('getData')
4744  ->with($conf['data'], $expect)
4745  ->willReturn($return);
4746  $this->assertSame($return, $subject->stdWrap_data('discard', $conf));
4747  $this->assertSame('', $subject->_get('alternativeData'));
4748  }
4749 
4763  public function stdWrap_dataWrap()
4764  {
4765  $content = $this->getUniqueId('content');
4766  $conf = [
4767  'dataWrap' => $this->getUniqueId('dataWrap'),
4768  'dataWrap.' => [$this->getUniqueId('not used')],
4769  ];
4770  $return = $this->getUniqueId('return');
4771  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
4772  ->setMethods(['dataWrap'])->getMock();
4773  $subject
4774  ->expects($this->once())
4775  ->method('dataWrap')
4776  ->with($content, $conf['dataWrap'])
4777  ->willReturn($return);
4778  $this->assertSame($return,
4779  $subject->stdWrap_dataWrap($content, $conf));
4780  }
4781 
4787  public function stdWrap_dateDataProvider()
4788  {
4789  // Fictive execution time: 2015-10-02 12:00
4790  $now = 1443780000;
4791  return [
4792  'given timestamp' => [
4793  '02.10.2015',
4794  $now,
4795  ['date' => 'd.m.Y'],
4796  $now
4797  ],
4798  'empty string' => [
4799  '02.10.2015',
4800  '',
4801  ['date' => 'd.m.Y'],
4802  $now
4803  ],
4804  'testing null' => [
4805  '02.10.2015',
4806  null,
4807  ['date' => 'd.m.Y'],
4808  $now
4809  ],
4810  'given timestamp return GMT' => [
4811  '02.10.2015 10:00:00',
4812  $now,
4813  [
4814  'date' => 'd.m.Y H:i:s',
4815  'date.' => ['GMT' => true],
4816  ],
4817  $now
4818  ]
4819  ];
4820  }
4821 
4833  public function stdWrap_date($expected, $content, $conf, $now)
4834  {
4835  $GLOBALS['EXEC_TIME'] = $now;
4836  $this->assertEquals($expected,
4837  $this->subject->stdWrap_date($content, $conf));
4838  }
4839 
4846  public function stdWrap_debug()
4847  {
4848  $expect = '<pre>&lt;p class=&quot;class&quot;&gt;&lt;br/&gt;'
4849  . '&lt;/p&gt;</pre>';
4850  $content = '<p class="class"><br/></p>';
4851  $this->assertSame($expect, $this->subject->stdWrap_debug($content));
4852  }
4853 
4881  public function stdWrap_debugData()
4882  {
4883  $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'] = '*';
4884  $content = $this->getUniqueId('content');
4885  $key = $this->getUniqueId('key');
4886  $value = $this->getUniqueId('value');
4887  $altValue = $this->getUniqueId('value alt');
4888  $this->subject->data = [$key => $value];
4889  // Without alternative data only data is returned.
4890  ob_start();
4891  $result = $this->subject->stdWrap_debugData($content);
4892  $out = ob_get_clean();
4893  $this->assertSame($result, $content);
4894  $this->assertNotContains('$cObj->data', $out);
4895  $this->assertContains($value, $out);
4896  $this->assertNotContains($altValue, $out);
4897  // By adding alternative data both are returned together.
4898  $this->subject->alternativeData = [$key => $altValue];
4899  ob_start();
4900  $this->subject->stdWrap_debugData($content);
4901  $out = ob_get_clean();
4902  $this->assertNotContains('$cObj->alternativeData', $out);
4903  $this->assertContains($value, $out);
4904  $this->assertContains($altValue, $out);
4905  }
4906 
4907  /*
4908  * Data provider for stdWrap_debugFunc.
4909  *
4910  * @return array [$expectArray, $confDebugFunc]
4911  */
4913  {
4914  return [
4915  'expect array by string' => [ true, '2' ],
4916  'expect array by integer' => [ true, 2 ],
4917  'do not expect array' => [ false, '' ],
4918  ];
4919  }
4920 
4943  public function stdWrap_debugFunc($expectArray, $confDebugFunc)
4944  {
4945  $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'] = '*';
4946  $content = $this->getUniqueId('content');
4947  $conf = ['debugFunc' => $confDebugFunc];
4948  ob_start();
4949  $result = $this->subject->stdWrap_debugFunc($content, $conf);
4950  $out = ob_get_clean();
4951  $this->assertSame($result, $content);
4952  $this->assertContains($content, $out);
4953  if ($expectArray) {
4954  $this->assertContains('=>', $out);
4955  } else {
4956  $this->assertNotContains('=>', $out);
4957  }
4958  }
4959 
4966  {
4967  return [
4968  'no config: void input' => [
4969  '',
4970  '',
4971  [],
4972  ],
4973  'no config: single break' => [
4974  'one' . LF . 'two',
4975  'one' . LF . 'two',
4976  [],
4977  ],
4978  'no config: double break' => [
4979  'onetwo',
4980  'one' . LF . LF . 'two',
4981  [],
4982  ],
4983  'no config: double break with whitespace' => [
4984  'onetwo',
4985  'one' . LF . TAB . ' ' . TAB . ' ' . LF . 'two',
4986  [],
4987  ],
4988  'no config: single break around' => [
4989  LF . 'one' . LF,
4990  LF . 'one' . LF,
4991  [],
4992  ],
4993  'no config: double break around' => [
4994  'one',
4995  LF . LF . 'one' . LF . LF,
4996  [],
4997  ],
4998  'empty string: double break around' => [
4999  'one',
5000  LF . LF . 'one' . LF . LF,
5001  ['doubleBrTag' => ''],
5002  ],
5003  'br tag: double break' => [
5004  'one<br/>two',
5005  'one' . LF . LF . 'two',
5006  ['doubleBrTag' => '<br/>'],
5007  ],
5008  'br tag: double break around' => [
5009  '<br/>one<br/>',
5010  LF . LF . 'one' . LF . LF,
5011  ['doubleBrTag' => '<br/>'],
5012  ],
5013  'double br tag: double break around' => [
5014  '<br/><br/>one<br/><br/>',
5015  LF . LF . 'one' . LF . LF,
5016  ['doubleBrTag' => '<br/><br/>'],
5017  ],
5018  ];
5019  }
5020 
5031  public function stdWrap_doubleBrTag($expected, $input, $config)
5032  {
5033  $this->assertEquals($expected, $this->subject->stdWrap_doubleBrTag($input, $config));
5034  }
5035 
5042  {
5043  $content = $this->getUniqueId('content');
5044  $editIcons = $this->getUniqueId('editIcons');
5045  $editIconsArray = [$this->getUniqueId('editIcons.')];
5046  $will = $this->getUniqueId('will');
5047  return [
5048  'standard case calls edit icons' => [
5049  $will, $content,
5050  ['editIcons' => $editIcons, 'editIcons.' => $editIconsArray],
5051  true, 1, $editIconsArray, $will
5052  ],
5053  'null in editIcons. repalaced by []' => [
5054  $will, $content,
5055  ['editIcons' => $editIcons, 'editIcons.' => null],
5056  true, 1, [], $will
5057  ],
5058  'missing editIcons. replaced by []' => [
5059  $will, $content,
5060  ['editIcons' => $editIcons],
5061  true, 1, [], $will
5062  ],
5063  'no user login disables call' => [
5064  $content, $content,
5065  ['editIcons' => $editIcons, 'editIcons.' => $editIconsArray],
5066  false, 0, $editIconsArray, $will
5067  ],
5068  'empty string in editIcons disables call' => [
5069  $content, $content,
5070  ['editIcons' => '', 'editIcons.' => $editIconsArray],
5071  true, 0, $editIconsArray, $will
5072  ],
5073  'zero string in editIcons disables call' => [
5074  $content, $content,
5075  ['editIcons' => '0', 'editIcons.' => $editIconsArray],
5076  true, 0, $editIconsArray, $will
5077  ],
5078  ];
5079  }
5080 
5108  public function stdWrap_editIcons(
5109  $expect, $content, $conf, $login, $times, $param3, $will)
5110  {
5111  $GLOBALS['TSFE']->beUserLogin = $login;
5112  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5113  ->setMethods(['editIcons'])->getMock();
5114  $subject
5115  ->expects($this->exactly($times))
5116  ->method('editIcons')
5117  ->with($content, $conf['editIcons'], $param3)
5118  ->willReturn($will);
5119  $this->assertSame($expect,
5120  $subject->stdWrap_editIcons($content, $conf));
5121  }
5122 
5136  public function stdWrap_encapsLines()
5137  {
5138  $content = $this->getUniqueId('content');
5139  $conf = [
5140  'encapsLines' => [$this->getUniqueId('not used')],
5141  'encapsLines.' => [$this->getUniqueId('encapsLines.')],
5142  ];
5143  $return = $this->getUniqueId('return');
5144  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5145  ->setMethods(['encaps_lineSplit'])->getMock();
5146  $subject
5147  ->expects($this->once())
5148  ->method('encaps_lineSplit')
5149  ->with($content, $conf['encapsLines.'])
5150  ->willReturn($return);
5151  $this->assertSame($return,
5152  $subject->stdWrap_encapsLines($content, $conf));
5153  }
5154 
5161  {
5162  $content = $this->getUniqueId('content');
5163  $will = $this->getUniqueId('will');
5164  return [
5165  'standard case calls edit icons' => [
5166  $will, $content, true, 1, $will
5167  ],
5168  'no user login disables call' => [
5169  $content, $content, false, 0, $will
5170  ],
5171  ];
5172  }
5173 
5196  public function stdWrap_editPanel(
5197  $expect, $content, $login, $times, $will)
5198  {
5199  $GLOBALS['TSFE']->beUserLogin = $login;
5200  $conf = ['editPanel.' => [$this->getUniqueId('editPanel.')]];
5201  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5202  ->setMethods(['editPanel'])->getMock();
5203  $subject
5204  ->expects($this->exactly($times))
5205  ->method('editPanel')
5206  ->with($content, $conf['editPanel.'])
5207  ->willReturn($will);
5208  $this->assertSame($expect,
5209  $subject->stdWrap_editPanel($content, $conf));
5210  }
5211 
5218  {
5219  return [
5220  'double quote in string' => [
5221  '\'double\u0020quote\u0022\'', 'double quote"'
5222  ],
5223  'backslash in string' => [
5224  '\'backslash\u0020\u005C\'', 'backslash \\'
5225  ],
5226  'exclamation mark' => [
5227  '\'exclamation\u0021\'', 'exclamation!'
5228  ],
5229  'whitespace tab, newline and carriage return' => [
5230  '\'white\u0009space\u000As\u000D\'', "white\tspace\ns\r"
5231  ],
5232  'single quote in string' => [
5233  '\'single\u0020quote\u0020\u0027\'', 'single quote \''
5234  ],
5235  'tag' => [
5236  '\'\u003Ctag\u003E\'', '<tag>'
5237  ],
5238  'ampersand in string' => [
5239  '\'amper\u0026sand\'', 'amper&sand'
5240  ]
5241  ];
5242  }
5243 
5253  public function stdWrap_encodeForJavaScriptValue($expect, $content)
5254  {
5255  $this->assertSame($expect,
5256  $this->subject->stdWrap_encodeForJavaScriptValue($content));
5257  }
5258 
5265  {
5266  return [
5267  'numbers' => ['1,2,3', '1,2,3'],
5268  'range' => ['3,4,5', '3-5'],
5269  'numbers and range' => ['1,3,4,5,7', '1,3-5,7']
5270  ];
5271  }
5272 
5287  public function stdWrap_expandList($expected, $content)
5288  {
5289  $this->assertEquals($expected,
5290  $this->subject->stdWrap_expandList($content));
5291  }
5292 
5304  public function stdWrap_field()
5305  {
5306  $expect = $this->getUniqueId('expect');
5307  $conf = ['field' => $this->getUniqueId('field')];
5308  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5309  ->setMethods(['getFieldVal'])->getMock();
5310  $subject
5311  ->expects($this->once())
5312  ->method('getFieldVal')
5313  ->with($conf['field'])
5314  ->willReturn($expect);
5315  $this->assertSame($expect,
5316  $subject->stdWrap_field('discarded', $conf));
5317  }
5318 
5325  {
5326  $content = $this->getUniqueId('content');
5327  return [
5328  // resulting in boolean false
5329  'false is false' => [
5330  '', true, $content, ['fieldRequired' => 'false']
5331  ],
5332  'null is false' => [
5333  '', true, $content, ['fieldRequired' => 'null']
5334  ],
5335  'empty string is false' => [
5336  '', true, $content, ['fieldRequired' => 'empty']
5337  ],
5338  'whitespace is false' => [
5339  '', true, $content, ['fieldRequired' => 'whitespace']
5340  ],
5341  'string zero is false' => [
5342  '', true, $content, ['fieldRequired' => 'stringZero']
5343  ],
5344  'string zero with whitespace is false' => [
5345  '', true, $content,
5346  ['fieldRequired' => 'stringZeroWithWhiteSpace']
5347  ],
5348  'zero is false' => [
5349  '', true, $content, ['fieldRequired' => 'zero']
5350  ],
5351  // resulting in boolean true
5352  'true is true' => [
5353  $content, false, $content, ['fieldRequired' => 'true']
5354  ],
5355  'string is true' => [
5356  $content, false, $content, ['fieldRequired' => 'string']
5357  ],
5358  'one is true' => [
5359  $content, false, $content, ['fieldRequired' => 'one']
5360  ]
5361  ];
5362  }
5363 
5384  public function stdWrap_fieldRequired($expect, $stop, $content, $conf)
5385  {
5386  $data = [
5387  'null' => null,
5388  'false' => false,
5389  'empty' => '',
5390  'whitespace' => TAB . ' ',
5391  'stringZero' => '0',
5392  'stringZeroWithWhiteSpace' => TAB . ' 0 ' . TAB,
5393  'zero' => 0,
5394  'string' => 'string',
5395  'true' => true,
5396  'one' => 1
5397  ];
5399  $subject->_set('data', $data);
5400  $subject->_set('stdWrapRecursionLevel', 1);
5401  $subject->_set('stopRendering', [1 => false]);
5402  $this->assertSame($expect,
5403  $subject->stdWrap_fieldRequired($content, $conf));
5404  $this->assertSame($stop, $subject->_get('stopRendering')[1]);
5405  }
5406 
5420  public function stdWrap_filelink()
5421  {
5422  $content = $this->getUniqueId('content');
5423  $conf = [
5424  'filelink' => $this->getUniqueId('not used'),
5425  'filelink.' => [$this->getUniqueId('filelink.')],
5426  ];
5427  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5428  ->setMethods(['filelink'])->getMock();
5429  $subject->expects($this->once())->method('filelink')
5430  ->with($content, $conf['filelink.'])->willReturn('return');
5431  $this->assertSame('return',
5432  $subject->stdWrap_filelink($content, $conf));
5433  }
5434 
5447  public function stdWrap_filelist()
5448  {
5449  $conf = [
5450  'filelist' => $this->getUniqueId('filelist'),
5451  'filelist.' => [$this->getUniqueId('not used')],
5452  ];
5453  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5454  ->setMethods(['filelist'])->getMock();
5455  $subject->expects($this->once())->method('filelist')
5456  ->with($conf['filelist'])->willReturn('return');
5457  $this->assertSame('return',
5458  $subject->stdWrap_filelist('discard', $conf));
5459  }
5460 
5466  public function hashDataProvider()
5467  {
5468  return [
5469  'md5' => [
5470  'bacb98acf97e0b6112b1d1b650b84971',
5471  'joh316',
5472  ['hash' => 'md5']
5473  ],
5474  'sha1' => [
5475  '063b3d108bed9f88fa618c6046de0dccadcf3158',
5476  'joh316',
5477  ['hash' => 'sha1']
5478  ],
5479  'stdWrap capability' => [
5480  'bacb98acf97e0b6112b1d1b650b84971',
5481  'joh316',
5482  [
5483  'hash' => '5',
5484  'hash.' => ['wrap' => 'md|']
5485  ]
5486  ],
5487  'non-existing hashing algorithm' => [
5488  '',
5489  'joh316',
5490  ['hash' => 'non-existing']
5491  ]
5492  ];
5493  }
5494 
5511  public function stdWrap_hash($expect, $content, $conf)
5512  {
5513  $this->assertSame($expect,
5514  $this->subject->stdWrap_hash($content, $conf));
5515  }
5516 
5523  {
5524  return [
5525  'void conf' => [
5526  '&lt;span&gt;1 &amp;lt; 2&lt;/span&gt;',
5527  '<span>1 &lt; 2</span>',
5528  [],
5529  ],
5530  'void preserveEntities' => [
5531  '&lt;span&gt;1 &amp;lt; 2&lt;/span&gt;',
5532  '<span>1 &lt; 2</span>',
5533  ['htmlSpecialChars.' => []],
5534  ],
5535  'false preserveEntities' => [
5536  '&lt;span&gt;1 &amp;lt; 2&lt;/span&gt;',
5537  '<span>1 &lt; 2</span>',
5538  ['htmlSpecialChars.' => ['preserveEntities' => 0]],
5539  ],
5540  'true preserveEntities' => [
5541  '&lt;span&gt;1 &lt; 2&lt;/span&gt;',
5542  '<span>1 &lt; 2</span>',
5543  ['htmlSpecialChars.' => ['preserveEntities' => 1]],
5544  ],
5545  ];
5546  }
5547 
5558  public function stdWrap_htmlSpecialChars($expected, $input, $conf)
5559  {
5560  $this->assertSame($expected,
5561  $this->subject->stdWrap_htmlSpecialChars($input, $conf));
5562  }
5563 
5569  public function stdWrap_ifDataProvider()
5570  {
5571  $content = $this->getUniqueId('content');
5572  $conf = ['if.' => [$this->getUniqueId('if.')]];
5573  return [
5574  // evals to true
5575  'empty config' => [
5576  $content, false, $content, [], 0, null
5577  ],
5578  'if. is empty array' => [
5579  $content, false, $content, ['if.' => []], 0, null
5580  ],
5581  'if. is null' => [
5582  $content, false, $content, ['if.' => null], 0, null
5583  ],
5584  'if. is false' => [
5585  $content, false, $content, ['if.' => false], 0, null
5586  ],
5587  'if. is 0' => [
5588  $content, false, $content, ['if.' => false], 0, null
5589  ],
5590  'if. is "0"' => [
5591  $content, false, $content, ['if.' => '0'], 0, null
5592  ],
5593  'checkIf returning true' => [
5594  $content, false, $content, $conf, 1, true
5595  ],
5596  // evals to false
5597  'checkIf returning false' => [
5598  '', true, $content, $conf, 1, false
5599  ],
5600  ];
5601  }
5602 
5624  public function stdWrap_if($expect, $stop, $content, $conf, $times, $will)
5625  {
5626  $subject = $this->getAccessibleMock(
5627  ContentObjectRenderer::class, ['checkIf']);
5628  $subject->_set('stdWrapRecursionLevel', 1);
5629  $subject->_set('stopRendering', [1 => false]);
5630  $subject
5631  ->expects($this->exactly($times))
5632  ->method('checkIf')
5633  ->with($conf['if.'])
5634  ->willReturn($will);
5635  $this->assertSame($expect, $subject->stdWrap_if($content, $conf));
5636  $this->assertSame($stop, $subject->_get('stopRendering')[1]);
5637  }
5638 
5645  {
5646  $alt = $this->getUniqueId('alternative content');
5647  $conf = ['ifBlank' => $alt];
5648  return [
5649  // blank cases
5650  'null is blank' => [$alt, null, $conf],
5651  'false is blank' => [$alt, false, $conf],
5652  'empty string is blank' => [$alt, '', $conf],
5653  'whitespace is blank' => [$alt, TAB . '', $conf],
5654  // non-blank cases
5655  'string is not blank' => ['string', 'string', $conf],
5656  'zero is not blank' => [0, 0, $conf],
5657  'zero string is not blank' => ['0', '0', $conf],
5658  'zero float is not blank' => [0.0, 0.0, $conf],
5659  'true is not blank' => [true, true, $conf],
5660  ];
5661  }
5662 
5680  public function stdWrap_ifBlank($expect, $content, $conf)
5681  {
5682  $result = $this->subject->stdWrap_ifBlank($content, $conf);
5683  $this->assertSame($expect, $result);
5684  }
5685 
5692  {
5693  $alt = $this->getUniqueId('alternative content');
5694  $conf = ['ifEmpty' => $alt];
5695  return [
5696  // empty cases
5697  'null is empty' => [$alt, null, $conf ],
5698  'false is empty' => [$alt, false, $conf ],
5699  'zero is empty' => [$alt, 0, $conf ],
5700  'float zero is empty' => [$alt, 0.0, $conf ],
5701  'whitespace is empty' => [$alt, TAB . ' ', $conf ],
5702  'empty string is empty' => [$alt, '', $conf ],
5703  'zero string is empty' => [$alt, '0', $conf ],
5704  'zero string is empty with whitespace' => [
5705  $alt, TAB . ' 0 ' . TAB, $conf
5706  ],
5707  // non-empty cases
5708  'string is not empty' => ['string', 'string', $conf ],
5709  '1 is not empty' => [1, 1, $conf ],
5710  '-1 is not empty' => [-1, -1, $conf ],
5711  '0.1 is not empty' => [0.1, 0.1, $conf ],
5712  '-0.1 is not empty' => [-0.1, -0.1, $conf ],
5713  'true is not empty' => [true, true, $conf ],
5714  ];
5715  }
5716 
5733  public function stdWrap_ifEmpty($expect, $content, $conf)
5734  {
5735  $result = $this->subject->stdWrap_ifEmpty($content, $conf);
5736  $this->assertSame($expect, $result);
5737  }
5738 
5744  public function stdWrap_ifNullDataProvider()
5745  {
5746  $alt = $this->getUniqueId('alternative content');
5747  $conf = ['ifNull' => $alt];
5748  return [
5749  'only null is null' => [$alt, null, $conf],
5750  'zero is not null' => [0, 0, $conf],
5751  'float zero is not null' => [0.0, 0.0, $conf],
5752  'false is not null' => [false, false, $conf],
5753  'zero is not null' => [0, 0, $conf],
5754  'zero string is not null' => ['0', '0', $conf],
5755  'empty string is not null' => ['', '', $conf],
5756  'whitespace is not null' => [TAB . '', TAB . '', $conf],
5757  ];
5758  }
5759 
5776  public function stdWrap_ifNull($expect, $content, $conf)
5777  {
5778  $result = $this->subject->stdWrap_ifNull($content, $conf);
5779  $this->assertSame($expect, $result);
5780  }
5781 
5788  {
5789  return [
5790  'no conf' => [
5791  'XXX',
5792  'XXX',
5793  [],
5794  ],
5795  'simple' => [
5796  '<wrap>XXX</wrap>',
5797  'XXX',
5798  ['innerWrap' => '<wrap>|</wrap>'],
5799  ],
5800  'missing pipe puts wrap before' => [
5801  '<pre>XXX',
5802  'XXX',
5803  ['innerWrap' => '<pre>'],
5804  ],
5805  'trims whitespace' => [
5806  '<wrap>XXX</wrap>',
5807  'XXX',
5808  ['innerWrap' => '<wrap>' . TAB . ' | ' . TAB . '</wrap>'],
5809  ],
5810  'split char change is not possible' => [
5811  '<wrap> # </wrap>XXX',
5812  'XXX',
5813  [
5814  'innerWrap' => '<wrap> # </wrap>',
5815  'innerWrap.' => ['splitChar' => '#'],
5816  ],
5817  ],
5818  ];
5819  }
5820 
5831  public function stdWrap_innerWrap($expected, $input, $conf)
5832  {
5833  $this->assertSame($expected,
5834  $this->subject->stdWrap_innerWrap($input, $conf));
5835  }
5836 
5843  {
5844  return [
5845  'no conf' => [
5846  'XXX',
5847  'XXX',
5848  [],
5849  ],
5850  'simple' => [
5851  '<wrap>XXX</wrap>',
5852  'XXX',
5853  ['innerWrap2' => '<wrap>|</wrap>'],
5854  ],
5855  'missing pipe puts wrap before' => [
5856  '<pre>XXX',
5857  'XXX',
5858  ['innerWrap2' => '<pre>'],
5859  ],
5860  'trims whitespace' => [
5861  '<wrap>XXX</wrap>',
5862  'XXX',
5863  ['innerWrap2' => '<wrap>' . TAB . ' | ' . TAB . '</wrap>'],
5864  ],
5865  'split char change is not possible' => [
5866  '<wrap> # </wrap>XXX',
5867  'XXX',
5868  [
5869  'innerWrap2' => '<wrap> # </wrap>',
5870  'innerWrap2.' => ['splitChar' => '#'],
5871  ],
5872  ],
5873  ];
5874  }
5875 
5886  public function stdWrap_innerWrap2($expected, $input, $conf)
5887  {
5888  $this->assertSame($expected,
5889  $this->subject->stdWrap_innerWrap2($input, $conf));
5890  }
5891 
5904  public function stdWrap_insertData()
5905  {
5906  $content = $this->getUniqueId('content');
5907  $conf = [$this->getUniqueId('conf not used')];
5908  $return = $this->getUniqueId('return');
5909  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
5910  ->setMethods(['insertData'])->getMock();
5911  $subject->expects($this->once())->method('insertData')
5912  ->with($content)->willReturn($return);
5913  $this->assertSame($return,
5914  $subject->stdWrap_insertData($content, $conf));
5915  }
5916 
5922  public function stdWrap_intvalDataProvider()
5923  {
5924  return [
5925  // numbers
5926  'int' => [123, 123],
5927  'float' => [123, 123.45],
5928  'float does not round up' => [123, 123.55],
5929  // negative numbers
5930  'negative int' => [-123, -123],
5931  'negative float' => [-123, -123.45],
5932  'negative float does not round down' => [-123, -123.55],
5933  // strings
5934  'word string' => [0, 'string'],
5935  'empty string' => [0, ''],
5936  'zero string' => [0, '0'],
5937  'int string' => [123, '123'],
5938  'float string' => [123, '123.55'],
5939  'negative float string' => [-123, '-123.55'],
5940  // other types
5941  'null' => [0, null],
5942  'true' => [1, true],
5943  'false' => [0, false]
5944  ];
5945  }
5946 
5967  public function stdWrap_intval($expect, $content)
5968  {
5969  $this->assertSame($expect, $this->subject->stdWrap_intval($content));
5970  }
5971 
5978  {
5979  return [
5980  'empty string' => ['', ''],
5981  'blank' => ['', ' '],
5982  'tab' => ['', "\t"],
5983  'single semicolon' => [',', ' ; '],
5984  'single comma' => [',', ' , '],
5985  'single nl' => [',', ' ' . PHP_EOL . ' '],
5986  'double semicolon' => [',,', ' ; ; '],
5987  'double comma' => [',,', ' , , '],
5988  'double nl' => [',,', ' ' . PHP_EOL . ' ' . PHP_EOL . ' '],
5989  'simple word' => ['one', ' one '],
5990  'simple word trimmed' => ['one', 'one'],
5991  ', separated' => ['one,two', ' one , two '],
5992  '; separated' => ['one,two', ' one ; two '],
5993  'nl separated' => ['one,two', ' one ' . PHP_EOL . ' two '],
5994  ', typical' => ['one,two,three', 'one, two, three'],
5995  '; typical' => ['one,two,three', ' one; two; three'],
5996  'nl typical' => [
5997  'one,two,three',
5998  'one' . PHP_EOL . 'two' . PHP_EOL . 'three'
5999  ],
6000  ', sourounded' => [',one,two,', ' , one , two , '],
6001  '; sourounded' => [',one,two,', ' ; one ; two ; '],
6002  'nl sourounded' => [
6003  ',one,two,',
6004  ' ' . PHP_EOL . ' one ' . PHP_EOL . ' two ' . PHP_EOL . ' '
6005  ],
6006  'mixed' => [
6007  'one,two,three,four',
6008  ' one, two; three' . PHP_EOL . 'four'
6009  ],
6010  'keywods with blanks in words' => [
6011  'one plus,two minus',
6012  ' one plus , two minus ',
6013  ]
6014  ];
6015  }
6016 
6026  public function stdWrap_keywords($expected, $input)
6027  {
6028  $this->assertSame($expected, $this->subject->stdWrap_keywords($input));
6029  }
6030 
6036  public function stdWrap_langDataProvider()
6037  {
6038  return [
6039  'empty conf' => [
6040  'original',
6041  'original',
6042  [],
6043  'de',
6044  ],
6045  'translation de' => [
6046  'Übersetzung',
6047  'original',
6048  [
6049  'lang.' => [
6050  'de' => 'Übersetzung',
6051  'it' => 'traduzione',
6052  ]
6053  ],
6054  'de',
6055  ],
6056  'translation it' => [
6057  'traduzione',
6058  'original',
6059  [
6060  'lang.' => [
6061  'de' => 'Übersetzung',
6062  'it' => 'traduzione',
6063  ]
6064  ],
6065  'it',
6066  ],
6067  'no translation' => [
6068  'original',
6069  'original',
6070  [
6071  'lang.' => [
6072  'de' => 'Übersetzung',
6073  'it' => 'traduzione',
6074  ]
6075  ],
6076  '',
6077  ],
6078  'missing label' => [
6079  'original',
6080  'original',
6081  [
6082  'lang.' => [
6083  'de' => 'Übersetzung',
6084  'it' => 'traduzione',
6085  ]
6086  ],
6087  'fr',
6088  ],
6089  ];
6090  }
6091 
6103  public function stdWrap_lang($expected, $input, $conf, $language)
6104  {
6105  if ($language) {
6106  $this->frontendControllerMock
6107  ->config['config']['language'] = $language;
6108  }
6109  $this->assertSame($expected,
6110  $this->subject->stdWrap_lang($input, $conf));
6111  }
6112 
6127  public function stdWrap_listNum()
6128  {
6129  $content = $this->getUniqueId('content');
6130  $conf = [
6131  'listNum' => $this->getUniqueId('listNum'),
6132  'listNum.' => [
6133  'splitChar' => $this->getUniqueId('splitChar')
6134  ],
6135  ];
6136  $return = $this->getUniqueId('return');
6137  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6138  ->setMethods(['listNum'])->getMock();
6139  $subject
6140  ->expects($this->once())
6141  ->method('listNum')
6142  ->with(
6143  $content,
6144  $conf['listNum'],
6145  $conf['listNum.']['splitChar']
6146  )
6147  ->willReturn($return);
6148  $this->assertSame($return,
6149  $subject->stdWrap_listNum($content, $conf));
6150  }
6151 
6158  {
6159  return [
6160  'Standard case' => [
6161  ' left middle right ',
6162  'middle',
6163  [
6164  'noTrimWrap' => '| left | right |',
6165  ],
6166  ],
6167  'Tabs as whitespace' => [
6168  TAB . 'left' . TAB . 'middle' . TAB . 'right' . TAB,
6169  'middle',
6170  [
6171  'noTrimWrap' =>
6172  '|' . TAB . 'left' . TAB . '|' . TAB . 'right' . TAB . '|',
6173  ],
6174  ],
6175  'Split char is 0' => [
6176  ' left middle right ',
6177  'middle',
6178  [
6179  'noTrimWrap' => '0 left 0 right 0',
6180  'noTrimWrap.' => ['splitChar' => '0'],
6181  ],
6182  ],
6183  'Split char is pipe (default)' => [
6184  ' left middle right ',
6185  'middle',
6186  [
6187  'noTrimWrap' => '| left | right |',
6188  'noTrimWrap.' => ['splitChar' => '|'],
6189  ],
6190  ],
6191  'Split char is a' => [
6192  ' left middle right ',
6193  'middle',
6194  [
6195  'noTrimWrap' => 'a left a right a',
6196  'noTrimWrap.' => ['splitChar' => 'a'],
6197  ],
6198  ],
6199  'Split char is a word (ab)' => [
6200  ' left middle right ',
6201  'middle',
6202  [
6203  'noTrimWrap' => 'ab left ab right ab',
6204  'noTrimWrap.' => ['splitChar' => 'ab'],
6205  ],
6206  ],
6207  'Split char accepts stdWrap' => [
6208  ' left middle right ',
6209  'middle',
6210  [
6211  'noTrimWrap' => 'abc left abc right abc',
6212  'noTrimWrap.' => [
6213  'splitChar' => 'b',
6214  'splitChar.' => ['wrap' => 'a|c'],
6215  ],
6216  ],
6217  ],
6218  ];
6219  }
6220 
6231  public function stdWrap_noTrimWrap($expect, $content, $conf)
6232  {
6233  $this->assertSame($expect,
6234  $this->subject->stdWrap_noTrimWrap($content, $conf));
6235  }
6236 
6249  public function stdWrap_numRows()
6250  {
6251  $conf = [
6252  'numRows' => $this->getUniqueId('numRows'),
6253  'numRows.' => [$this->getUniqueId('numRows')],
6254  ];
6255  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6256  ->setMethods(['numRows'])->getMock();
6257  $subject->expects($this->once())->method('numRows')
6258  ->with($conf['numRows.'])->willReturn('return');
6259  $this->assertSame('return',
6260  $subject->stdWrap_numRows('discard', $conf));
6261  }
6262 
6276  public function stdWrap_numberFormat()
6277  {
6278  $content = $this->getUniqueId('content');
6279  $conf = [
6280  'numberFormat' => $this->getUniqueId('not used'),
6281  'numberFormat.' => [$this->getUniqueId('numberFormat.')],
6282  ];
6283  $return = $this->getUniqueId('return');
6284  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6285  ->setMethods(['numberFormat'])->getMock();
6286  $subject
6287  ->expects($this->once())
6288  ->method('numberFormat')
6289  ->with($content, $conf['numberFormat.'])
6290  ->willReturn($return);
6291  $this->assertSame($return,
6292  $subject->stdWrap_numberFormat($content, $conf));
6293  }
6294 
6301  {
6302  return [
6303  'no conf' => [
6304  'XXX',
6305  'XXX',
6306  [],
6307  ],
6308  'simple' => [
6309  '<wrap>XXX</wrap>',
6310  'XXX',
6311  ['outerWrap' => '<wrap>|</wrap>'],
6312  ],
6313  'missing pipe puts wrap before' => [
6314  '<pre>XXX',
6315  'XXX',
6316  ['outerWrap' => '<pre>'],
6317  ],
6318  'trims whitespace' => [
6319  '<wrap>XXX</wrap>',
6320  'XXX',
6321  ['outerWrap' => '<wrap>' . TAB . ' | ' . TAB . '</wrap>'],
6322  ],
6323  'split char change is not possible' => [
6324  '<wrap> # </wrap>XXX',
6325  'XXX',
6326  [
6327  'outerWrap' => '<wrap> # </wrap>',
6328  'outerWrap.' => ['splitChar' => '#'],
6329  ],
6330  ],
6331  ];
6332  }
6333 
6344  public function stdWrap_outerWrap($expected, $input, $conf)
6345  {
6346  $this->assertSame($expected,
6347  $this->subject->stdWrap_outerWrap($input, $conf));
6348  }
6349 
6356  {
6357  return [
6358  'standard case' => [
6359  'override', 'content', ['override' => 'override']
6360  ],
6361  'empty conf does not override' => [
6362  'content', 'content', []
6363  ],
6364  'empty string does not override' => [
6365  'content', 'content', ['override' => '']
6366  ],
6367  'whitespace does not override' => [
6368  'content', 'content', ['override' => ' ' . TAB]
6369  ],
6370  'zero does not override' => [
6371  'content', 'content', ['override' => 0]
6372  ],
6373  'false does not override' => [
6374  'content', 'content', ['override' => false]
6375  ],
6376  'null does not override' => [
6377  'content', 'content', ['override' => null]
6378  ],
6379  'one does override' => [
6380  1, 'content', ['override' => 1]
6381  ],
6382  'minus one does override' => [
6383  -1, 'content', ['override' => -1]
6384  ],
6385  'float does override' => [
6386  -0.1, 'content', ['override' => -0.1]
6387  ],
6388  'true does override' => [
6389  true, 'content', ['override' => true]
6390  ],
6391  'the value is not trimmed' => [
6392  TAB . 'override', 'content', ['override' => TAB . 'override']
6393  ],
6394  ];
6395  }
6396 
6406  public function stdWrap_override($expect, $content, $conf)
6407  {
6408  $this->assertSame($expect,
6409  $this->subject->stdWrap_override($content, $conf));
6410  }
6411 
6426  public function stdWrap_parseFunc()
6427  {
6428  $content = $this->getUniqueId('content');
6429  $conf = [
6430  'parseFunc' => $this->getUniqueId('parseFunc'),
6431  'parseFunc.' => [$this->getUniqueId('parseFunc.')],
6432  ];
6433  $return = $this->getUniqueId('return');
6434  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6435  ->setMethods(['parseFunc'])->getMock();
6436  $subject
6437  ->expects($this->once())
6438  ->method('parseFunc')
6439  ->with($content, $conf['parseFunc.'], $conf['parseFunc'])
6440  ->willReturn($return);
6441  $this->assertSame($return,
6442  $subject->stdWrap_parseFunc($content, $conf));
6443  }
6444 
6459  public function stdWrap_postCObject()
6460  {
6461  $debugKey = '/stdWrap/.postCObject';
6462  $content = $this->getUniqueId('content');
6463  $conf = [
6464  'postCObject' => $this->getUniqueId('postCObject'),
6465  'postCObject.' => [$this->getUniqueId('postCObject.')],
6466  ];
6467  $return = $this->getUniqueId('return');
6468  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6469  ->setMethods(['cObjGetSingle'])->getMock();
6470  $subject
6471  ->expects($this->once())
6472  ->method('cObjGetSingle')
6473  ->with($conf['postCObject'], $conf['postCObject.'], $debugKey)
6474  ->willReturn($return);
6475  $this->assertSame($content . $return,
6476  $subject->stdWrap_postCObject($content, $conf));
6477  }
6478 
6491  public function stdWrap_postUserFunc()
6492  {
6493  $content = $this->getUniqueId('content');
6494  $conf = [
6495  'postUserFunc' => $this->getUniqueId('postUserFunc'),
6496  'postUserFunc.' => [$this->getUniqueId('postUserFunc.')],
6497  ];
6498  $return = $this->getUniqueId('return');
6499  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6500  ->setMethods(['callUserFunction'])->getMock();
6501  $subject
6502  ->expects($this->once())
6503  ->method('callUserFunction')
6504  ->with($conf['postUserFunc'], $conf['postUserFunc.'])
6505  ->willReturn($return);
6506  $this->assertSame($return,
6507  $subject->stdWrap_postUserFunc($content, $conf));
6508  }
6509 
6529  public function stdWrap_postUserFuncInt()
6530  {
6531  $uniqueHash = $this->getUniqueId('uniqueHash');
6532  $substKey = 'INT_SCRIPT.' . $uniqueHash;
6533  $content = $this->getUniqueId('content');
6534  $conf = [
6535  'postUserFuncInt' => $this->getUniqueId('function'),
6536  'postUserFuncInt.' => [$this->getUniqueId('function array')],
6537  ];
6538  $expect = '<!--' . $substKey . '-->';
6539  $frontend = $this->getMockBuilder(TypoScriptFrontendController::class)
6540  ->disableOriginalConstructor()->setMethods(['uniqueHash'])
6541  ->getMock();
6542  $frontend->expects($this->once())->method('uniqueHash')
6543  ->with()->willReturn($uniqueHash);
6544  $frontend->config = [];
6545  $subject = $this->getAccessibleMock(
6546  ContentObjectRenderer::class, null, [$frontend]);
6547  $this->assertSame($expect,
6548  $subject->stdWrap_postUserFuncInt($content, $conf));
6549  $array = [
6550  'content' => $content,
6551  'postUserFunc' => $conf['postUserFuncInt'],
6552  'conf' => $conf['postUserFuncInt.'],
6553  'type' => 'POSTUSERFUNC',
6554  'cObj' => serialize($subject)
6555  ];
6556  $this->assertSame($array,
6557  $frontend->config['INTincScript'][$substKey]);
6558  }
6559 
6574  public function stdWrap_preCObject()
6575  {
6576  $debugKey = '/stdWrap/.preCObject';
6577  $content = $this->getUniqueId('content');
6578  $conf = [
6579  'preCObject' => $this->getUniqueId('preCObject'),
6580  'preCObject.' => [$this->getUniqueId('preCObject.')],
6581  ];
6582  $return = $this->getUniqueId('return');
6583  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6584  ->setMethods(['cObjGetSingle'])->getMock();
6585  $subject
6586  ->expects($this->once())
6587  ->method('cObjGetSingle')
6588  ->with($conf['preCObject'], $conf['preCObject.'], $debugKey)
6589  ->willReturn($return);
6590  $this->assertSame($return . $content,
6591  $subject->stdWrap_preCObject($content, $conf));
6592  }
6593 
6608  public function stdWrap_preIfEmptyListNum()
6609  {
6610  $content = $this->getUniqueId('content');
6611  $conf = [
6612  'preIfEmptyListNum' => $this->getUniqueId('preIfEmptyListNum'),
6613  'preIfEmptyListNum.' => [
6614  'splitChar' => $this->getUniqueId('splitChar')
6615  ],
6616  ];
6617  $return = $this->getUniqueId('return');
6618  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6619  ->setMethods(['listNum'])->getMock();
6620  $subject
6621  ->expects($this->once())
6622  ->method('listNum')
6623  ->with(
6624  $content,
6625  $conf['preIfEmptyListNum'],
6626  $conf['preIfEmptyListNum.']['splitChar']
6627  )
6628  ->willReturn($return);
6629  $this->assertSame($return,
6630  $subject->stdWrap_preIfEmptyListNum($content, $conf));
6631  }
6632 
6639  {
6640  $content = $this->getUniqueId('content');
6641  $will = $this->getUniqueId('will');
6642  $conf['prefixComment'] = $this->getUniqueId('prefixComment');
6643  $emptyConf1 = [];
6644  $emptyConf2['prefixComment'] = '';
6645  return [
6646  'standard case' => [$will, $content, $conf, false, 1, $will],
6647  'emptyConf1' => [$content, $content, $emptyConf1, false, 0, $will],
6648  'emptyConf2' => [$content, $content, $emptyConf2, false, 0, $will],
6649  'disabled by bool' => [$content, $content, $conf, true, 0, $will],
6650  'disabled by int' => [$content, $content, $conf, 1, 0, $will],
6651  ];
6652  }
6653 
6672  public function stdWrap_prefixComment(
6673  $expect, $content, $conf, $disable, $times, $will)
6674  {
6675  $this->frontendControllerMock
6676  ->config['config']['disablePrefixComment'] = $disable;
6677  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6678  ->setMethods(['prefixComment'])->getMock();
6679  $subject
6680  ->expects($this->exactly($times))
6681  ->method('prefixComment')
6682  ->with($conf['prefixComment'], [], $content)
6683  ->willReturn($will);
6684  $this->assertSame($expect,
6685  $subject->stdWrap_prefixComment($content, $conf));
6686  }
6687 
6702  public function stdWrap_prepend()
6703  {
6704  $debugKey = '/stdWrap/.prepend';
6705  $content = $this->getUniqueId('content');
6706  $conf = [
6707  'prepend' => $this->getUniqueId('prepend'),
6708  'prepend.' => [$this->getUniqueId('prepend.')],
6709  ];
6710  $return = $this->getUniqueId('return');
6711  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6712  ->setMethods(['cObjGetSingle'])->getMock();
6713  $subject
6714  ->expects($this->once())
6715  ->method('cObjGetSingle')
6716  ->with($conf['prepend'], $conf['prepend.'], $debugKey)
6717  ->willReturn($return);
6718  $this->assertSame($return . $content,
6719  $subject->stdWrap_prepend($content, $conf));
6720  }
6721 
6728  {
6729  return [
6730  'priority of *' => ['7', '1 + 2 * 3', []],
6731  'priority of parentheses' => ['9', '(1 + 2) * 3', []],
6732  'float' => ['1.5', '3/2', []],
6733  'intval casts to int' => [1, '3/2', ['prioriCalc' => 'intval']],
6734  'intval does not round' => [2, '2.7', ['prioriCalc' => 'intval']],
6735  ];
6736  }
6737 
6759  public function stdWrap_prioriCalc($expect, $content, $conf)
6760  {
6761  $result = $this->subject->stdWrap_prioriCalc($content, $conf);
6762  $this->assertSame($expect, $result);
6763  }
6764 
6779  public function stdWrap_preUserFunc()
6780  {
6781  $content = $this->getUniqueId('content');
6782  $conf = [
6783  'preUserFunc' => $this->getUniqueId('preUserFunc'),
6784  'preUserFunc.' => [$this->getUniqueId('preUserFunc.')],
6785  ];
6786  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6787  ->setMethods(['callUserFunction'])->getMock();
6788  $subject->expects($this->once())->method('callUserFunction')
6789  ->with($conf['preUserFunc'], $conf['preUserFunc.'], $content)
6790  ->willReturn('return');
6791  $this->assertSame('return',
6792  $subject->stdWrap_preUserFunc($content, $conf));
6793  }
6794 
6801  {
6802  return [
6803  'https://typo3.org?id=10' => [
6804  'https%3A%2F%2Ftypo3.org%3Fid%3D10',
6805  'https://typo3.org?id=10',
6806  ],
6807  'https://typo3.org?id=10&foo=bar' => [
6808  'https%3A%2F%2Ftypo3.org%3Fid%3D10%26foo%3Dbar',
6809  'https://typo3.org?id=10&foo=bar',
6810  ],
6811  ];
6812  }
6813 
6823  public function stdWrap_rawUrlEncode($expect, $content)
6824  {
6825  $this->assertSame($expect,
6826  $this->subject->stdWrap_rawUrlEncode($content));
6827  }
6828 
6842  public function stdWrap_replacement()
6843  {
6844  $content = $this->getUniqueId('content');
6845  $conf = [
6846  'replacement' => $this->getUniqueId('not used'),
6847  'replacement.' => [$this->getUniqueId('replacement.')],
6848  ];
6849  $return = $this->getUniqueId('return');
6850  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6851  ->setMethods(['replacement'])->getMock();
6852  $subject
6853  ->expects($this->once())
6854  ->method('replacement')
6855  ->with($content, $conf['replacement.'])
6856  ->willReturn($return);
6857  $this->assertSame($return,
6858  $subject->stdWrap_replacement($content, $conf));
6859  }
6860 
6867  {
6868  return [
6869  // empty content
6870  'empty string is empty' => ['', true, ''],
6871  'null is empty' => ['', true, null],
6872  'false is empty' => ['', true, false],
6873 
6874  // non-empty content
6875  'blank is not empty' => [' ', false, ' '],
6876  'tab is not empty' => [TAB, false, TAB],
6877  'linebreak is not empty' => [PHP_EOL, false, PHP_EOL],
6878  '"0" is not empty' => ['0', false, '0'],
6879  '0 is not empty' => [0, false, 0],
6880  '1 is not empty' => [1, false, 1],
6881  'true is not empty' => [true, false, true],
6882  ];
6883  }
6884 
6901  public function stdWrap_required($expect, $stop, $content)
6902  {
6904  $subject->_set('stdWrapRecursionLevel', 1);
6905  $subject->_set('stopRendering', [1 => false]);
6906  $this->assertSame($expect, $subject->stdWrap_required($content));
6907  $this->assertSame($stop, $subject->_get('stopRendering')[1]);
6908  }
6909 
6923  public function stdWrap_round()
6924  {
6925  $content = $this->getUniqueId('content');
6926  $conf = [
6927  'round' => $this->getUniqueId('not used'),
6928  'round.' => [$this->getUniqueId('round.')],
6929  ];
6930  $return = $this->getUniqueId('return');
6931  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
6932  ->setMethods(['round'])->getMock();
6933  $subject
6934  ->expects($this->once())
6935  ->method('round')
6936  ->with($content, $conf['round.'])
6937  ->willReturn($return);
6938  $this->assertSame($return, $subject->stdWrap_round($content, $conf));
6939  }
6940 
6948  {
6949  $content = $this->getUniqueId('content');
6950  $this->assertNotSame($content, $this->subject->getData('current'));
6951  $this->assertSame($content,
6952  $this->subject->stdWrap_setContentToCurrent($content));
6953  $this->assertSame($content, $this->subject->getData('current'));
6954  }
6955 
6962  {
6963  return [
6964  'no conf' => [
6965  'content',
6966  [],
6967  ],
6968  'empty string' => [
6969  'content',
6970  ['setCurrent' => ''],
6971  ],
6972  'non-empty string' => [
6973  'content',
6974  ['setCurrent' => 'xxx'],
6975  ],
6976  'integer null' => [
6977  'content',
6978  ['setCurrent' => 0],
6979  ],
6980  'integer not null' => [
6981  'content',
6982  ['setCurrent' => 1],
6983  ],
6984  'boolean true' => [
6985  'content',
6986  ['setCurrent' => true],
6987  ],
6988  'boolean false' => [
6989  'content',
6990  ['setCurrent' => false],
6991  ],
6992  ];
6993  }
6994 
7004  public function stdWrap_setCurrent($input, $conf)
7005  {
7006  if (isset($conf['setCurrent'])) {
7007  $this->assertNotSame($conf['setCurrent'], $this->subject->getData('current'));
7008  }
7009  $this->assertSame($input, $this->subject->stdWrap_setCurrent($input, $conf));
7010  if (isset($conf['setCurrent'])) {
7011  $this->assertSame($conf['setCurrent'], $this->subject->getData('current'));
7012  }
7013  }
7014 
7030  public function stdWrap_space()
7031  {
7032  $content = $this->getUniqueId('content');
7033  $trimmed = $this->getUniqueId('space trimmed');
7034  $conf = [
7035  'space' => TAB . ' ' . $trimmed . ' ' . TAB,
7036  'space.' => [$this->getUniqueId('space.')],
7037  ];
7038  $return = $this->getUniqueId('return');
7039  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7040  ->setMethods(['wrapSpace'])->getMock();
7041  $subject
7042  ->expects($this->once())
7043  ->method('wrapSpace')
7044  ->with($content, $trimmed, $conf['space.'])
7045  ->willReturn($return);
7046  $this->assertSame($return, $subject->stdWrap_space($content, $conf));
7047  }
7048 
7065  public function stdWrap_spaceAfter()
7066  {
7067  $content = $this->getUniqueId('content');
7068  $trimmed = $this->getUniqueId('spaceAfter trimmed');
7069  $conf = [
7070  'spaceAfter' => TAB . ' ' . $trimmed . ' ' . TAB,
7071  'space.' => [$this->getUniqueId('space.')],
7072  ];
7073  $return = $this->getUniqueId('return');
7074  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7075  ->setMethods(['wrapSpace'])->getMock();
7076  $subject
7077  ->expects($this->once())
7078  ->method('wrapSpace')
7079  ->with($content, '|' . $trimmed, $conf['space.'])
7080  ->willReturn($return);
7081  $this->assertSame($return,
7082  $subject->stdWrap_spaceAfter($content, $conf));
7083  }
7084 
7101  public function stdWrap_spaceBefore()
7102  {
7103  $content = $this->getUniqueId('content');
7104  $trimmed = $this->getUniqueId('spaceBefore trimmed');
7105  $conf = [
7106  'spaceBefore' => TAB . ' ' . $trimmed . ' ' . TAB,
7107  'space.' => [$this->getUniqueId('space.')],
7108  ];
7109  $return = $this->getUniqueId('return');
7110  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7111  ->setMethods(['wrapSpace'])->getMock();
7112  $subject
7113  ->expects($this->once())
7114  ->method('wrapSpace')
7115  ->with($content, $trimmed . '|', $conf['space.'])
7116  ->willReturn($return);
7117  $this->assertSame($return,
7118  $subject->stdWrap_spaceBefore($content, $conf));
7119  }
7120 
7134  public function stdWrap_split()
7135  {
7136  $content = $this->getUniqueId('content');
7137  $conf = [
7138  'split' => $this->getUniqueId('not used'),
7139  'split.' => [$this->getUniqueId('split.')],
7140  ];
7141  $return = $this->getUniqueId('return');
7142  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7143  ->setMethods(['splitObj'])->getMock();
7144  $subject
7145  ->expects($this->once())
7146  ->method('splitObj')
7147  ->with($content, $conf['split.'])
7148  ->willReturn($return);
7149  $this->assertSame($return,
7150  $subject->stdWrap_split($content, $conf));
7151  }
7152 
7165  public function stdWrap_stdWrap()
7166  {
7167  $content = $this->getUniqueId('content');
7168  $conf = [
7169  'stdWrap' => $this->getUniqueId('not used'),
7170  'stdWrap.' => [$this->getUniqueId('stdWrap.')],
7171  ];
7172  $return = $this->getUniqueId('return');
7173  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7174  ->setMethods(['stdWrap'])->getMock();
7175  $subject
7176  ->expects($this->once())
7177  ->method('stdWrap')
7178  ->with($content, $conf['stdWrap.'])
7179  ->willReturn($return);
7180  $this->assertSame($return, $subject->stdWrap_stdWrap($content, $conf));
7181  }
7182 
7189  {
7190  return [
7191  'only key returns value' => [
7192  'ifNull',
7193  [
7194  'ifNull' => '1',
7195  ],
7196  '',
7197  '1',
7198  ],
7199  'array without key returns empty string' => [
7200  'ifNull',
7201  [
7202  'ifNull.' => '1',
7203  ],
7204  '',
7205  '',
7206  ],
7207  'array without key returns default' => [
7208  'ifNull',
7209  [
7210  'ifNull.' => '1',
7211  ],
7212  'default',
7213  'default',
7214  ],
7215  'non existing key returns default' => [
7216  'ifNull',
7217  [
7218  'noTrimWrap' => 'test',
7219  'noTrimWrap.' => '1',
7220  ],
7221  'default',
7222  'default',
7223  ],
7224  'existing key and array returns stdWrap' => [
7225  'test',
7226  [
7227  'test' => 'value',
7228  'test.' => ['case' => 'upper'],
7229  ],
7230  'default',
7231  'VALUE'
7232  ],
7233  ];
7234  }
7235 
7244  public function stdWrap_stdWrapValue($key, array $configuration, $defaultValue, $expected)
7245  {
7246  $result = $this->subject->stdWrapValue($key, $configuration, $defaultValue);
7247  $this->assertEquals($expected, $result);
7248  }
7249 
7255  public function stdWrap_strPadDataProvider()
7256  {
7257  return [
7258  'pad string with default settings and length 10' => [
7259  'Alien ',
7260  'Alien',
7261  [
7262  'length' => '10',
7263  ],
7264  ],
7265  'pad string with padWith -= and type left and length 10' => [
7266  '-=-=-Alien',
7267  'Alien',
7268  [
7269  'length' => '10',
7270  'padWith' => '-=',
7271  'type' => 'left',
7272  ],
7273  ],
7274  'pad string with padWith _ and type both and length 10' => [
7275  '__Alien___',
7276  'Alien',
7277  [
7278  'length' => '10',
7279  'padWith' => '_',
7280  'type' => 'both',
7281  ],
7282  ],
7283  'pad string with padWith 0 and type both and length 10' => [
7284  '00Alien000',
7285  'Alien',
7286  [
7287  'length' => '10',
7288  'padWith' => '0',
7289  'type' => 'both',
7290  ],
7291  ],
7292  'pad string with padWith ___ and type both and length 6' => [
7293  'Alien_',
7294  'Alien',
7295  [
7296  'length' => '6',
7297  'padWith' => '___',
7298  'type' => 'both',
7299  ],
7300  ],
7301  'pad string with padWith _ and type both and length 12, using stdWrap for length' => [
7302  '___Alien____',
7303  'Alien',
7304  [
7305  'length' => '1',
7306  'length.' => [
7307  'wrap' => '|2',
7308  ],
7309  'padWith' => '_',
7310  'type' => 'both',
7311  ],
7312  ],
7313  'pad string with padWith _ and type both and length 12, using stdWrap for padWidth' => [
7314  '-_=Alien-_=-',
7315  'Alien',
7316  [
7317  'length' => '12',
7318  'padWith' => '_',
7319  'padWith.' => [
7320  'wrap' => '-|=',
7321  ],
7322  'type' => 'both',
7323  ],
7324  ],
7325  'pad string with padWith _ and type both and length 12, using stdWrap for type' => [
7326  '_______Alien',
7327  'Alien',
7328  [
7329  'length' => '12',
7330  'padWith' => '_',
7331  'type' => 'both',
7332  // make type become "left"
7333  'type.' => [
7334  'substring' => '2,1',
7335  'wrap' => 'lef|',
7336  ],
7337  ],
7338  ],
7339  ];
7340  }
7341 
7352  public function stdWrap_strPad($expect, $content, $conf)
7353  {
7354  $conf = ['strPad.' => $conf];
7355  $result = $this->subject->stdWrap_strPad($content, $conf);
7356  $this->assertSame($expect, $result);
7357  }
7358 
7365  {
7366  // Fictive execution time is 2012-09-01 12:00 in UTC/GMT.
7367  $now = 1346500800;
7368  return [
7369  'given timestamp' => [
7370  '01-09-2012',
7371  $now,
7372  ['strftime' => '%d-%m-%Y'],
7373  $now
7374  ],
7375  'empty string' => [
7376  '01-09-2012',
7377  '',
7378  ['strftime' => '%d-%m-%Y'],
7379  $now
7380  ],
7381  'testing null' => [
7382  '01-09-2012',
7383  null,
7384  ['strftime' => '%d-%m-%Y'],
7385  $now
7386  ]
7387  ];
7388  }
7389 
7401  public function stdWrap_strftime($expect, $content, $conf, $now)
7402  {
7403  // Save current timezone and set to UTC to make the system under test
7404  // behave the same in all server timezone settings
7405  $timezoneBackup = date_default_timezone_get();
7406  date_default_timezone_set('UTC');
7407 
7408  $GLOBALS['EXEC_TIME'] = $now;
7409  $result = $this->subject->stdWrap_strftime($content, $conf);
7410 
7411  // Reset timezone
7412  date_default_timezone_set($timezoneBackup);
7413 
7414  $this->assertSame($expect, $result);
7415  }
7416 
7422  public function stdWrap_stripHtml()
7423  {
7424  $content = '<html><p>Hello <span class="inline">inline tag<span>!</p><p>Hello!</p></html>';
7425  $expected = 'Hello inline tag!Hello!';
7426  $this->assertSame($expected, $this->subject->stdWrap_stripHtml($content));
7427  }
7428 
7435  {
7436  return [
7437  'date from content' => [
7438  1417651200, '2014-12-04',
7439  ['strtotime' => '1']
7440  ],
7441  'manipulation of date from content' => [
7442  1417996800, '2014-12-04',
7443  ['strtotime' => '+ 2 weekdays']
7444  ],
7445  'date from configuration' => [
7446  1417651200, '',
7447  ['strtotime' => '2014-12-04']
7448  ],
7449  'manipulation of date from configuration' => [
7450  1417996800, '',
7451  ['strtotime' => '2014-12-04 + 2 weekdays']
7452  ],
7453  'empty input' => [
7454  false, '',
7455  ['strtotime' => '1']
7456  ],
7457  'date from content and configuration' => [
7458  false, '2014-12-04',
7459  ['strtotime' => '2014-12-05']
7460  ]
7461  ];
7462  }
7463 
7474  public function stdWrap_strtotime($expect, $content, $conf)
7475  {
7476  // Set exec_time to a hard timestamp
7477  $GLOBALS['EXEC_TIME'] = 1417392000;
7478  // Save current timezone and set to UTC to make the system under test
7479  // behave the same in all server timezone settings
7480  $timezoneBackup = date_default_timezone_get();
7481  date_default_timezone_set('UTC');
7482 
7483  $result = $this->subject->stdWrap_strtotime($content, $conf);
7484 
7485  // Reset timezone
7486  date_default_timezone_set($timezoneBackup);
7487 
7488  $this->assertEquals($expect, $result);
7489  }
7490 
7504  public function stdWrap_substring()
7505  {
7506  $content = $this->getUniqueId('content');
7507  $conf = [
7508  'substring' => $this->getUniqueId('substring'),
7509  'substring.' => $this->getUniqueId('not used'),
7510  ];
7511  $return = $this->getUniqueId('return');
7512  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7513  ->setMethods(['substring'])->getMock();
7514  $subject
7515  ->expects($this->once())
7516  ->method('substring')
7517  ->with($content, $conf['substring'])
7518  ->willReturn($return);
7519  $this->assertSame($return,
7520  $subject->stdWrap_substring($content, $conf));
7521  }
7522 
7528  public function stdWrap_trimDataProvider()
7529  {
7530  return [
7531  // string not trimmed
7532  'empty string' => ['', ''],
7533  'string without whitespace' => ['xxx', 'xxx'],
7534  'string with whitespace inside' => [
7535  'xx ' . TAB . ' xx',
7536  'xx ' . TAB . ' xx',
7537  ],
7538  'string with newlines inside' => [
7539  'xx ' . PHP_EOL . ' xx',
7540  'xx ' . PHP_EOL . ' xx',
7541  ],
7542  // string trimmed
7543  'blanks around' => ['xxx', ' xxx '],
7544  'tabs around' => ['xxx', TAB . 'xxx' . TAB],
7545  'newlines around' => ['xxx', PHP_EOL . 'xxx' . PHP_EOL],
7546  'mixed case' => ['xxx', TAB . ' xxx ' . PHP_EOL],
7547  // non strings
7548  'null' => ['', null],
7549  'false' => ['', false],
7550  'true' => ['1', true],
7551  'zero' => ['0', 0],
7552  'one' => ['1', 1],
7553  '-1' => ['-1', -1],
7554  '0.0' => ['0', 0.0],
7555  '1.0' => ['1', 1.0],
7556  '-1.0' => ['-1', -1.0],
7557  '1.1' => ['1.1', 1.1],
7558  ];
7559  }
7560 
7582  public function stdWrap_trim($expect, $content)
7583  {
7584  $result = $this->subject->stdWrap_trim($content);
7585  $this->assertSame($expect, $result);
7586  }
7587 
7600  public function stdWrap_typolink()
7601  {
7602  $content = $this->getUniqueId('content');
7603  $conf = [
7604  'typolink' => $this->getUniqueId('not used'),
7605  'typolink.' => [$this->getUniqueId('typolink.')],
7606  ];
7607  $return = $this->getUniqueId('return');
7608  $subject = $this->getMockBuilder(ContentObjectRenderer::class)
7609  ->setMethods(['typolink'])->getMock();
7610  $subject
7611  ->expects($this->once())
7612  ->method('typolink')
7613  ->with($content, $conf['typolink.'])
7614  ->willReturn($return);
7615  $this->assertSame($return, $subject->stdWrap_typolink($content, $conf));
7616  }
7617 
7623  public function stdWrap_wrapDataProvider()
7624  {
7625  return [
7626  'no conf' => [
7627  'XXX',
7628  'XXX',
7629  [],
7630  ],
7631  'simple' => [
7632  '<wrapper>XXX</wrapper>',
7633  'XXX',
7634  ['wrap' => '<wrapper>|</wrapper>'],
7635  ],
7636  'trims whitespace' => [
7637  '<wrapper>XXX</wrapper>',
7638  'XXX',
7639  ['wrap' => '<wrapper>' . TAB . ' | ' . TAB . '</wrapper>'],
7640  ],
7641  'missing pipe puts wrap before' => [
7642  '<pre>XXX',
7643  'XXX',
7644  [
7645  'wrap' => '<pre>',
7646  ],
7647  ],
7648  'split char change' => [
7649  '<wrapper>XXX</wrapper>',
7650  'XXX',
7651  [
7652  'wrap' => '<wrapper> # </wrapper>',
7653  'wrap.' => ['splitChar' => '#'],
7654  ],
7655  ],
7656  'split by pattern' => [
7657  '<wrapper>XXX</wrapper>',
7658  'XXX',
7659  [
7660  'wrap' => '<wrapper> ###splitter### </wrapper>',
7661  'wrap.' => ['splitChar' => '###splitter###'],
7662  ],
7663  ],
7664  ];
7665  }
7666 
7677  public function stdWrap_wrap($expected, $input, $conf)
7678  {
7679  $this->assertSame($expected,
7680  $this->subject->stdWrap_wrap($input, $conf));
7681  }
7682 
7688  public function stdWrap_wrap2DataProvider()
7689  {
7690  return [
7691  'no conf' => [
7692  'XXX',
7693  'XXX',
7694  [],
7695  ],
7696  'simple' => [
7697  '<wrapper>XXX</wrapper>',
7698  'XXX',
7699  ['wrap2' => '<wrapper>|</wrapper>'],
7700  ],
7701  'trims whitespace' => [
7702  '<wrapper>XXX</wrapper>',
7703  'XXX',
7704  ['wrap2' => '<wrapper>' . TAB . ' | ' . TAB . '</wrapper>'],
7705  ],
7706  'missing pipe puts wrap2 before' => [
7707  '<pre>XXX',
7708  'XXX',
7709  [
7710  'wrap2' => '<pre>',
7711  ],
7712  ],
7713  'split char change' => [
7714  '<wrapper>XXX</wrapper>',
7715  'XXX',
7716  [
7717  'wrap2' => '<wrapper> # </wrapper>',
7718  'wrap2.' => ['splitChar' => '#'],
7719  ],
7720  ],
7721  'split by pattern' => [
7722  '<wrapper>XXX</wrapper>',
7723  'XXX',
7724  [
7725  'wrap2' => '<wrapper> ###splitter### </wrapper>',
7726  'wrap2.' => ['splitChar' => '###splitter###'],
7727  ],
7728  ],
7729  ];
7730  }
7731 
7742  public function stdWrap_wrap2($expected, $input, $conf)
7743  {
7744  $this->assertSame($expected, $this->subject->stdWrap_wrap2($input, $conf));
7745  }
7746 
7752  public function stdWrap_wrap3DataProvider()
7753  {
7754  return [
7755  'no conf' => [
7756  'XXX',
7757  'XXX',
7758  [],
7759  ],
7760  'simple' => [
7761  '<wrapper>XXX</wrapper>',
7762  'XXX',
7763  ['wrap3' => '<wrapper>|</wrapper>'],
7764  ],
7765  'trims whitespace' => [
7766  '<wrapper>XXX</wrapper>',
7767  'XXX',
7768  ['wrap3' => '<wrapper>' . TAB . ' | ' . TAB . '</wrapper>'],
7769  ],
7770  'missing pipe puts wrap3 before' => [
7771  '<pre>XXX',
7772  'XXX',
<