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