cf9214b11bbce68ce142b12109555c49e5d112e8
[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 * @param string|NULL $content
1512 * @param array $configuration
1513 * @param string $expected
1514 * @dataProvider stdWrap_ifNullDeterminesNullValuesDataProvider
1515 * @test
1516 */
1517 public function stdWrap_ifNullDeterminesNullValues($content, array $configuration, $expected) {
1518 $result = $this->subject->stdWrap_ifNull($content, $configuration);
1519 $this->assertEquals($expected, $result);
1520 }
1521
1522 /**
1523 * Data provider for stdWrap_ifNullDeterminesNullValues test
1524 *
1525 * @return array
1526 */
1527 public function stdWrap_ifNullDeterminesNullValuesDataProvider() {
1528 return array(
1529 'null value' => array(
1530 NULL,
1531 array(
1532 'ifNull' => '1',
1533 ),
1534 '1',
1535 ),
1536 'zero value' => array(
1537 '0',
1538 array(
1539 'ifNull' => '1',
1540 ),
1541 '0',
1542 ),
1543 );
1544 }
1545
1546 /**
1547 * @param $content
1548 * @param array $configuration
1549 * @param $expected
1550 * @dataProvider stdWrap_noTrimWrapAcceptsSplitCharDataProvider
1551 * @test
1552 */
1553 public function stdWrap_noTrimWrapAcceptsSplitChar($content, array $configuration, $expected) {
1554 $result = $this->subject->stdWrap_noTrimWrap($content, $configuration);
1555 $this->assertEquals($expected, $result);
1556 }
1557
1558 /**
1559 * Data provider for stdWrap_noTrimWrapAcceptsSplitChar test
1560 *
1561 * @return array
1562 */
1563 public function stdWrap_noTrimWrapAcceptsSplitCharDataProvider() {
1564 return array(
1565 'No char given' => array(
1566 'middle',
1567 array(
1568 'noTrimWrap' => '| left | right |',
1569 ),
1570 ' left middle right '
1571 ),
1572 'Zero char given' => array(
1573 'middle',
1574 array(
1575 'noTrimWrap' => '0 left 0 right 0',
1576 'noTrimWrap.' => array('splitChar' => '0'),
1577
1578 ),
1579 ' left middle right '
1580 ),
1581 'Default char given' => array(
1582 'middle',
1583 array(
1584 'noTrimWrap' => '| left | right |',
1585 'noTrimWrap.' => array('splitChar' => '|'),
1586 ),
1587 ' left middle right '
1588 ),
1589 'Split char is a' => array(
1590 'middle',
1591 array(
1592 'noTrimWrap' => 'a left a right a',
1593 'noTrimWrap.' => array('splitChar' => 'a'),
1594 ),
1595 ' left middle right '
1596 ),
1597 'Split char is multi-char (ab)' => array(
1598 'middle',
1599 array(
1600 'noTrimWrap' => 'ab left ab right ab',
1601 'noTrimWrap.' => array('splitChar' => 'ab'),
1602 ),
1603 ' left middle right '
1604 ),
1605 'Split char accepts stdWrap' => array(
1606 'middle',
1607 array(
1608 'noTrimWrap' => 'abc left abc right abc',
1609 'noTrimWrap.' => array(
1610 'splitChar' => 'b',
1611 'splitChar.' => array('wrap' => 'a|c'),
1612 ),
1613 ),
1614 ' left middle right '
1615 ),
1616 );
1617 }
1618
1619 /**
1620 * @param array $expectedTags
1621 * @param array $configuration
1622 * @test
1623 * @dataProvider stdWrap_addPageCacheTagsAddsPageTagsDataProvider
1624 */
1625 public function stdWrap_addPageCacheTagsAddsPageTags(array $expectedTags, array $configuration) {
1626 $this->subject->stdWrap_addPageCacheTags('', $configuration);
1627 $this->assertEquals($expectedTags, $this->typoScriptFrontendControllerMock->_get('pageCacheTags'));
1628 }
1629
1630 /**
1631 * @return array
1632 */
1633 public function stdWrap_addPageCacheTagsAddsPageTagsDataProvider() {
1634 return array(
1635 'No Tag' => array(
1636 array(),
1637 array('addPageCacheTags' => ''),
1638 ),
1639 'Two expectedTags' => array(
1640 array('tag1', 'tag2'),
1641 array('addPageCacheTags' => 'tag1,tag2'),
1642 ),
1643 'Two expectedTags plus one with stdWrap' => array(
1644 array('tag1', 'tag2', 'tag3'),
1645 array(
1646 'addPageCacheTags' => 'tag1,tag2',
1647 'addPageCacheTags.' => array('wrap' => '|,tag3')
1648 ),
1649 ),
1650 );
1651 }
1652
1653 /**
1654 * Data provider for stdWrap_encodeForJavaScriptValue test
1655 *
1656 * @return array multi-dimensional array with the second level like this:
1657 * @see encodeForJavaScriptValue
1658 */
1659 public function stdWrap_encodeForJavaScriptValueDataProvider() {
1660 return array(
1661 'double quote in string' => array(
1662 'double quote"',
1663 array(),
1664 '\'double\u0020quote\u0022\''
1665 ),
1666 'backslash in string' => array(
1667 'backslash \\',
1668 array(),
1669 '\'backslash\u0020\u005C\''
1670 ),
1671 'exclamation mark' => array(
1672 'exclamation!',
1673 array(),
1674 '\'exclamation\u0021\''
1675 ),
1676 'whitespace tab, newline and carriage return' => array(
1677 "white\tspace\ns\r",
1678 array(),
1679 '\'white\u0009space\u000As\u000D\''
1680 ),
1681 'single quote in string' => array(
1682 'single quote \'',
1683 array(),
1684 '\'single\u0020quote\u0020\u0027\''
1685 ),
1686 'tag' => array(
1687 '<tag>',
1688 array(),
1689 '\'\u003Ctag\u003E\''
1690 ),
1691 'ampersand in string' => array(
1692 'amper&sand',
1693 array(),
1694 '\'amper\u0026sand\''
1695 ),
1696 );
1697 }
1698
1699 /**
1700 * Check if encodeForJavaScriptValue works properly
1701 *
1702 * @dataProvider stdWrap_encodeForJavaScriptValueDataProvider
1703 * @test
1704 */
1705 public function stdWrap_encodeForJavaScriptValue($input, $conf, $expected) {
1706 $result = $this->subject->stdWrap_encodeForJavaScriptValue($input, $conf);
1707 $this->assertEquals($expected, $result);
1708 }
1709
1710
1711 /////////////////////////////
1712 // Tests concerning getData()
1713 /////////////////////////////
1714
1715 /**
1716 * @return array
1717 */
1718 public function getDataWithTypeGpDataProvider() {
1719 return array(
1720 'Value in get-data' => array('onlyInGet', 'GetValue'),
1721 'Value in post-data' => array('onlyInPost', 'PostValue'),
1722 'Value in post-data overriding get-data' => array('inGetAndPost', 'ValueInPost'),
1723 );
1724 }
1725
1726 /**
1727 * Checks if getData() works with type "gp"
1728 *
1729 * @test
1730 * @dataProvider getDataWithTypeGpDataProvider
1731 */
1732 public function getDataWithTypeGp($key, $expectedValue) {
1733 $_GET = array(
1734 'onlyInGet' => 'GetValue',
1735 'inGetAndPost' => 'ValueInGet',
1736 );
1737 $_POST = array(
1738 'onlyInPost' => 'PostValue',
1739 'inGetAndPost' => 'ValueInPost',
1740 );
1741 $this->assertEquals($expectedValue, $this->subject->getData('gp:' . $key));
1742 }
1743
1744 /**
1745 * Checks if getData() works with type "tsfe"
1746 *
1747 * @test
1748 */
1749 public function getDataWithTypeTsfe() {
1750 $this->assertEquals($GLOBALS['TSFE']->renderCharset, $this->subject->getData('tsfe:renderCharset'));
1751 }
1752
1753 /**
1754 * Checks if getData() works with type "getenv"
1755 *
1756 * @test
1757 */
1758 public function getDataWithTypeGetenv() {
1759 $envName = $this->getUniqueId('frontendtest');
1760 $value = $this->getUniqueId('someValue');
1761 putenv($envName . '=' . $value);
1762 $this->assertEquals($value, $this->subject->getData('getenv:' . $envName));
1763 }
1764
1765 /**
1766 * Checks if getData() works with type "getindpenv"
1767 *
1768 * @test
1769 */
1770 public function getDataWithTypeGetindpenv() {
1771 $this->subject->expects($this->once())->method('getEnvironmentVariable')
1772 ->with($this->equalTo('SCRIPT_FILENAME'))->will($this->returnValue('dummyPath'));
1773 $this->assertEquals('dummyPath', $this->subject->getData('getindpenv:SCRIPT_FILENAME'));
1774 }
1775
1776 /**
1777 * Checks if getData() works with type "field"
1778 *
1779 * @test
1780 */
1781 public function getDataWithTypeField() {
1782 $key = 'someKey';
1783 $value = 'someValue';
1784 $field = array($key => $value);
1785
1786 $this->assertEquals($value, $this->subject->getData('field:' . $key, $field));
1787 }
1788
1789 /**
1790 * Checks if getData() works with type "field" of the field content
1791 * is multi-dimensional (e.g. an array)
1792 *
1793 * @test
1794 */
1795 public function getDataWithTypeFieldAndFieldIsMultiDimensional() {
1796 $key = 'somekey|level1|level2';
1797 $value = 'somevalue';
1798 $field = array('somekey' => array('level1' => array('level2' => 'somevalue')));
1799
1800 $this->assertEquals($value, $this->subject->getData('field:' . $key, $field));
1801 }
1802
1803 /**
1804 * Basic check if getData gets the uid of a file object
1805 *
1806 * @test
1807 */
1808 public function getDataWithTypeFileReturnsUidOfFileObject() {
1809 $uid = $this->getUniqueId();
1810 $file = $this->getMock(\TYPO3\CMS\Core\Resource\File::class, array(), array(), '', FALSE);
1811 $file->expects($this->once())->method('getUid')->will($this->returnValue($uid));
1812 $this->subject->setCurrentFile($file);
1813 $this->assertEquals($uid, $this->subject->getData('file:current:uid'));
1814 }
1815
1816 /**
1817 * Checks if getData() works with type "parameters"
1818 *
1819 * @test
1820 */
1821 public function getDataWithTypeParameters() {
1822 $key = $this->getUniqueId('someKey');
1823 $value = $this->getUniqueId('someValue');
1824 $this->subject->parameters[$key] = $value;
1825
1826 $this->assertEquals($value, $this->subject->getData('parameters:' . $key));
1827 }
1828
1829 /**
1830 * Checks if getData() works with type "register"
1831 *
1832 * @test
1833 */
1834 public function getDataWithTypeRegister() {
1835 $key = $this->getUniqueId('someKey');
1836 $value = $this->getUniqueId('someValue');
1837 $GLOBALS['TSFE']->register[$key] = $value;
1838
1839 $this->assertEquals($value, $this->subject->getData('register:' . $key));
1840 }
1841
1842 /**
1843 * Checks if getData() works with type "level"
1844 *
1845 * @test
1846 */
1847 public function getDataWithTypeLevel() {
1848 $rootline = array(
1849 0 => array('uid' => 1, 'title' => 'title1'),
1850 1 => array('uid' => 2, 'title' => 'title2'),
1851 2 => array('uid' => 3, 'title' => 'title3'),
1852 );
1853
1854 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1855 $this->assertEquals(2, $this->subject->getData('level'));
1856 }
1857
1858 /**
1859 * Checks if getData() works with type "global"
1860 *
1861 * @test
1862 */
1863 public function getDataWithTypeGlobal() {
1864 $this->assertEquals($GLOBALS['TSFE']->renderCharset, $this->subject->getData('global:TSFE|renderCharset'));
1865 }
1866
1867 /**
1868 * Checks if getData() works with type "leveltitle"
1869 *
1870 * @test
1871 */
1872 public function getDataWithTypeLeveltitle() {
1873 $rootline = array(
1874 0 => array('uid' => 1, 'title' => 'title1'),
1875 1 => array('uid' => 2, 'title' => 'title2'),
1876 2 => array('uid' => 3, 'title' => ''),
1877 );
1878
1879 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1880 $this->assertEquals('', $this->subject->getData('leveltitle:-1'));
1881 // since "title3" is not set, it will slide to "title2"
1882 $this->assertEquals('title2', $this->subject->getData('leveltitle:-1,slide'));
1883 }
1884
1885 /**
1886 * Checks if getData() works with type "levelmedia"
1887 *
1888 * @test
1889 */
1890 public function getDataWithTypeLevelmedia() {
1891 $rootline = array(
1892 0 => array('uid' => 1, 'title' => 'title1', 'media' => 'media1'),
1893 1 => array('uid' => 2, 'title' => 'title2', 'media' => 'media2'),
1894 2 => array('uid' => 3, 'title' => 'title3', 'media' => ''),
1895 );
1896
1897 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1898 $this->assertEquals('', $this->subject->getData('levelmedia:-1'));
1899 // since "title3" is not set, it will slide to "title2"
1900 $this->assertEquals('media2', $this->subject->getData('levelmedia:-1,slide'));
1901 }
1902
1903 /**
1904 * Checks if getData() works with type "leveluid"
1905 *
1906 * @test
1907 */
1908 public function getDataWithTypeLeveluid() {
1909 $rootline = array(
1910 0 => array('uid' => 1, 'title' => 'title1'),
1911 1 => array('uid' => 2, 'title' => 'title2'),
1912 2 => array('uid' => 3, 'title' => 'title3'),
1913 );
1914
1915 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1916 $this->assertEquals(3, $this->subject->getData('leveluid:-1'));
1917 // every element will have a uid - so adding slide doesn't really make sense, just for completeness
1918 $this->assertEquals(3, $this->subject->getData('leveluid:-1,slide'));
1919 }
1920
1921 /**
1922 * Checks if getData() works with type "levelfield"
1923 *
1924 * @test
1925 */
1926 public function getDataWithTypeLevelfield() {
1927 $rootline = array(
1928 0 => array('uid' => 1, 'title' => 'title1', 'testfield' => 'field1'),
1929 1 => array('uid' => 2, 'title' => 'title2', 'testfield' => 'field2'),
1930 2 => array('uid' => 3, 'title' => 'title3', 'testfield' => ''),
1931 );
1932
1933 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
1934 $this->assertEquals('', $this->subject->getData('levelfield:-1,testfield'));
1935 $this->assertEquals('field2', $this->subject->getData('levelfield:-1,testfield,slide'));
1936 }
1937
1938 /**
1939 * Checks if getData() works with type "fullrootline"
1940 *
1941 * @test
1942 */
1943 public function getDataWithTypeFullrootline() {
1944 $rootline1 = array(
1945 0 => array('uid' => 1, 'title' => 'title1', 'testfield' => 'field1'),
1946 );
1947 $rootline2 = array(
1948 0 => array('uid' => 1, 'title' => 'title1', 'testfield' => 'field1'),
1949 1 => array('uid' => 2, 'title' => 'title2', 'testfield' => 'field2'),
1950 2 => array('uid' => 3, 'title' => 'title3', 'testfield' => 'field3'),
1951 );
1952
1953 $GLOBALS['TSFE']->tmpl->rootLine = $rootline1;
1954 $GLOBALS['TSFE']->rootLine = $rootline2;
1955 $this->assertEquals('field2', $this->subject->getData('fullrootline:-1,testfield'));
1956 }
1957
1958 /**
1959 * Checks if getData() works with type "date"
1960 *
1961 * @test
1962 */
1963 public function getDataWithTypeDate() {
1964 $format = 'Y-M-D';
1965 $defaultFormat = 'd/m Y';
1966
1967 $this->assertEquals(date($format, $GLOBALS['EXEC_TIME']), $this->subject->getData('date:' . $format));
1968 $this->assertEquals(date($defaultFormat, $GLOBALS['EXEC_TIME']), $this->subject->getData('date'));
1969 }
1970
1971 /**
1972 * Checks if getData() works with type "page"
1973 *
1974 * @test
1975 */
1976 public function getDataWithTypePage() {
1977 $uid = rand();
1978 $GLOBALS['TSFE']->page['uid'] = $uid;
1979 $this->assertEquals($uid, $this->subject->getData('page:uid'));
1980 }
1981
1982 /**
1983 * Checks if getData() works with type "current"
1984 *
1985 * @test
1986 */
1987 public function getDataWithTypeCurrent() {
1988 $key = $this->getUniqueId('someKey');
1989 $value = $this->getUniqueId('someValue');
1990 $this->subject->data[$key] = $value;
1991 $this->subject->currentValKey = $key;
1992 $this->assertEquals($value, $this->subject->getData('current'));
1993 }
1994
1995 /**
1996 * Checks if getData() works with type "db"
1997 *
1998 * @test
1999 */
2000 public function getDataWithTypeDb() {
2001 $dummyRecord = array('uid' => 5, 'title' => 'someTitle');
2002
2003 $GLOBALS['TSFE']->sys_page->expects($this->atLeastOnce())->method('getRawRecord')->with('tt_content', '106')->will($this->returnValue($dummyRecord));
2004 $this->assertEquals($dummyRecord['title'], $this->subject->getData('db:tt_content:106:title'));
2005 }
2006
2007 /**
2008 * Checks if getData() works with type "lll"
2009 *
2010 * @test
2011 */
2012 public function getDataWithTypeLll() {
2013 $key = $this->getUniqueId('someKey');
2014 $value = $this->getUniqueId('someValue');
2015 $language = $this->getUniqueId('someLanguage');
2016 $GLOBALS['TSFE']->LL_labels_cache[$language]['LLL:' . $key] = $value;
2017 $GLOBALS['TSFE']->lang = $language;
2018
2019 $this->assertEquals($value, $this->subject->getData('lll:' . $key));
2020 }
2021
2022 /**
2023 * Checks if getData() works with type "path"
2024 *
2025 * @test
2026 */
2027 public function getDataWithTypePath() {
2028 $filenameIn = $this->getUniqueId('someValue');
2029 $filenameOut = $this->getUniqueId('someValue');
2030 $this->templateServiceMock->expects($this->atLeastOnce())->method('getFileName')->with($filenameIn)->will($this->returnValue($filenameOut));
2031 $this->assertEquals($filenameOut, $this->subject->getData('path:' . $filenameIn));
2032 }
2033
2034 /**
2035 * Checks if getData() works with type "parentRecordNumber"
2036 *
2037 * @test
2038 */
2039 public function getDataWithTypeParentRecordNumber() {
2040 $recordNumber = rand();
2041 $this->subject->parentRecordNumber = $recordNumber;
2042 $this->assertEquals($recordNumber, $this->subject->getData('cobj:parentRecordNumber'));
2043 }
2044
2045 /**
2046 * Checks if getData() works with type "debug:rootLine"
2047 *
2048 * @test
2049 */
2050 public function getDataWithTypeDebugRootline() {
2051 $rootline = array(
2052 0 => array('uid' => 1, 'title' => 'title1'),
2053 1 => array('uid' => 2, 'title' => 'title2'),
2054 2 => array('uid' => 3, 'title' => ''),
2055 );
2056 $expectedResult = '0uid1titletitle11uid2titletitle22uid3title';
2057 $GLOBALS['TSFE']->tmpl->rootLine = $rootline;
2058
2059 $result = $this->subject->getData('debug:rootLine');
2060 $cleanedResult = strip_tags($result);
2061 $cleanedResult = str_replace("\r", '', $cleanedResult);
2062 $cleanedResult = str_replace("\n", '', $cleanedResult);
2063 $cleanedResult = str_replace("\t", '', $cleanedResult);
2064 $cleanedResult = str_replace(' ', '', $cleanedResult);
2065
2066 $this->assertEquals($expectedResult, $cleanedResult);
2067 }
2068
2069 /**
2070 * Checks if getData() works with type "debug:fullRootLine"
2071 *
2072 * @test
2073 */
2074 public function getDataWithTypeDebugFullRootline() {
2075 $rootline = array(
2076 0 => array('uid' => 1, 'title' => 'title1'),
2077 1 => array('uid' => 2, 'title' => 'title2'),
2078 2 => array('uid' => 3, 'title' => ''),
2079 );
2080 $expectedResult = '0uid1titletitle11uid2titletitle22uid3title';
2081 $GLOBALS['TSFE']->rootLine = $rootline;
2082
2083 $result = $this->subject->getData('debug:fullRootLine');
2084 $cleanedResult = strip_tags($result);
2085 $cleanedResult = str_replace("\r", '', $cleanedResult);
2086 $cleanedResult = str_replace("\n", '', $cleanedResult);
2087 $cleanedResult = str_replace("\t", '', $cleanedResult);
2088 $cleanedResult = str_replace(' ', '', $cleanedResult);
2089
2090 $this->assertEquals($expectedResult, $cleanedResult);
2091 }
2092
2093 /**
2094 * Checks if getData() works with type "debug:data"
2095 *
2096 * @test
2097 */
2098 public function getDataWithTypeDebugData() {
2099 $key = $this->getUniqueId('someKey');
2100 $value = $this->getUniqueId('someValue');
2101 $this->subject->data = array($key => $value);
2102
2103 $expectedResult = $key . $value;
2104
2105 $result = $this->subject->getData('debug:data');
2106 $cleanedResult = strip_tags($result);
2107 $cleanedResult = str_replace("\r", '', $cleanedResult);
2108 $cleanedResult = str_replace("\n", '', $cleanedResult);
2109 $cleanedResult = str_replace("\t", '', $cleanedResult);
2110 $cleanedResult = str_replace(' ', '', $cleanedResult);
2111
2112 $this->assertEquals($expectedResult, $cleanedResult);
2113 }
2114
2115 /**
2116 * Checks if getData() works with type "debug:register"
2117 *
2118 * @test
2119 */
2120 public function getDataWithTypeDebugRegister() {
2121 $key = $this->getUniqueId('someKey');
2122 $value = $this->getUniqueId('someValue');
2123 $GLOBALS['TSFE']->register = array($key => $value);
2124
2125 $expectedResult = $key . $value;
2126
2127 $result = $this->subject->getData('debug:register');
2128 $cleanedResult = strip_tags($result);
2129 $cleanedResult = str_replace("\r", '', $cleanedResult);
2130 $cleanedResult = str_replace("\n", '', $cleanedResult);
2131 $cleanedResult = str_replace("\t", '', $cleanedResult);
2132 $cleanedResult = str_replace(' ', '', $cleanedResult);
2133
2134 $this->assertEquals($expectedResult, $cleanedResult);
2135 }
2136
2137 /**
2138 * Checks if getData() works with type "data:page"
2139 *
2140 * @test
2141 */
2142 public function getDataWithTypeDebugPage() {
2143 $uid = rand();
2144 $GLOBALS['TSFE']->page = array('uid' => $uid);
2145
2146 $expectedResult = 'uid' . $uid;
2147
2148 $result = $this->subject->getData('debug:page');
2149 $cleanedResult = strip_tags($result);
2150 $cleanedResult = str_replace("\r", '', $cleanedResult);
2151 $cleanedResult = str_replace("\n", '', $cleanedResult);
2152 $cleanedResult = str_replace("\t", '', $cleanedResult);
2153 $cleanedResult = str_replace(' ', '', $cleanedResult);
2154
2155 $this->assertEquals($expectedResult, $cleanedResult);
2156 }
2157
2158 /**
2159 * @test
2160 */
2161 public function getTreeListReturnsChildPageUids() {
2162 $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetSingleRow')->with('treelist')->will($this->returnValue(NULL));
2163 $GLOBALS['TSFE']->sys_page
2164 ->expects($this->any())
2165 ->method('getRawRecord')
2166 ->will(
2167 $this->onConsecutiveCalls(
2168 array('uid' => 17),
2169 array('uid' => 321),
2170 array('uid' => 719),
2171 array('uid' => 42)
2172 )
2173 );
2174
2175 $GLOBALS['TSFE']->sys_page->expects($this->any())->method('getMountPointInfo')->will($this->returnValue(NULL));
2176 $GLOBALS['TYPO3_DB']
2177 ->expects($this->any())
2178 ->method('exec_SELECTgetRows')
2179 ->will(
2180 $this->onConsecutiveCalls(
2181 array(
2182 array('uid' => 321)
2183 ),
2184 array(
2185 array('uid' => 719)
2186 ),
2187 array(
2188 array('uid' => 42)
2189 )
2190 )
2191 );
2192 // 17 = pageId, 5 = recursionLevel, 0 = begin (entry to recursion, internal), TRUE = do not check enable fields
2193 // 17 is positive, we expect 17 NOT to be included in result
2194 $result = $this->subject->getTreeList(17, 5, 0, TRUE);
2195 $expectedResult = '42,719,321';
2196 $this->assertEquals($expectedResult, $result);
2197 }
2198
2199 /**
2200 * @test
2201 */
2202 public function getTreeListReturnsChildPageUidsAndOriginalPidForNegativeValue() {
2203 $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetSingleRow')->with('treelist')->will($this->returnValue(NULL));
2204 $GLOBALS['TSFE']->sys_page
2205 ->expects($this->any())
2206 ->method('getRawRecord')
2207 ->will(
2208 $this->onConsecutiveCalls(
2209 array('uid' => 17),
2210 array('uid' => 321),
2211 array('uid' => 719),
2212 array('uid' => 42)
2213 )
2214 );
2215
2216 $GLOBALS['TSFE']->sys_page->expects($this->any())->method('getMountPointInfo')->will($this->returnValue(NULL));
2217 $GLOBALS['TYPO3_DB']
2218 ->expects($this->any())
2219 ->method('exec_SELECTgetRows')
2220 ->will(
2221 $this->onConsecutiveCalls(
2222 array(
2223 array('uid' => 321)
2224 ),
2225 array(
2226 array('uid' => 719)
2227 ),
2228 array(
2229 array('uid' => 42)
2230 )
2231 )
2232 );
2233 // 17 = pageId, 5 = recursionLevel, 0 = begin (entry to recursion, internal), TRUE = do not check enable fields
2234 // 17 is negative, we expect 17 to be included in result
2235 $result = $this->subject->getTreeList(-17, 5, 0, TRUE);
2236 $expectedResult = '42,719,321,17';
2237 $this->assertEquals($expectedResult, $result);
2238 }
2239
2240 /**
2241 * @test
2242 */
2243 public function aTagParamsHasLeadingSpaceIfNotEmpty() {
2244 $aTagParams = $this->subject->getATagParams(array('ATagParams' => 'data-test="testdata"'));
2245 $this->assertEquals(' data-test="testdata"', $aTagParams );
2246 }
2247
2248 /**
2249 * @test
2250 */
2251 public function aTagParamsHaveSpaceBetweenLocalAndGlobalParams() {
2252 $GLOBALS['TSFE']->ATagParams = 'data-global="dataglobal"';
2253 $aTagParams = $this->subject->getATagParams(array('ATagParams' => 'data-test="testdata"'));
2254 $this->assertEquals(' data-global="dataglobal" data-test="testdata"', $aTagParams );
2255 }
2256
2257 /**
2258 * @test
2259 */
2260 public function aTagParamsHasNoLeadingSpaceIfEmpty() {
2261 // make sure global ATagParams are empty
2262 $GLOBALS['TSFE']->ATagParams = '';
2263 $aTagParams = $this->subject->getATagParams(array('ATagParams' => ''));
2264 $this->assertEquals('', $aTagParams);
2265 }
2266
2267 /**
2268 * @return array
2269 */
2270 public function getImageTagTemplateFallsBackToDefaultTemplateIfNoTemplateIsFoundDataProvider() {
2271 return array(
2272 array(NULL, NULL),
2273 array('', NULL),
2274 array('', array()),
2275 array('fooo', array('foo' => 'bar'))
2276 );
2277 }
2278
2279 /**
2280 * Make sure that the rendering falls back to the classic <img style if nothing else is found
2281 *
2282 * @test
2283 * @dataProvider getImageTagTemplateFallsBackToDefaultTemplateIfNoTemplateIsFoundDataProvider
2284 * @param string $key
2285 * @param array $configuration
2286 */
2287 public function getImageTagTemplateFallsBackToDefaultTemplateIfNoTemplateIsFound($key, $configuration) {
2288 $defaultImgTagTemplate = '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>';
2289 $result = $this->subject->getImageTagTemplate($key, $configuration);
2290 $this->assertEquals($result, $defaultImgTagTemplate);
2291 }
2292
2293 /**
2294 * @return array
2295 */
2296 public function getImageTagTemplateReturnTemplateElementIdentifiedByKeyDataProvider() {
2297 return array(
2298 array(
2299 'foo',
2300 array(
2301 'layout.' => array(
2302 'foo.' => array(
2303 'element' => '<img src="###SRC###" srcset="###SOURCES###" ###PARAMS### ###ALTPARAMS### ###FOOBAR######SELFCLOSINGTAGSLASH###>'
2304 )
2305 )
2306 ),
2307 '<img src="###SRC###" srcset="###SOURCES###" ###PARAMS### ###ALTPARAMS### ###FOOBAR######SELFCLOSINGTAGSLASH###>'
2308 )
2309
2310 );
2311 }
2312
2313 /**
2314 * Assure if a layoutKey and layout is given the selected layout is returned
2315 *
2316 * @test
2317 * @dataProvider getImageTagTemplateReturnTemplateElementIdentifiedByKeyDataProvider
2318 * @param string $key
2319 * @param array $configuration
2320 * @param string $expectation
2321 */
2322 public function getImageTagTemplateReturnTemplateElementIdentifiedByKey($key, $configuration, $expectation) {
2323 $result = $this->subject->getImageTagTemplate($key, $configuration);
2324 $this->assertEquals($result, $expectation);
2325 }
2326
2327 /**
2328 * @return array
2329 */
2330 public function getImageSourceCollectionReturnsEmptyStringIfNoSourcesAreDefinedDataProvider() {
2331 return array(
2332 array(NULL, NULL, NULL),
2333 array('foo', NULL, NULL),
2334 array('foo', array('sourceCollection.' => 1), 'bar')
2335 );
2336 }
2337
2338 /**
2339 * Make sure the source collection is empty if no valid configuration or source collection is defined
2340 *
2341 * @test
2342 * @dataProvider getImageSourceCollectionReturnsEmptyStringIfNoSourcesAreDefinedDataProvider
2343 * @param string $layoutKey
2344 * @param array $configuration
2345 * @param string $file
2346 */
2347 public function getImageSourceCollectionReturnsEmptyStringIfNoSourcesAreDefined($layoutKey, $configuration, $file) {
2348 $result = $this->subject->getImageSourceCollection($layoutKey, $configuration, $file);
2349 $this->assertSame($result, '');
2350 }
2351
2352 /**
2353 * Make sure the generation of subimages calls the generation of the subimages and uses the layout -> source template
2354 *
2355 * @test
2356 */
2357 public function getImageSourceCollectionRendersDefinedSources() {
2358 /** @var $cObj \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer */
2359 $cObj = $this->getMock(
2360 \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
2361 array('stdWrap','getImgResource')
2362 );
2363 $cObj->start(array(), 'tt_content');
2364
2365 $layoutKey = 'test';
2366
2367 $configuration = array(
2368 'layoutKey' => 'test',
2369 'layout.' => array (
2370 'test.' => array(
2371 'element' => '<img ###SRC### ###SRCCOLLECTION### ###SELFCLOSINGTAGSLASH###>',
2372 'source' => '---###SRC###---'
2373 )
2374 ),
2375 'sourceCollection.' => array(
2376 '1.' => array(
2377 'width' => '200'
2378 )
2379 )
2380 );
2381
2382 $file = 'testImageName';
2383
2384 // Avoid calling of stdWrap
2385 $cObj
2386 ->expects($this->any())
2387 ->method('stdWrap')
2388 ->will($this->returnArgument(0));
2389
2390 // Avoid calling of imgResource
2391 $cObj
2392 ->expects($this->exactly(1))
2393 ->method('getImgResource')
2394 ->with($this->equalTo('testImageName'))
2395 ->will($this->returnValue(array(100, 100, NULL, 'bar')));
2396
2397 $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
2398
2399 $this->assertEquals('---bar---', $result);
2400 }
2401
2402 /**
2403 * Data provider for the getImageSourceCollectionRendersDefinedLayoutKeyDefault test
2404 *
2405 * @return array multi-dimensional array with the second level like this:
2406 * @see getImageSourceCollectionRendersDefinedLayoutKeyDefault
2407 */
2408 public function getImageSourceCollectionRendersDefinedLayoutKeyDataDefaultProvider() {
2409 /**
2410 * @see css_styled_content/static/setup.txt
2411 */
2412 $sourceCollectionArray = array(
2413 'small.' => array(
2414 'width' => '200',
2415 'srcsetCandidate' => '600w',
2416 'mediaQuery' => '(max-device-width: 600px)',
2417 'dataKey' => 'small',
2418 ),
2419 'smallRetina.' => array(
2420 'if.directReturn' => 0,
2421 'width' => '200',
2422 'pixelDensity' => '2',
2423 'srcsetCandidate' => '600w 2x',
2424 'mediaQuery' => '(max-device-width: 600px) AND (min-resolution: 192dpi)',
2425 'dataKey' => 'smallRetina',
2426 )
2427 );
2428 return array(
2429 array(
2430 'default',
2431 array(
2432 'layoutKey' => 'default',
2433 'layout.' => array (
2434 'default.' => array(
2435 'element' => '<img src="###SRC###" width="###WIDTH###" height="###HEIGHT###" ###PARAMS### ###ALTPARAMS### ###BORDER######SELFCLOSINGTAGSLASH###>',
2436 'source' => ''
2437 )
2438 ),
2439 'sourceCollection.' => $sourceCollectionArray
2440 )
2441 ),
2442 );
2443 }
2444
2445 /**
2446 * Make sure the generation of subimages renders the expected HTML Code for the sourceset
2447 *
2448 * @test
2449 * @dataProvider getImageSourceCollectionRendersDefinedLayoutKeyDataDefaultProvider
2450 * @param string $layoutKey
2451 * @param array $configuration
2452 */
2453 public function getImageSourceCollectionRendersDefinedLayoutKeyDefault($layoutKey , $configuration) {
2454 /** @var $cObj \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer */
2455 $cObj = $this->getMock(
2456 \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
2457 array('stdWrap','getImgResource')
2458 );
2459 $cObj->start(array(), 'tt_content');
2460
2461 $file = 'testImageName';
2462
2463 // Avoid calling of stdWrap
2464 $cObj
2465 ->expects($this->any())
2466 ->method('stdWrap')
2467 ->will($this->returnArgument(0));
2468
2469 $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
2470
2471 $this->assertEmpty($result);
2472 }
2473
2474 /**
2475 * Data provider for the getImageSourceCollectionRendersDefinedLayoutKeyData test
2476 *
2477 * @return array multi-dimensional array with the second level like this:
2478 * @see getImageSourceCollectionRendersDefinedLayoutKeyData
2479 */
2480 public function getImageSourceCollectionRendersDefinedLayoutKeyDataDataProvider() {
2481 /**
2482 * @see css_styled_content/static/setup.txt
2483 */
2484 $sourceCollectionArray = array(
2485 'small.' => array(
2486 'width' => '200',
2487 'srcsetCandidate' => '600w',
2488 'mediaQuery' => '(max-device-width: 600px)',
2489 'dataKey' => 'small',
2490 ),
2491 'smallRetina.' => array(
2492 'if.directReturn' => 1,
2493 'width' => '200',
2494 'pixelDensity' => '2',
2495 'srcsetCandidate' => '600w 2x',
2496 'mediaQuery' => '(max-device-width: 600px) AND (min-resolution: 192dpi)',
2497 'dataKey' => 'smallRetina',
2498 )
2499 );
2500 return array(
2501 array(
2502 'srcset',
2503 array(
2504 'layoutKey' => 'srcset',
2505 'layout.' => array (
2506 'srcset.' => array(
2507 'element' => '<img src="###SRC###" srcset="###SOURCECOLLECTION###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
2508 'source' => '|*|###SRC### ###SRCSETCANDIDATE###,|*|###SRC### ###SRCSETCANDIDATE###'
2509 )
2510 ),
2511 'sourceCollection.' => $sourceCollectionArray
2512 ),
2513 'xhtml_strict',
2514 'bar-file.jpg 600w,bar-file.jpg 600w 2x',
2515 ),
2516 array(
2517 'picture',
2518 array(
2519 'layoutKey' => 'picture',
2520 'layout.' => array (
2521 'picture.' => array(
2522 'element' => '<picture>###SOURCECOLLECTION###<img src="###SRC###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###></picture>',
2523 'source' => '<source src="###SRC###" media="###MEDIAQUERY###"###SELFCLOSINGTAGSLASH###>'
2524 )
2525 ),
2526 'sourceCollection.' => $sourceCollectionArray,
2527 ),
2528 'xhtml_strict',
2529 '<source src="bar-file.jpg" media="(max-device-width: 600px)" /><source src="bar-file.jpg" media="(max-device-width: 600px) AND (min-resolution: 192dpi)" />',
2530 ),
2531 array(
2532 'picture',
2533 array(
2534 'layoutKey' => 'picture',
2535 'layout.' => array (
2536 'picture.' => array(
2537 'element' => '<picture>###SOURCECOLLECTION###<img src="###SRC###" ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###></picture>',
2538 'source' => '<source src="###SRC###" media="###MEDIAQUERY###"###SELFCLOSINGTAGSLASH###>'
2539 )
2540 ),
2541 'sourceCollection.' => $sourceCollectionArray,
2542 ),
2543 '',
2544 '<source src="bar-file.jpg" media="(max-device-width: 600px)"><source src="bar-file.jpg" media="(max-device-width: 600px) AND (min-resolution: 192dpi)">',
2545 ),
2546 array(
2547 'data',
2548 array(
2549 'layoutKey' => 'data',
2550 'layout.' => array (
2551 'data.' => array(
2552 'element' => '<img src="###SRC###" ###SOURCECOLLECTION### ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
2553 'source' => 'data-###DATAKEY###="###SRC###"'
2554 )
2555 ),
2556 'sourceCollection.' => $sourceCollectionArray
2557 ),
2558 'xhtml_strict',
2559 'data-small="bar-file.jpg"data-smallRetina="bar-file.jpg"',
2560 ),
2561 );
2562 }
2563
2564 /**
2565 * Make sure the generation of subimages renders the expected HTML Code for the sourceset
2566 *
2567 * @test
2568 * @dataProvider getImageSourceCollectionRendersDefinedLayoutKeyDataDataProvider
2569 * @param string $layoutKey
2570 * @param array $configuration
2571 * @param string $xhtmlDoctype
2572 * @param string $expectedHtml
2573 */
2574 public function getImageSourceCollectionRendersDefinedLayoutKeyData($layoutKey , $configuration, $xhtmlDoctype, $expectedHtml) {
2575 /** @var $cObj \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer */
2576 $cObj = $this->getMock(
2577 \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
2578 array('stdWrap','getImgResource')
2579 );
2580 $cObj->start(array(), 'tt_content');
2581
2582 $file = 'testImageName';
2583
2584 $GLOBALS['TSFE']->xhtmlDoctype = $xhtmlDoctype;
2585
2586 // Avoid calling of stdWrap
2587 $cObj
2588 ->expects($this->any())
2589 ->method('stdWrap')
2590 ->will($this->returnArgument(0));
2591
2592 // Avoid calling of imgResource
2593 $cObj
2594 ->expects($this->exactly(2))
2595 ->method('getImgResource')
2596 ->with($this->equalTo('testImageName'))
2597 ->will($this->returnValue(array(100, 100, NULL, 'bar-file.jpg')));
2598
2599 $result = $cObj->getImageSourceCollection($layoutKey, $configuration, $file);
2600
2601 $this->assertEquals($expectedHtml, $result);
2602 }
2603
2604 /**
2605 * Make sure the hook in get sourceCollection is called
2606 *
2607 * @test
2608 */
2609 public function getImageSourceCollectionHookCalled() {
2610 $this->subject = $this->getAccessibleMock(
2611 \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
2612 array('getResourceFactory', 'stdWrap', 'getImgResource')
2613 );
2614 $this->subject->start(array(), 'tt_content');
2615
2616 // Avoid calling stdwrap and getImgResource
2617 $this->subject->expects($this->any())
2618 ->method('stdWrap')
2619 ->will($this->returnArgument(0));
2620
2621 $this->subject->expects($this->any())
2622 ->method('getImgResource')
2623 ->will($this->returnValue(array(100, 100, NULL, 'bar-file.jpg')));
2624
2625 $resourceFactory = $this->getMock(\TYPO3\CMS\Core\Resource\ResourceFactory::class, array(), array(), '', FALSE);
2626 $this->subject->expects($this->any())->method('getResourceFactory')->will($this->returnValue($resourceFactory));
2627
2628 $className = $this->getUniqueId('tx_coretest_getImageSourceCollectionHookCalled');
2629 $getImageSourceCollectionHookMock = $this->getMock(\TYPO3\CMS\Frontend\ContentObject\ContentObjectOneSourceCollectionHookInterface::class, array('getOneSourceCollection'), array(), $className);
2630 $GLOBALS['T3_VAR']['getUserObj'][$className] = $getImageSourceCollectionHookMock;
2631 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_content.php']['getImageSourceCollection'][] = $className;
2632
2633 $getImageSourceCollectionHookMock
2634 ->expects($this->exactly(1))
2635 ->method('getOneSourceCollection')
2636 ->will($this->returnCallback(array($this, 'isGetOneSourceCollectionCalledCallback')));
2637
2638 $configuration = array(
2639 'layoutKey' => 'data',
2640 'layout.' => array (
2641 'data.' => array(
2642 'element' => '<img src="###SRC###" ###SOURCECOLLECTION### ###PARAMS### ###ALTPARAMS######SELFCLOSINGTAGSLASH###>',
2643 'source' => 'data-###DATAKEY###="###SRC###"'
2644 )
2645 ),
2646 'sourceCollection.' => array(
2647 'small.' => array(
2648 'width' => '200',
2649 'srcsetCandidate' => '600w',
2650 'mediaQuery' => '(max-device-width: 600px)',
2651 'dataKey' => 'small',
2652 ),
2653 ),
2654 );
2655
2656 $result = $this->subject->getImageSourceCollection('data', $configuration, $this->getUniqueId('testImage-'));
2657
2658 $this->assertSame($result, 'isGetOneSourceCollectionCalledCallback');
2659 }
2660
2661 /**
2662 * Handles the arguments that have been sent to the getImgResource hook.
2663 *
2664 * @return string
2665 * @see getImageSourceCollectionHookCalled
2666 */
2667 public function isGetOneSourceCollectionCalledCallback() {
2668 list($sourceRenderConfiguration, $sourceConfiguration, $oneSourceCollection, $parent) = func_get_args();
2669 $this->assertTrue(is_array($sourceRenderConfiguration));
2670 $this->assertTrue(is_array($sourceConfiguration));
2671 return 'isGetOneSourceCollectionCalledCallback';
2672 }
2673
2674 /**
2675 * @param string $expected The expected URL
2676 * @param string $url The URL to parse and manipulate
2677 * @param array $configuration The configuration array
2678 * @test
2679 * @dataProvider forceAbsoluteUrlReturnsCorrectAbsoluteUrlDataProvider
2680 */
2681 public function forceAbsoluteUrlReturnsCorrectAbsoluteUrl($expected, $url, array $configuration) {
2682 // Force hostname
2683 $this->subject->expects($this->any())->method('getEnvironmentVariable')->will($this->returnValueMap(
2684 array(
2685 array('HTTP_HOST', 'localhost'),
2686 array('TYPO3_SITE_PATH', '/'),
2687 )
2688 ));
2689 $GLOBALS['TSFE']->absRefPrefix = '';
2690
2691 $this->assertEquals($expected, $this->subject->_call('forceAbsoluteUrl', $url, $configuration));
2692 }
2693
2694 /**
2695 * @return array The test data for forceAbsoluteUrlReturnsAbsoluteUrl
2696 */
2697 public function forceAbsoluteUrlReturnsCorrectAbsoluteUrlDataProvider() {
2698 return array(
2699 'Missing forceAbsoluteUrl leaves URL untouched' => array(
2700 'foo',
2701 'foo',
2702 array()
2703 ),
2704 'Absolute URL stays unchanged' => array(
2705 'http://example.org/',
2706 'http://example.org/',
2707 array(
2708 'forceAbsoluteUrl' => '1'
2709 )
2710 ),
2711 'Absolute URL stays unchanged 2' => array(
2712 'http://example.org/resource.html',
2713 'http://example.org/resource.html',
2714 array(
2715 'forceAbsoluteUrl' => '1'
2716 )
2717 ),
2718 'Scheme and host w/o ending slash stays unchanged' => array(
2719 'http://example.org',
2720 'http://example.org',
2721 array(
2722 'forceAbsoluteUrl' => '1'
2723 )
2724 ),
2725 'Scheme can be forced' => array(
2726 'typo3://example.org',
2727 'http://example.org',
2728 array(
2729 'forceAbsoluteUrl' => '1',
2730 'forceAbsoluteUrl.' => array(
2731 'scheme' => 'typo3'
2732 )
2733 )
2734 ),
2735 'Relative path old-style' => array(
2736 'http://localhost/fileadmin/dummy.txt',
2737 '/fileadmin/dummy.txt',
2738 array(
2739 'forceAbsoluteUrl' => '1',
2740 )
2741 ),
2742 'Relative path' => array(
2743 'http://localhost/fileadmin/dummy.txt',
2744 'fileadmin/dummy.txt',
2745 array(
2746 'forceAbsoluteUrl' => '1',
2747 )
2748 ),
2749 'Scheme can be forced with pseudo-relative path' => array(
2750 'typo3://localhost/fileadmin/dummy.txt',
2751 '/fileadmin/dummy.txt',
2752 array(
2753 'forceAbsoluteUrl' => '1',
2754 'forceAbsoluteUrl.' => array(
2755 'scheme' => 'typo3'
2756 )
2757 )
2758 ),
2759 'Hostname only is not treated as valid absolute URL' => array(
2760 'http://localhost/example.org',
2761 'example.org',
2762 array(
2763 'forceAbsoluteUrl' => '1'
2764 )
2765 ),
2766 'Scheme and host is added to local file path' => array(
2767 'typo3://localhost/fileadmin/my.pdf',
2768 'fileadmin/my.pdf',
2769 array(
2770 'forceAbsoluteUrl' => '1',
2771 'forceAbsoluteUrl.' => array(
2772 'scheme' => 'typo3'
2773 )
2774 )
2775 )
2776 );
2777 }
2778
2779 /**
2780 * @test
2781 * @expectedException \LogicException
2782 * @expectedExceptionCode 1414513947
2783 */
2784 public function renderingContentObjectThrowsException() {
2785 $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2786 $this->subject->render($contentObjectFixture, array());
2787 }
2788
2789 /**
2790 * @test
2791 */
2792 public function exceptionHandlerIsEnabledByDefaultInProductionContext() {
2793 $backupApplicationContext = GeneralUtility::getApplicationContext();
2794 Fixtures\GeneralUtilityFixture::setApplicationContext(new ApplicationContext('Production'));
2795
2796 $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2797 $this->subject->render($contentObjectFixture, array());
2798
2799 Fixtures\GeneralUtilityFixture::setApplicationContext($backupApplicationContext);
2800 }
2801
2802 /**
2803 * @test
2804 */
2805 public function renderingContentObjectDoesNotThrowExceptionIfExceptionHandlerIsConfiguredLocally() {
2806 $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2807
2808 $configuration = array(
2809 'exceptionHandler' => '1'
2810 );
2811 $this->subject->render($contentObjectFixture, $configuration);
2812 }
2813
2814 /**
2815 * @test
2816 */
2817 public function renderingContentObjectDoesNotThrowExceptionIfExceptionHandlerIsConfiguredGlobally() {
2818 $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2819
2820 $this->typoScriptFrontendControllerMock->config['config']['contentObjectExceptionHandler'] = '1';
2821 $this->subject->render($contentObjectFixture, array());
2822 }
2823
2824 /**
2825 * @test
2826 * @expectedException \LogicException
2827 * @expectedExceptionCode 1414513947
2828 */
2829 public function globalExceptionHandlerConfigurationCanBeOverriddenByLocalConfiguration() {
2830 $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2831
2832 $this->typoScriptFrontendControllerMock->config['config']['contentObjectExceptionHandler'] = '1';
2833 $configuration = array(
2834 'exceptionHandler' => '0'
2835 );
2836 $this->subject->render($contentObjectFixture, $configuration);
2837 }
2838
2839 /**
2840 * @test
2841 */
2842 public function renderedErrorMessageCanBeCustomized() {
2843 $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2844
2845 $configuration = array(
2846 'exceptionHandler' => '1',
2847 'exceptionHandler.' => array(
2848 'errorMessage' => 'New message for testing',
2849 )
2850 );
2851
2852 $this->assertSame('New message for testing', $this->subject->render($contentObjectFixture, $configuration));
2853 }
2854
2855 /**
2856 * @test
2857 */
2858 public function localConfigurationOverridesGlobalConfiguration() {
2859 $contentObjectFixture = $this->createContentObjectThrowingExceptionFixture();
2860
2861 $this->typoScriptFrontendControllerMock