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