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