f97b15100c3656f474e61caf394abeae6a6ce88e
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Tests / Unit / ContentObject / ContentObjectRendererTest.php
1 <?php
2 namespace TYPO3\CMS\Frontend\Tests\Unit\ContentObject;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Psr\Log\LoggerInterface;
18 use TYPO3\CMS\Core\Charset\CharsetConverter;
19 use TYPO3\CMS\Core\Core\ApplicationContext;
20 use TYPO3\CMS\Core\Log\LogManager;
21 use TYPO3\CMS\Core\TypoScript\TemplateService;
22 use TYPO3\CMS\Core\Utility\DebugUtility;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\CMS\Frontend\ContentObject\AbstractContentObject;
25 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
26 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
27 use TYPO3\CMS\Frontend\Tests\Unit\ContentObject\Fixtures\PageRepositoryFixture;
28 use TYPO3\CMS\Core\Cache\CacheManager;
29 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface as CacheFrontendInterface;
30
31 /**
32 * Testcase for TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
33 */
34 class ContentObjectRendererTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
35 {
36 /**
37 * @var string
38 */
39 protected $currentLocale;
40
41 /**
42 * @var array A backup of registered singleton instances
43 */
44 protected $singletonInstances = array();
45
46 /**
47 * @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface|\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
48 */
49 protected $subject = null;
50
51 /**
52 * @var \PHPUnit_Framework_MockObject_MockObject|TypoScriptFrontendController|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface
53 */
54 protected $typoScriptFrontendControllerMock = null;
55
56 /**
57 * @var \PHPUnit_Framework_MockObject_MockObject|TemplateService
58 */
59 protected $templateServiceMock = null;
60
61 /**
62 * Default content object name -> class name map, shipped with TYPO3 CMS
63 *
64 * @var array
65 */
66 protected $contentObjectMap = array(
67 'TEXT' => \TYPO3\CMS\Frontend\ContentObject\TextContentObject::class,
68 'CASE' => \TYPO3\CMS\Frontend\ContentObject\CaseContentObject::class,
69 'COBJ_ARRAY' => \TYPO3\CMS\Frontend\ContentObject\ContentObjectArrayContentObject::class,
70 'COA' => \TYPO3\CMS\Frontend\ContentObject\ContentObjectArrayContentObject::class,
71 'COA_INT' => \TYPO3\CMS\Frontend\ContentObject\ContentObjectArrayInternalContentObject::class,
72 'USER' => \TYPO3\CMS\Frontend\ContentObject\UserContentObject::class,
73 'USER_INT' => \TYPO3\CMS\Frontend\ContentObject\UserInternalContentObject::class,
74 'FILE' => \TYPO3\CMS\Frontend\ContentObject\FileContentObject::class,
75 'FILES' => \TYPO3\CMS\Frontend\ContentObject\FilesContentObject::class,
76 'IMAGE' => \TYPO3\CMS\Frontend\ContentObject\ImageContentObject::class,
77 'IMG_RESOURCE' => \TYPO3\CMS\Frontend\ContentObject\ImageResourceContentObject::class,
78 'CONTENT' => \TYPO3\CMS\Frontend\ContentObject\ContentContentObject::class,
79 'RECORDS' => \TYPO3\CMS\Frontend\ContentObject\RecordsContentObject::class,
80 'HMENU' => \TYPO3\CMS\Frontend\ContentObject\HierarchicalMenuContentObject::class,
81 'CASEFUNC' => \TYPO3\CMS\Frontend\ContentObject\CaseContentObject::class,
82 'LOAD_REGISTER' => \TYPO3\CMS\Frontend\ContentObject\LoadRegisterContentObject::class,
83 'RESTORE_REGISTER' => \TYPO3\CMS\Frontend\ContentObject\RestoreRegisterContentObject::class,
84 'TEMPLATE' => \TYPO3\CMS\Frontend\ContentObject\TemplateContentObject::class,
85 'FLUIDTEMPLATE' => \TYPO3\CMS\Frontend\ContentObject\FluidTemplateContentObject::class,
86 'SVG' => \TYPO3\CMS\Frontend\ContentObject\ScalableVectorGraphicsContentObject::class,
87 'EDITPANEL' => \TYPO3\CMS\Frontend\ContentObject\EditPanelContentObject::class
88 );
89
90 /**
91 * Set up
92 */
93 protected function setUp()
94 {
95 $this->currentLocale = setlocale(LC_NUMERIC, 0);
96
97 $this->singletonInstances = \TYPO3\CMS\Core\Utility\GeneralUtility::getSingletonInstances();
98 $this->createMockedLoggerAndLogManager();
99
100 $this->templateServiceMock = $this->getMockBuilder(TemplateService::class)
101 ->setMethods(array('getFileName', 'linkData'))
102 ->getMock();
103 $pageRepositoryMock = $this->getMockBuilder(PageRepositoryFixture::class)
104 ->setMethods(array('getRawRecord', 'getMountPointInfo'))
105 ->getMock();
106
107 $this->typoScriptFrontendControllerMock = $this->getAccessibleMock(TypoScriptFrontendController::class, array('dummy'), array(), '', false);
108 $this->typoScriptFrontendControllerMock->tmpl = $this->templateServiceMock;
109 $this->typoScriptFrontendControllerMock->config = array();
110 $this->typoScriptFrontendControllerMock->page = array();
111 $this->typoScriptFrontendControllerMock->sys_page = $pageRepositoryMock;
112 $GLOBALS['TSFE'] = $this->typoScriptFrontendControllerMock;
113 $GLOBALS['TYPO3_DB'] = $this->getMockBuilder(\TYPO3\CMS\Core\Database\DatabaseConnection::class)->getMock();
114
115 $this->subject = $this->getAccessibleMock(
116 \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class,
117 array('getResourceFactory', 'getEnvironmentVariable'),
118 array($this->typoScriptFrontendControllerMock)
119 );
120 $this->subject->setContentObjectClassMap($this->contentObjectMap);
121 $this->subject->start(array(), 'tt_content');
122 }
123
124 protected function tearDown()
125 {
126 setlocale(LC_NUMERIC, $this->currentLocale);
127 GeneralUtility::resetSingletonInstances($this->singletonInstances);
128 parent::tearDown();
129 }
130
131 //////////////////////
132 // Utility functions
133 //////////////////////
134
135 /**
136 * Avoid logging to the file system (file writer is currently the only configured writer)
137 */
138 protected function createMockedLoggerAndLogManager()
139 {
140 $logManagerMock = $this->getMockBuilder(LogManager::class)->getMock();
141 $loggerMock = $this->getMockBuilder(LoggerInterface::class)->getMock();
142 $logManagerMock->expects($this->any())
143 ->method('getLogger')
144 ->willReturn($loggerMock);
145 GeneralUtility::setSingletonInstance(LogManager::class, $logManagerMock);
146 }
147
148 /**
149 * Converts the subject and the expected result into utf-8.
150 *
151 * @param string $subject the subject, will be modified
152 * @param string $expected the expected result, will be modified
153 */
154 protected function handleCharset(&$subject, &$expected)
155 {
156 $charsetConverter = new CharsetConverter();
157 $subject = $charsetConverter->conv($subject, 'iso-8859-1', 'utf-8');
158 $expected = $charsetConverter->conv($expected, 'iso-8859-1', 'utf-8');
159 }
160
161 /////////////////////////////////////////////
162 // Tests concerning the getImgResource hook
163 /////////////////////////////////////////////
164 /**
165 * @test
166 */
167 public function getImgResourceCallsGetImgResourcePostProcessHook()
168 {
169 $this->templateServiceMock
170 ->expects($this->atLeastOnce())
171 ->method('getFileName')
172 ->with('typo3/clear.gif')
173 ->will($this->returnValue('typo3/clear.gif'));
174
175 $resourceFactory = $this->createMock(\TYPO3\CMS\Core\Resource\ResourceFactory::class);
176 $this->subject->expects($this->any())->method('getResourceFactory')->will($this->returnValue($resourceFactory));
177
178 $className = $this->getUniqueId('tx_coretest');
179 $getImgResourceHookMock = $this->getMockBuilder(\TYPO3\CMS\Frontend\ContentObject\ContentObjectGetImageResourceHookInterface::class)
180 ->setMethods(array('getImgResourcePostProcess'))
181 ->setMockClassName($className)
182 ->getMock();
183 $getImgResourceHookMock
184 ->expects($this->once())
185 ->method('getImgResourcePostProcess')
186 ->will($this->returnCallback(array($this, 'isGetImgResourceHookCalledCallback')));
187 $getImgResourceHookObjects = array($getImgResourceHookMock);
188 $this->subject->_setRef('getImgResourceHookObjects', $getImgResourceHookObjects);
189 $this->subject->getImgResource('typo3/clear.gif', array());
190 }
191
192 /**
193 * Handles the arguments that have been sent to the getImgResource hook.
194 *
195 * @param string $file
196 * @param array $fileArray
197 * @param $imageResource
198 * @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $parent
199 * @return array
200 * @see getImgResourceHookGetsCalled
201 */
202 public function isGetImgResourceHookCalledCallback($file, $fileArray, $imageResource, $parent)
203 {
204 $this->assertEquals('typo3/clear.gif', $file);
205 $this->assertEquals('typo3/clear.gif', $imageResource['origFile']);
206 $this->assertTrue(is_array($fileArray));
207 $this->assertTrue($parent instanceof \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer);
208 return $imageResource;
209 }
210
211 //////////////////////////////////////
212 // Tests concerning getContentObject
213 //////////////////////////////////////
214
215 public function getContentObjectValidContentObjectsDataProvider()
216 {
217 $dataProvider = array();
218 foreach ($this->contentObjectMap as $name => $className) {
219 $dataProvider[] = array($name, $className);
220 }
221 return $dataProvider;
222 }
223
224 /**
225 * @test
226 * @dataProvider getContentObjectValidContentObjectsDataProvider
227 * @param string $name TypoScript name of content object
228 * @param string $fullClassName Expected class name
229 */
230 public function getContentObjectCallsMakeInstanceForNewContentObjectInstance($name, $fullClassName)
231 {
232 $contentObjectInstance = $this->createMock($fullClassName);
233 \TYPO3\CMS\Core\Utility\GeneralUtility::addInstance($fullClassName, $contentObjectInstance);
234 $this->assertSame($contentObjectInstance, $this->subject->getContentObject($name));
235 }
236
237 /////////////////////////////////////////
238 // Tests concerning getQueryArguments()
239 /////////////////////////////////////////
240 /**
241 * @test
242 */
243 public function getQueryArgumentsExcludesParameters()
244 {
245 $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
246 $this->returnValue('key1=value1&key2=value2&key3[key31]=value31&key3[key32][key321]=value321&key3[key32][key322]=value322')
247 );
248 $getQueryArgumentsConfiguration = array();
249 $getQueryArgumentsConfiguration['exclude'] = array();
250 $getQueryArgumentsConfiguration['exclude'][] = 'key1';
251 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
252 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
253 $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
254 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2&key3[key32][key322]=value322');
255 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
256 $this->assertEquals($expectedResult, $actualResult);
257 }
258
259 /**
260 * @test
261 */
262 public function getQueryArgumentsExcludesGetParameters()
263 {
264 $_GET = array(
265 'key1' => 'value1',
266 'key2' => 'value2',
267 'key3' => array(
268 'key31' => 'value31',
269 'key32' => array(
270 'key321' => 'value321',
271 'key322' => 'value322'
272 )
273 )
274 );
275 $getQueryArgumentsConfiguration = array();
276 $getQueryArgumentsConfiguration['method'] = 'GET';
277 $getQueryArgumentsConfiguration['exclude'] = array();
278 $getQueryArgumentsConfiguration['exclude'][] = 'key1';
279 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
280 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
281 $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
282 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2&key3[key32][key322]=value322');
283 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
284 $this->assertEquals($expectedResult, $actualResult);
285 }
286
287 /**
288 * @test
289 */
290 public function getQueryArgumentsOverrulesSingleParameter()
291 {
292 $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
293 $this->returnValue('key1=value1')
294 );
295 $getQueryArgumentsConfiguration = array();
296 $overruleArguments = array(
297 // Should be overridden
298 'key1' => 'value1Overruled',
299 // Shouldn't be set: Parameter doesn't exist in source array and is not forced
300 'key2' => 'value2Overruled'
301 );
302 $expectedResult = '&key1=value1Overruled';
303 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments);
304 $this->assertEquals($expectedResult, $actualResult);
305 }
306
307 /**
308 * @test
309 */
310 public function getQueryArgumentsOverrulesMultiDimensionalParameters()
311 {
312 $_POST = array(
313 'key1' => 'value1',
314 'key2' => 'value2',
315 'key3' => array(
316 'key31' => 'value31',
317 'key32' => array(
318 'key321' => 'value321',
319 'key322' => 'value322'
320 )
321 )
322 );
323 $getQueryArgumentsConfiguration = array();
324 $getQueryArgumentsConfiguration['method'] = 'POST';
325 $getQueryArgumentsConfiguration['exclude'] = array();
326 $getQueryArgumentsConfiguration['exclude'][] = 'key1';
327 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
328 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
329 $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
330 $overruleArguments = array(
331 // Should be overriden
332 'key2' => 'value2Overruled',
333 'key3' => array(
334 'key32' => array(
335 // Shouldn't be set: Parameter is excluded and not forced
336 'key321' => 'value321Overruled',
337 // Should be overriden: Parameter is not excluded
338 'key322' => 'value322Overruled',
339 // Shouldn't be set: Parameter doesn't exist in source array and is not forced
340 'key323' => 'value323Overruled'
341 )
342 )
343 );
344 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2Overruled&key3[key32][key322]=value322Overruled');
345 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments);
346 $this->assertEquals($expectedResult, $actualResult);
347 }
348
349 /**
350 * @test
351 */
352 public function getQueryArgumentsOverrulesMultiDimensionalForcedParameters()
353 {
354 $this->subject->expects($this->any())->method('getEnvironmentVariable')->with($this->equalTo('QUERY_STRING'))->will(
355 $this->returnValue('key1=value1&key2=value2&key3[key31]=value31&key3[key32][key321]=value321&key3[key32][key322]=value322')
356 );
357 $_POST = array(
358 'key1' => 'value1',
359 'key2' => 'value2',
360 'key3' => array(
361 'key31' => 'value31',
362 'key32' => array(
363 'key321' => 'value321',
364 'key322' => 'value322'
365 )
366 )
367 );
368 $getQueryArgumentsConfiguration = array();
369 $getQueryArgumentsConfiguration['exclude'] = array();
370 $getQueryArgumentsConfiguration['exclude'][] = 'key1';
371 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key31]';
372 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key321]';
373 $getQueryArgumentsConfiguration['exclude'][] = 'key3[key32][key322]';
374 $getQueryArgumentsConfiguration['exclude'] = implode(',', $getQueryArgumentsConfiguration['exclude']);
375 $overruleArguments = array(
376 // Should be overriden
377 'key2' => 'value2Overruled',
378 'key3' => array(
379 'key32' => array(
380 // Should be set: Parameter is excluded but forced
381 'key321' => 'value321Overruled',
382 // Should be set: Parameter doesn't exist in source array but is forced
383 'key323' => 'value323Overruled'
384 )
385 )
386 );
387 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key2=value2Overruled&key3[key32][key321]=value321Overruled&key3[key32][key323]=value323Overruled');
388 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments, true);
389 $this->assertEquals($expectedResult, $actualResult);
390 $getQueryArgumentsConfiguration['method'] = 'POST';
391 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration, $overruleArguments, true);
392 $this->assertEquals($expectedResult, $actualResult);
393 }
394
395 /**
396 * @test
397 */
398 public function getQueryArgumentsWithMethodPostGetMergesParameters()
399 {
400 $_POST = array(
401 'key1' => 'POST1',
402 'key2' => 'POST2',
403 'key3' => array(
404 'key31' => 'POST31',
405 'key32' => 'POST32',
406 'key33' => array(
407 'key331' => 'POST331',
408 'key332' => 'POST332',
409 )
410 )
411 );
412 $_GET = array(
413 'key2' => 'GET2',
414 'key3' => array(
415 'key32' => 'GET32',
416 'key33' => array(
417 'key331' => 'GET331',
418 )
419 )
420 );
421 $getQueryArgumentsConfiguration = array();
422 $getQueryArgumentsConfiguration['method'] = 'POST,GET';
423 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key1=POST1&key2=GET2&key3[key31]=POST31&key3[key32]=GET32&key3[key33][key331]=GET331&key3[key33][key332]=POST332');
424 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
425 $this->assertEquals($expectedResult, $actualResult);
426 }
427
428 /**
429 * @test
430 */
431 public function getQueryArgumentsWithMethodGetPostMergesParameters()
432 {
433 $_GET = array(
434 'key1' => 'GET1',
435 'key2' => 'GET2',
436 'key3' => array(
437 'key31' => 'GET31',
438 'key32' => 'GET32',
439 'key33' => array(
440 'key331' => 'GET331',
441 'key332' => 'GET332',
442 )
443 )
444 );
445 $_POST = array(
446 'key2' => 'POST2',
447 'key3' => array(
448 'key32' => 'POST32',
449 'key33' => array(
450 'key331' => 'POST331',
451 )
452 )
453 );
454 $getQueryArgumentsConfiguration = array();
455 $getQueryArgumentsConfiguration['method'] = 'GET,POST';
456 $expectedResult = $this->rawUrlEncodeSquareBracketsInUrl('&key1=GET1&key2=POST2&key3[key31]=GET31&key3[key32]=POST32&key3[key33][key331]=POST331&key3[key33][key332]=GET332');
457 $actualResult = $this->subject->getQueryArguments($getQueryArgumentsConfiguration);
458 $this->assertEquals($expectedResult, $actualResult);
459 }
460
461 /**
462 * Encodes square brackets in URL.
463 *
464 * @param string $string
465 * @return string
466 */
467 private function rawUrlEncodeSquareBracketsInUrl($string)
468 {
469 return str_replace(array('[', ']'), array('%5B', '%5D'), $string);
470 }
471
472 //////////////////////////
473 // Tests concerning crop
474 //////////////////////////
475 /**
476 * @test
477 */
478 public function cropIsMultibyteSafe()
479 {
480 $this->assertEquals('бла', $this->subject->crop('бла', '3|...'));
481 }
482
483 //////////////////////////////
484 // Tests concerning cropHTML
485 //////////////////////////////
486 /**
487 * This is the data provider for the tests of crop and cropHTML below. It provides all combinations
488 * of charset, text type, and configuration options to be tested.
489 *
490 * @return array two-dimensional array with the second level like this:
491 * @see cropHtmlWithDataProvider
492 */
493 public function cropHtmlDataProvider()
494 {
495 $plainText = 'Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j implemented the original version of the crop function.';
496 $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.';
497 $textWithEntities = 'Kasper Sk&aring;rh&oslash;j implemented the; original ' . 'version of the crop function.';
498 $data = array(
499 'plain text; 11|...' => array(
500 '11|...',
501 $plainText,
502 'Kasper Sk' . chr(229) . 'r...'
503 ),
504 'plain text; -58|...' => array(
505 '-58|...',
506 $plainText,
507 '...h' . chr(248) . 'j implemented the original version of the crop function.'
508 ),
509 'plain text; 4|...|1' => array(
510 '4|...|1',
511 $plainText,
512 'Kasp...'
513 ),
514 'plain text; 20|...|1' => array(
515 '20|...|1',
516 $plainText,
517 'Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j...'
518 ),
519 'plain text; -5|...|1' => array(
520 '-5|...|1',
521 $plainText,
522 '...tion.'
523 ),
524 'plain text; -49|...|1' => array(
525 '-49|...|1',
526 $plainText,
527 '...the original version of the crop function.'
528 ),
529 'text with markup; 11|...' => array(
530 '11|...',
531 $textWithMarkup,
532 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'r...</a></strong>'
533 ),
534 'text with markup; 13|...' => array(
535 '13|...',
536 $textWithMarkup,
537 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . '...</a></strong>'
538 ),
539 'text with markup; 14|...' => array(
540 '14|...',
541 $textWithMarkup,
542 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>'
543 ),
544 'text with markup; 15|...' => array(
545 '15|...',
546 $textWithMarkup,
547 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a> ...</strong>'
548 ),
549 'text with markup; 29|...' => array(
550 '29|...',
551 $textWithMarkup,
552 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong> th...'
553 ),
554 'text with markup; -58|...' => array(
555 '-58|...',
556 $textWithMarkup,
557 '<strong><a href="mailto:kasper@typo3.org">...h' . chr(248) . 'j</a> implemented</strong> the original version of the crop function.'
558 ),
559 'text with markup 4|...|1' => array(
560 '4|...|1',
561 $textWithMarkup,
562 '<strong><a href="mailto:kasper@typo3.org">Kasp...</a></strong>'
563 ),
564 'text with markup; 11|...|1' => array(
565 '11|...|1',
566 $textWithMarkup,
567 '<strong><a href="mailto:kasper@typo3.org">Kasper...</a></strong>'
568 ),
569 'text with markup; 13|...|1' => array(
570 '13|...|1',
571 $textWithMarkup,
572 '<strong><a href="mailto:kasper@typo3.org">Kasper...</a></strong>'
573 ),
574 'text with markup; 14|...|1' => array(
575 '14|...|1',
576 $textWithMarkup,
577 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>'
578 ),
579 'text with markup; 15|...|1' => array(
580 '15|...|1',
581 $textWithMarkup,
582 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a>...</strong>'
583 ),
584 'text with markup; 29|...|1' => array(
585 '29|...|1',
586 $textWithMarkup,
587 '<strong><a href="mailto:kasper@typo3.org">Kasper Sk' . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong>...'
588 ),
589 'text with markup; -66|...|1' => array(
590 '-66|...|1',
591 $textWithMarkup,
592 '<strong><a href="mailto:kasper@typo3.org">...Sk' . chr(229) . 'rh' . chr(248) . 'j</a> implemented</strong> the original version of the crop function.'
593 ),
594 'text with entities 9|...' => array(
595 '9|...',
596 $textWithEntities,
597 'Kasper Sk...'
598 ),
599 'text with entities 10|...' => array(
600 '10|...',
601 $textWithEntities,
602 'Kasper Sk&aring;...'
603 ),
604 'text with entities 11|...' => array(
605 '11|...',
606 $textWithEntities,
607 'Kasper Sk&aring;r...'
608 ),
609 'text with entities 13|...' => array(
610 '13|...',
611 $textWithEntities,
612 'Kasper Sk&aring;rh&oslash;...'
613 ),
614 'text with entities 14|...' => array(
615 '14|...',
616 $textWithEntities,
617 'Kasper Sk&aring;rh&oslash;j...'
618 ),
619 'text with entities 15|...' => array(
620 '15|...',
621 $textWithEntities,
622 'Kasper Sk&aring;rh&oslash;j ...'
623 ),
624 'text with entities 16|...' => array(
625 '16|...',
626 $textWithEntities,
627 'Kasper Sk&aring;rh&oslash;j i...'
628 ),
629 'text with entities -57|...' => array(
630 '-57|...',
631 $textWithEntities,
632 '...j implemented the; original version of the crop function.'
633 ),
634 'text with entities -58|...' => array(
635 '-58|...',
636 $textWithEntities,
637 '...&oslash;j implemented the; original version of the crop function.'
638 ),
639 'text with entities -59|...' => array(
640 '-59|...',
641 $textWithEntities,
642 '...h&oslash;j implemented the; original version of the crop function.'
643 ),
644 'text with entities 4|...|1' => array(
645 '4|...|1',
646 $textWithEntities,
647 'Kasp...'
648 ),
649 'text with entities 9|...|1' => array(
650 '9|...|1',
651 $textWithEntities,
652 'Kasper...'
653 ),
654 'text with entities 10|...|1' => array(
655 '10|...|1',
656 $textWithEntities,
657 'Kasper...'
658 ),
659 'text with entities 11|...|1' => array(
660 '11|...|1',
661 $textWithEntities,
662 'Kasper...'
663 ),
664 'text with entities 13|...|1' => array(
665 '13|...|1',
666 $textWithEntities,
667 'Kasper...'
668 ),
669 'text with entities 14|...|1' => array(
670 '14|...|1',
671 $textWithEntities,
672 'Kasper Sk&aring;rh&oslash;j...'
673 ),
674 'text with entities 15|...|1' => array(
675 '15|...|1',
676 $textWithEntities,
677 'Kasper Sk&aring;rh&oslash;j...'
678 ),
679 'text with entities 16|...|1' => array(
680 '16|...|1',
681 $textWithEntities,
682 'Kasper Sk&aring;rh&oslash;j...'
683 ),
684 'text with entities -57|...|1' => array(
685 '-57|...|1',
686 $textWithEntities,
687 '...implemented the; original version of the crop function.'
688 ),
689 'text with entities -58|...|1' => array(
690 '-58|...|1',
691 $textWithEntities,
692 '...implemented the; original version of the crop function.'
693 ),
694 'text with entities -59|...|1' => array(
695 '-59|...|1',
696 $textWithEntities,
697 '...implemented the; original version of the crop function.'
698 ),
699 'text with dash in html-element 28|...|1' => array(
700 '28|...|1',
701 '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',
702 'Some text with a link to <link email.address@example.org - mail "Open email window">my...</link>'
703 ),
704 'html elements with dashes in attributes' => array(
705 '9',
706 '<em data-foo="x">foobar</em>foobaz',
707 '<em data-foo="x">foobar</em>foo'
708 ),
709 'html elements with iframe embedded 24|...|1' => array(
710 '24|...|1',
711 'Text with iframe <iframe src="//what.ever/"></iframe> and text after it',
712 'Text with iframe <iframe src="//what.ever/"></iframe> and...'
713 ),
714 'html elements with script tag embedded 24|...|1' => array(
715 '24|...|1',
716 'Text with script <script>alert(\'foo\');</script> and text after it',
717 'Text with script <script>alert(\'foo\');</script> and...'
718 )
719 );
720 return $data;
721 }
722
723 /**
724 * Checks if stdWrap.cropHTML works with plain text cropping from left
725 *
726 * @test
727 * @dataProvider cropHtmlDataProvider
728 * @param string $settings
729 * @param string $subject the string to crop
730 * @param string $expected the expected cropped result
731 */
732 public function cropHtmlWithDataProvider($settings, $subject, $expected)
733 {
734 $this->handleCharset($subject, $expected);
735 $this->assertEquals($expected, $this->subject->cropHTML($subject, $settings), 'cropHTML failed with settings: "' . $settings . '"');
736 }
737
738 /**
739 * Checks if stdWrap.cropHTML works with a complex content with many tags. Currently cropHTML
740 * counts multiple invisible characters not as one (as the browser will output the content).
741 *
742 * @test
743 */
744 public function cropHtmlWorksWithComplexContent()
745 {
746 $input =
747 '<h1>Blog Example</h1>' . LF .
748 '<hr>' . LF .
749 '<div class="csc-header csc-header-n1">' . LF .
750 ' <h2 class="csc-firstHeader">Welcome to Blog #1</h2>' . LF .
751 '</div>' . LF .
752 '<p class="bodytext">' . LF .
753 ' 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 .
754 '</p>' . LF .
755 '<div class="tx-blogexample-list-container">' . LF .
756 ' <p class="bodytext">' . LF .
757 ' Below are the most recent posts:' . LF .
758 ' </p>' . LF .
759 ' <ul>' . LF .
760 ' <li data-element="someId">' . LF .
761 ' <h3>' . LF .
762 ' <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 .
763 ' </h3>' . LF .
764 ' <p class="bodytext">' . LF .
765 ' Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut...' . LF .
766 ' </p>' . LF .
767 ' <p class="metadata">' . LF .
768 ' Published on 26.08.2009 by Jochen Rau' . LF .
769 ' </p>' . LF .
770 ' <p>' . LF .
771 ' Tags: [MVC]&nbsp;[Domain Driven Design]&nbsp;<br>' . LF .
772 ' <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 .
773 ' <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 .
774 ' </p>' . LF .
775 ' </li>' . LF .
776 ' </ul>' . LF .
777 ' <p>' . LF .
778 ' <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 .
779 ' </p>' . LF .
780 '</div>' . LF .
781 '<hr>' . LF .
782 '<p>' . LF .
783 ' ? TYPO3 Association' . LF .
784 '</p>';
785
786 $result = $this->subject->cropHTML($input, '300');
787
788 $expected =
789 '<h1>Blog Example</h1>' . LF .
790 '<hr>' . LF .
791 '<div class="csc-header csc-header-n1">' . LF .
792 ' <h2 class="csc-firstHeader">Welcome to Blog #1</h2>' . LF .
793 '</div>' . LF .
794 '<p class="bodytext">' . LF .
795 ' 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 .
796 '</p>' . LF .
797 '<div class="tx-blogexample-list-container">' . LF .
798 ' <p class="bodytext">' . LF .
799 ' Below are the most recent posts:' . LF .
800 ' </p>' . LF .
801 ' <ul>' . LF .
802 ' <li data-element="someId">' . LF .
803 ' <h3>' . LF .
804 ' <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>';
805
806 $this->assertEquals($expected, $result);
807
808 $result = $this->subject->cropHTML($input, '-100');
809
810 $expected =
811 '<div class="tx-blogexample-list-container"><ul><li data-element="someId"><p> Design]&nbsp;<br>' . LF .
812 ' <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 .
813 ' <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 .
814 ' </p>' . LF .
815 ' </li>' . LF .
816 ' </ul>' . LF .
817 ' <p>' . LF .
818 ' <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 .
819 ' </p>' . LF .
820 '</div>' . LF .
821 '<hr>' . LF .
822 '<p>' . LF .
823 ' ? TYPO3 Association' . LF .
824 '</p>';
825
826 $this->assertEquals($expected, $result);
827 }
828
829 /**
830 * Checks if stdWrap.cropHTML handles linebreaks correctly (by ignoring them)
831 *
832 * @test
833 */
834 public function cropHtmlWorksWithLinebreaks()
835 {
836 $subject = "Lorem ipsum dolor sit amet,\nconsetetur sadipscing elitr,\nsed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam";
837 $expected = "Lorem ipsum dolor sit amet,\nconsetetur sadipscing elitr,\nsed diam nonumy eirmod tempor invidunt ut labore et dolore magna";
838 $result = $this->subject->cropHTML($subject, '121');
839 $this->assertEquals($expected, $result);
840 }
841
842 /**
843 * Data provider for stdWrap_cacheRead
844 *
845 * @return array Order: expect, input, conf, times, with, will
846 */
847 public function stdWrap_cacheReadDataProvider()
848 {
849 $cacheConf = [$this->getUniqueId('cache.')];
850 $conf = ['cache.' => $cacheConf];
851 return [
852 'no conf' => [
853 'content', 'content', [],
854 0, null, null,
855 ],
856 'no cache. conf' => [
857 'content', 'content', ['otherConf' => 1],
858 0, null, null,
859 ],
860 'non-cached simulation' => [
861 'content', 'content', $conf,
862 1, $cacheConf, false,
863 ],
864 'cached simulation' => [
865 'cachedContent', 'content', $conf,
866 1, $cacheConf, 'cachedContent',
867 ],
868 ];
869 }
870
871 /**
872 * Check if stdWrap_cacheRead works properly.
873 *
874 * - the method branches correctly
875 * - getFromCache is called to fetch from cache
876 * - $conf['cache.'] is passed on as parameter
877 *
878 * @test
879 * @dataProvider stdWrap_cacheReadDataProvider
880 * @param string $expect Expected result.
881 * @param string $input Given input string.
882 * @param array $conf Property 'cache.'
883 * @param integer $times Times called mocked method.
884 * @param array $with Parameter passed to mocked method.
885 * @param string|false $will Return value of mocked method.
886 * @return void
887 */
888 public function stdWrap_cacheRead(
889 $expect, $input, $conf, $times, $with, $will)
890 {
891 $subject = $this->getAccessibleMock(
892 ContentObjectRenderer::class, ['getFromCache']);
893 $subject
894 ->expects($this->exactly($times))
895 ->method('getFromCache')
896 ->with($with)
897 ->willReturn($will);
898 $this->assertSame($expect,
899 $subject->stdWrap_cacheRead($input, $conf));
900 }
901
902 /**
903 * Check if stdWrap_setContentToCurrent works properly.
904 *
905 * @test
906 * @return void
907 */
908 public function stdWrap_setContentToCurrent()
909 {
910 $content = $this->getUniqueId('content');
911 $this->assertNotSame($content, $this->subject->getData('current'));
912 $this->assertSame($content,
913 $this->subject->stdWrap_setContentToCurrent($content));
914 $this->assertSame($content, $this->subject->getData('current'));
915 }
916
917 /**
918 * Data provider for stdWrap_setCurrent
919 *
920 * @return array Order input, conf
921 */
922 public function stdWrap_setCurrentDataProvider()
923 {
924 return [
925 'no conf' => [
926 'content',
927 [],
928 ],
929 'empty string' => [
930 'content',
931 ['setCurrent' => ''],
932 ],
933 'non-empty string' => [
934 'content',
935 ['setCurrent' => 'xxx'],
936 ],
937 'integer null' => [
938 'content',
939 ['setCurrent' => 0],
940 ],
941 'integer not null' => [
942 'content',
943 ['setCurrent' => 1],
944 ],
945 'boolean true' => [
946 'content',
947 ['setCurrent' => true],
948 ],
949 'boolean false' => [
950 'content',
951 ['setCurrent' => false],
952 ],
953 ];
954 }
955
956 /**
957 * Check if stdWrap_setCurrent works properly.
958 *
959 * @test
960 * @dataProvider stdWrap_setCurrentDataProvider
961 * @param string $input The input value.
962 * @param array $conf Property: setCurrent
963 * @return void
964 */
965 public function stdWrap_setCurrent($input, $conf)
966 {
967 if (isset($conf['setCurrent'])) {
968 $this->assertNotSame($conf['setCurrent'], $this->subject->getData('current'));
969 }
970 $this->assertSame($input, $this->subject->stdWrap_setCurrent($input, $conf));
971 if (isset($conf['setCurrent'])) {
972 $this->assertSame($conf['setCurrent'], $this->subject->getData('current'));
973 }
974 }
975
976 /**
977 * Data provider for stdWrap_data.
978 *
979 * @return array [$expect, $data, $alt]
980 */
981 public function stdWrap_dataDataProvider()
982 {
983 $data = [$this->getUniqueId('data')];
984 $alt = [$this->getUniqueId('alternativeData')];
985 return [
986 'default' => [$data, $data, ''],
987 'alt is array' => [$alt, $data, $alt],
988 'alt is empty array' => [[], $data, []],
989 'alt null' => [$data, $data, null],
990 'alt string' => [$data, $data, 'xxx'],
991 'alt int' => [$data, $data, 1],
992 'alt bool' => [$data, $data, true],
993 ];
994 }
995
996 /**
997 * Checks that stdWrap_data works properly.
998 *
999 * Show:
1000 *
1001 * - Delegates to method getData.
1002 * - Parameter 1 is $conf['data'].
1003 * - Parameter 2 is property data by default.
1004 * - Parameter 2 is property alternativeData, if set as array.
1005 * - Property alternativeData is always unset to ''.
1006 * - Returns the return value.
1007 *
1008 * @test
1009 * @dataProvider stdWrap_dataDataProvider
1010 * @param mixed $expect Expect either $data or $alternativeData.
1011 * @param array $data The data.
1012 * @param mixed $alt The alternativeData.
1013 * @return void
1014 */
1015 public function stdWrap_data($expect, $data, $alt)
1016 {
1017 $conf = ['data' => $this->getUniqueId('conf.data')];
1018 $return = $this->getUniqueId('return');
1019 $subject = $this->getAccessibleMock(
1020 ContentObjectRenderer::class, ['getData']);
1021 $subject->_set('data', $data);
1022 $subject->_set('alternativeData', $alt);
1023 $subject
1024 ->expects($this->once())
1025 ->method('getData')
1026 ->with($conf['data'], $expect)
1027 ->willReturn($return);
1028 $this->assertSame($return, $subject->stdWrap_data('discard', $conf));
1029 $this->assertSame('', $subject->_get('alternativeData'));
1030 }
1031
1032 /**
1033 * Check if stdWrap_preIfEmptyListNum works properly.
1034 *
1035 * Show:
1036 *
1037 * - Delegates to method listNum.
1038 * - Parameter 1 is $content.
1039 * - Parameter 2 is $conf['preIfEmptyListNum'].
1040 * - Parameter 3 is $conf['preIfEmptyListNum.']['splitChar'].
1041 * - Returns the return value.
1042 *
1043 * @test
1044 * @return void
1045 */
1046 public function stdWrap_preIfEmptyListNum()
1047 {
1048 $content = $this->getUniqueId('content');
1049 $conf = [
1050 'preIfEmptyListNum' => $this->getUniqueId('preIfEmptyListNum'),
1051 'preIfEmptyListNum.' => [
1052 'splitChar' => $this->getUniqueId('splitChar')
1053 ],
1054 ];
1055 $return = $this->getUniqueId('return');
1056 $subject = $this->getMockBuilder(ContentObjectRenderer::class)
1057 ->setMethods(['listNum'])->getMock();
1058 $subject
1059 ->expects($this->once())
1060 ->method('listNum')
1061 ->with(
1062 $content,
1063 $conf['preIfEmptyListNum'],
1064 $conf['preIfEmptyListNum.']['splitChar']
1065 )
1066 ->willReturn($return);
1067 $this->assertSame($return,
1068 $subject->stdWrap_preIfEmptyListNum($content, $conf));
1069 }
1070
1071 /**
1072 * Check if stdWrap_current works properly.
1073 *
1074 * Show:
1075 *
1076 * - current is returned from $this->data
1077 * - the key is stored in $this->currentValKey
1078 * - the key defaults to 'currentValue_kidjls9dksoje'
1079 *
1080 * @test
1081 * @return void
1082 */
1083 public function stdWrap_current()
1084 {
1085 $data = [
1086 'currentValue_kidjls9dksoje' => 'default',
1087 'currentValue_new' => 'new',
1088 ];
1089 $this->subject->_set('data', $data);
1090 $this->assertSame('currentValue_kidjls9dksoje',
1091 $this->subject->_get('currentValKey'));
1092 $this->assertSame('default',
1093 $this->subject->stdWrap_current('discarded', ['discarded']));
1094 $this->subject->_set('currentValKey', 'currentValue_new');
1095 $this->assertSame('new',
1096 $this->subject->stdWrap_current('discarded', ['discarded']));
1097 }
1098
1099 /**
1100 * Check if stdWrap_preUserFunc works properly.
1101 *
1102 * Show:
1103 *
1104 * - Delegates to method callUserFunction.
1105 * - Parameter 1 is $conf['preUserFunc'].
1106 * - Parameter 2 is $conf['preUserFunc.'].
1107 * - Parameter 3 is $content.
1108 * - Returns the return value.
1109 *
1110 * @test
1111 * @return void
1112 */
1113 public function stdWrap_preUserFunc()
1114 {
1115 $content = $this->getUniqueId('content');
1116 $conf = [
1117 'preUserFunc' => $this->getUniqueId('preUserFunc'),
1118 'preUserFunc.' => [$this->getUniqueId('preUserFunc.')],
1119 ];
1120 $subject = $this->getMockBuilder(ContentObjectRenderer::class)
1121 ->setMethods(['callUserFunction'])->getMock();
1122 $subject->expects($this->once())->method('callUserFunction')
1123 ->with($conf['preUserFunc'], $conf['preUserFunc.'], $content)
1124 ->willReturn('return');
1125 $this->assertSame('return',
1126 $subject->stdWrap_preUserFunc($content, $conf));
1127 }
1128
1129 /**
1130 * Data provider for stdWrap_csConv
1131 *
1132 * @return array Order expected, input, conf
1133 */
1134 public function stdWrap_overrideDataProvider()
1135 {
1136 return [
1137 'standard case' => [
1138 'override', 'content', ['override' => 'override']
1139 ],
1140 'empty conf does not override' => [
1141 'content', 'content', []
1142 ],
1143 'empty string does not override' => [
1144 'content', 'content', ['override' => '']
1145 ],
1146 'whitespace does not override' => [
1147 'content', 'content', ['override' => ' ' . TAB]
1148 ],
1149 'zero does not override' => [
1150 'content', 'content', ['override' => 0]
1151 ],
1152 'false does not override' => [
1153 'content', 'content', ['override' => false]
1154 ],
1155 'null does not override' => [
1156 'content', 'content', ['override' => null]
1157 ],
1158 'one does override' => [
1159 1, 'content', ['override' => 1]
1160 ],
1161 'minus one does override' => [
1162 -1, 'content', ['override' => -1]
1163 ],
1164 'float does override' => [
1165 -0.1, 'content', ['override' => -0.1]
1166 ],
1167 'true does override' => [
1168 true, 'content', ['override' => true]
1169 ],
1170 'the value is not trimmed' => [
1171 TAB . 'override', 'content', ['override' => TAB . 'override']
1172 ],
1173 ];
1174 }
1175
1176 /**
1177 * Check if stdWrap_override works properly.
1178 *
1179 * @test
1180 * @dataProvider stdWrap_overrideDataProvider
1181 * @param string $input The input value.
1182 * @param array $conf Property: setCurrent
1183 * @return void
1184 */
1185 public function stdWrap_override($expect, $content, $conf)
1186 {
1187 $this->assertSame($expect,
1188 $this->subject->stdWrap_override($content, $conf));
1189 }
1190
1191 /**
1192 * Check if stdWrap_listNum works properly.
1193 *
1194 * Show:
1195 *
1196 * - Delegates to method listNum.
1197 * - Parameter 1 is $content.
1198 * - Parameter 2 is $conf['listNum'].
1199 * - Parameter 3 is $conf['listNum.']['splitChar'].
1200 * - Returns the return value.
1201 *
1202 * @test
1203 * @return void
1204 */
1205 public function stdWrap_listNum()
1206 {
1207 $content = $this->getUniqueId('content');
1208 $conf = [
1209 'listNum' => $this->getUniqueId('listNum'),
1210 'listNum.' => [
1211 'splitChar' => $this->getUniqueId('splitChar')
1212 ],
1213 ];
1214 $return = $this->getUniqueId('return');
1215 $subject = $this->getMockBuilder(ContentObjectRenderer::class)
1216 ->setMethods(['listNum'])->getMock();
1217 $subject
1218 ->expects($this->once())
1219 ->method('listNum')
1220 ->with(
1221 $content,
1222 $conf['listNum'],
1223 $conf['listNum.']['splitChar']
1224 )
1225 ->willReturn($return);
1226 $this->assertSame($return,
1227 $subject->stdWrap_listNum($content, $conf));
1228 }
1229
1230 /**
1231 * Check if stdWrap_field works properly.
1232 *
1233 * Show:
1234 *
1235 * - calls getFieldVal
1236 * - passes conf['field'] as parameter
1237 *
1238 * @test
1239 * @return void
1240 */
1241 public function stdWrap_field()
1242 {
1243 $expect = $this->getUniqueId('expect');
1244 $conf = ['field' => $this->getUniqueId('field')];
1245 $subject = $this->getMockBuilder(ContentObjectRenderer::class)
1246 ->setMethods(['getFieldVal'])->getMock();
1247 $subject
1248 ->expects($this->once())
1249 ->method('getFieldVal')
1250 ->with($conf['field'])
1251 ->willReturn($expect);
1252 $this->assertSame($expect,
1253 $subject->stdWrap_field('discarded', $conf));
1254 }
1255
1256 /**
1257 * Check if stdWrap_cObject works properly.
1258 *
1259 * Show:
1260 *
1261 * - Delegates to the method cObjGetSingle().
1262 * - First parameter is $conf['cObject'].
1263 * - Second parameter is $conf['cObject.'].
1264 * - Third parameter is '/stdWrap/.cObject'.
1265 * - Returns the return.
1266 *
1267 * @test
1268 * @return void
1269 */
1270 public function stdWrap_cObject()
1271 {
1272 $debugKey = '/stdWrap/.cObject';
1273 $conf = [
1274 'cObject' => $this->getUniqueId('cObject'),
1275 'cObject.' => [$this->getUniqueId('cObject.')],
1276 ];
1277 $subject = $this->getMockBuilder(ContentObjectRenderer::class)
1278 ->setMethods(['cObjGetSingle'])->getMock();
1279 $subject
1280 ->expects($this->once())
1281 ->method('cObjGetSingle')
1282 ->with($conf['cObject'], $conf['cObject.'], $debugKey)
1283 ->willReturn('return');
1284 $this->assertSame('return',
1285 $subject->stdWrap_cObject('discard', $conf));
1286 }
1287
1288 /**
1289 * Data provider for stdWrap_csConv
1290 *
1291 * @return array Order expected, input, conf
1292 */
1293 public function stdWrap_csConvDataProvider()
1294 {
1295 return [
1296 'empty string from ISO-8859-15' => [
1297 '',
1298 iconv('UTF-8', 'ISO-8859-15', ''),
1299 ['csConv' => 'ISO-8859-15']
1300 ],
1301 'empty string from BIG-5' => [
1302 '',
1303 mb_convert_encoding('', 'BIG-5'),
1304 ['csConv' => 'BIG-5']
1305 ],
1306 '"0" from ISO-8859-15' => [
1307 '0',
1308 iconv('UTF-8', 'ISO-8859-15', '0'),
1309 ['csConv' => 'ISO-8859-15']
1310 ],
1311 '"0" from BIG-5' => [
1312 '0',
1313 mb_convert_encoding('0', 'BIG-5'),
1314 ['csConv' => 'BIG-5']
1315 ],
1316 'euro symbol from ISO-88859-15' => [
1317 '€',
1318 iconv('UTF-8', 'ISO-8859-15', '€'),
1319 ['csConv' => 'ISO-8859-15']
1320 ],
1321 'good morning from BIG-5' => [
1322 '早安',
1323 mb_convert_encoding('早安', 'BIG-5'),
1324 ['csConv' => 'BIG-5']
1325 ],
1326 ];
1327 }
1328
1329 /**
1330 * Check if stdWrap_csConv works properly.
1331 *
1332 * @test
1333 * @dataProvider stdWrap_csConvDataProvider
1334 * @param string $expected The expected value.
1335 * @param string $value The input value.
1336 * @param array $conf Property: csConv
1337 * @return void
1338 */
1339 public function stdWrap_csConv($expected, $input, $conf)
1340 {
1341 $this->assertSame($expected,
1342 $this->subject->stdWrap_csConv($input, $conf));
1343 }
1344
1345 /**
1346 * Check if stdWrap_split works properly.
1347 *
1348 * Show:
1349 *
1350 * - Delegates to method splitObj.
1351 * - Parameter 1 is $content.
1352 * - Prameter 2 is $conf['split.'].
1353 * - Returns the return value.
1354 *
1355 * @test
1356 * @return void
1357 */
1358 public function stdWrap_split()
1359 {
1360 $content = $this->getUniqueId('content');
1361 $conf = [
1362 'split' => $this->getUniqueId('not used'),
1363 'split.' => [$this->getUniqueId('split.')],
1364 ];
1365 $return = $this->getUniqueId('return');
1366 $subject = $this->getMockBuilder(ContentObjectRenderer::class)
1367 ->setMethods(['splitObj'])->getMock();
1368 $subject
1369 ->expects($this->once())
1370 ->method('splitObj')
1371 ->with($content, $conf['split.'])
1372 ->willReturn($return);
1373 $this->assertSame($return,
1374 $subject->stdWrap_split($content, $conf));
1375 }
1376
1377 /**
1378 * Data provider for stdWrap_prioriCalc
1379 *
1380 * @return array [$expect, $content, $conf]
1381 */
1382 public function stdWrap_prioriCalcDataProvider()
1383 {
1384 return [
1385 'priority of *' => ['7', '1 + 2 * 3', []],
1386 'priority of parentheses' => ['9', '(1 + 2) * 3', []],
1387 'float' => ['1.5', '3/2', []],
1388 'intval casts to int' => [1, '3/2', ['prioriCalc' => 'intval']],
1389 'intval does not round' => [2, '2.7', ['prioriCalc' => 'intval']],
1390 ];
1391 }
1392
1393 /**
1394 * Check if stdWrap_prioriCalc works properly.
1395 *
1396 * Show:
1397 *
1398 * - If $conf['prioriCalc'] is 'intval' the return is casted to int.
1399 * - Delegates to MathUtility::calculateWithParentheses.
1400 *
1401 * Note: As PHPUnit can't mock static methods, the call to
1402 * MathUtility::calculateWithParentheses can't be easily intercepted.
1403 * The test is done by testing input/output pairs instead. To not
1404 * duplicate the testing of calculateWithParentheses just a few
1405 * smoke tests are done here.
1406 *
1407 * @test
1408 * @dataProvider stdWrap_prioriCalcDataProvider
1409 * @param mixed $expect The expected output.
1410 * @param string $content The given content.
1411 * @param array $conf The given configuration.
1412 * @return void
1413 */
1414 public function stdWrap_prioriCalc($expect, $content, $conf)
1415 {
1416 $result = $this->subject->stdWrap_prioriCalc($content, $conf);
1417 $this->assertSame($expect, $result);
1418 }
1419
1420 /**
1421 * Test for the stdWrap_stripHtml
1422 *
1423 * @test
1424 */
1425 public function stdWrap_stripHtml()
1426 {
1427 $content = '<html><p>Hello <span class="inline">inline tag<span>!</p><p>Hello!</p></html>';
1428 $expected = 'Hello inline tag!Hello!';
1429 $this->assertSame($expected, $this->subject->stdWrap_stripHtml($content));
1430 }
1431
1432 /**
1433 * Data provider for round
1434 *
1435 * @return array [$expect, $contet, $conf]
1436 */
1437 public function roundDataProvider()
1438 {
1439 return [
1440 // floats
1441 'down' => [1.0, 1.11, []],
1442 'up' => [2.0, 1.51, []],
1443 'rounds up from x.50' => [2.0, 1.50, []],
1444 'down with decimals' => [0.12, 0.1231, ['decimals' => 2]],
1445 'up with decimals' => [0.13, 0.1251, ['decimals' => 2]],
1446 'ceil' => [1.0, 0.11, ['roundType' => 'ceil']],
1447 'ceil does not accept decimals' => [
1448 1.0, 0.111, [
1449 'roundType' => 'ceil',
1450 'decimals' => 2,
1451 ],
1452 ],
1453 'floor' => [2.0, 2.99, ['roundType' => 'floor']],
1454 'floor does not accept decimals' => [
1455 2.0, 2.999, [
1456 'roundType' => 'floor',
1457 'decimals' => 2,
1458 ],
1459 ],
1460 'round, down' => [1.0, 1.11, ['roundType' => 'round']],
1461 'round, up' => [2.0, 1.55, ['roundType' => 'round']],
1462 'round does accept decimals' => [
1463 5.56, 5.5555, [
1464 'roundType' => 'round',
1465 'decimals' => 2,
1466 ],
1467 ],
1468 // strings
1469 'emtpy string' => [0.0, '', []],
1470 'word string' => [0.0, 'word', []],
1471 'float string' => [1.0, '1.123456789', []],
1472 // other types
1473 'null' => [0.0, null, []],
1474 'false' => [0.0, false, []],
1475 'true' => [1.0, true, []]
1476 ];
1477 }
1478
1479 /**
1480 * Check if round works properly
1481 *
1482 * Show:
1483 *
1484 * - Different types of input are casted to float.
1485 * - Configuration ceil rounds like ceil().
1486 * - Configuration floor rounds like floor().
1487 * - Otherwise rounds like round() and decimals can be applied.
1488 * - Always returns float.
1489 *
1490 * @param float $expected The expected output.
1491 * @param mixed $content The given content.
1492 * @param array $conf The given configuration of 'round.'.
1493 * @return void
1494 * @dataProvider roundDataProvider
1495 * @test
1496 */
1497 public function round($expect, $content, $conf)
1498 {
1499 $this->assertSame($expect,
1500 $this->subject->_call('round', $content, $conf));
1501 }
1502
1503 /**
1504 * Check if stdWrap_round works properly
1505 *
1506 * Show:
1507 *
1508 * - Delegates to method round.
1509 * - Parameter 1 is $content.
1510 * - Parameter 2 is $conf['round.'].
1511 * - Returns the return value.
1512 *
1513 * @test
1514 * @return void
1515 */
1516 public function stdWrap_round()
1517 {
1518 $content = $this->getUniqueId('content');
1519 $conf = [
1520 'round' => $this->getUniqueId('not used'),
1521 'round.' => [$this->getUniqueId('round.')],
1522 ];
1523 $return = $this->getUniqueId('return');
1524 $subject = $this->getMockBuilder(ContentObjectRenderer::class)
1525 ->setMethods(['round'])->getMock();
1526 $subject
1527 ->expects($this->once())
1528 ->method('round')
1529 ->with($content, $conf['round.'])
1530 ->willReturn($return);
1531 $this->assertSame($return, $subject->stdWrap_round($content, $conf));
1532 }
1533
1534 /**
1535 * @return array
1536 */
1537 public function stdWrap_numberFormatDataProvider()
1538 {
1539 return array(
1540 'testing decimals' => array(
1541 0.8,
1542 array(
1543 'numberFormat.' => array(
1544 'decimals' => 2
1545 ),
1546 ),
1547 '0.80'
1548 ),
1549 'testing decimals with input as string' => array(
1550 '0.8',
1551 array(
1552 'numberFormat.' => array(
1553 'decimals' => 2
1554 ),
1555 ),
1556 '0.80'
1557 ),
1558 'testing dec_point' => array(
1559 0.8,
1560 array(
1561 'numberFormat.' => array(
1562 'decimals' => 1,
1563 'dec_point' => ','
1564 ),
1565 ),
1566 '0,8'
1567 ),
1568 'testing thousands_sep' => array(
1569 999.99,
1570 array(
1571 'numberFormat.' => array(
1572 'decimals' => 0,
1573 'thousands_sep.' => array(
1574 'char' => 46
1575 ),
1576 ),
1577 ),
1578 '1.000'
1579 ),
1580 'testing mixture' => array(
1581 1281731.45,
1582 array(
1583 'numberFormat.' => array(
1584 'decimals' => 1,
1585 'dec_point.' => array(
1586 'char' => 44
1587 ),
1588 'thousands_sep.' => array(
1589 'char' => 46
1590 ),
1591 ),
1592 ),
1593 '1.281.731,5'
1594 )
1595 );
1596 }
1597
1598 /**
1599 * Test for the stdWrap function "stdWrap_numberFormat"
1600 *
1601 * @param float $float
1602 * @param array $conf
1603 * @param string $expected
1604 * @return void
1605 * @dataProvider stdWrap_numberFormatDataProvider
1606 * @test
1607 */
1608 public function stdWrap_numberFormat($float, $conf, $expected)
1609 {
1610 $result = $this->subject->stdWrap_numberFormat($float, $conf);
1611 $this->assertEquals($expected, $result);
1612 }
1613
1614 /**
1615 * Data provider for expandList
1616 *
1617 * @return array [$expect, $content]
1618 */
1619 public function stdWrap_expandListDataProvider()
1620 {
1621 return [
1622 'numbers' => ['1,2,3', '1,2,3'],
1623 'range' => ['3,4,5', '3-5'],
1624 'numbers and range' => ['1,3,4,5,7', '1,3-5,7']
1625 ];
1626 }
1627
1628 /**
1629 * Test for the stdWrap function "expandList"
1630 *
1631 * The method simply delegates to GeneralUtility::expandList. There is no
1632 * need to repeat the full set of tests of this method here. As PHPUnit
1633 * can't mock static methods, to prove they are called, all we do here
1634 * is to provide a few smoke tests.
1635 *
1636 * @test
1637 * @dataProvider stdWrap_expandListDataProvider
1638 * @param string $expected The expeced output.
1639 * @param string $content The given content.
1640 * @return void
1641 */
1642 public function stdWrap_expandList($expected, $content)
1643 {
1644 $this->assertEquals($expected,
1645 $this->subject->stdWrap_expandList($content));
1646 }
1647
1648 /**
1649 * Data provider for stdWrap_trim.
1650 *
1651 * @return array [$expect, $content]
1652 */
1653 public function stdWrap_trimDataProvider()
1654 {
1655 return [
1656 // string not trimmed
1657 'empty string' => ['', ''],
1658 'string without whitespace' => ['xxx', 'xxx'],
1659 'string with whitespace inside' => [
1660 'xx ' . TAB . ' xx',
1661 'xx ' . TAB . ' xx',
1662 ],
1663 'string with newlines inside' => [
1664 'xx ' . PHP_EOL . ' xx',
1665 'xx ' . PHP_EOL . ' xx',
1666 ],
1667 // string trimmed
1668 'blanks around' => ['xxx', ' xxx '],
1669 'tabs around' => ['xxx', TAB . 'xxx' . TAB],
1670 'newlines around' => ['xxx', PHP_EOL . 'xxx' . PHP_EOL],
1671 'mixed case' => ['xxx', TAB . ' xxx ' . PHP_EOL],
1672 // non strings
1673 'null' => ['', null],
1674 'false' => ['', false],
1675 'true' => ['1', true],
1676 'zero' => ['0', 0],
1677 'one' => ['1', 1],
1678 '-1' => ['-1', -1],
1679 '0.0' => ['0', 0.0],
1680 '1.0' => ['1', 1.0],
1681 '-1.0' => ['-1', -1.0],
1682 '1.1' => ['1.1', 1.1],
1683 ];
1684 }
1685
1686 /**
1687 * Check that stdWrap_trim works properly.
1688 *
1689 * Show:
1690 *
1691 * - the given string is trimmed like PHP trim
1692 * - non-strings are casted to strings:
1693 * - null => 'null'
1694 * - false => ''
1695 * - true => '1'
1696 * - 0 => '0'
1697 * - -1 => '-1'
1698 * - 1.0 => '1'
1699 * - 1.1 => '1.1'
1700 *
1701 * @test
1702 * @dataProvider stdWrap_trimDataProvider
1703 * @param string $expected The expected output.
1704 * @param mixed $content The given content.
1705 * @return void
1706 */
1707 public function stdWrap_trim($expect, $content)
1708 {
1709 $result = $this->subject->stdWrap_trim($content);
1710 $this->assertSame($expect, $result);
1711 }
1712
1713 /**
1714 * Data provider for stdWrap_if.
1715 *
1716 * @return array [$expect, $stop, $content, $conf, $times, $will]
1717 */
1718 public function stdWrap_ifDataProvider()
1719 {
1720 $content = $this->getUniqueId('content');
1721 $conf = ['if.' => [$this->getUniqueId('if.')]];
1722 return [
1723 // evals to true
1724 'empty config' => [
1725 $content, false, $content, [], 0, null
1726 ],
1727 'if. is empty array' => [
1728 $content, false, $content, ['if.' => []], 0, null
1729 ],
1730 'if. is null' => [
1731 $content, false, $content, ['if.' => null], 0, null
1732 ],
1733 'if. is false' => [
1734 $content, false, $content, ['if.' => false], 0, null
1735 ],
1736 'if. is 0' => [
1737 $content, false, $content, ['if.' => false], 0, null
1738 ],
1739 'if. is "0"' => [
1740 $content, false, $content, ['if.' => '0'], 0, null
1741 ],
1742 'checkIf returning true' => [
1743 $content, false, $content, $conf, 1, true
1744 ],
1745 // evals to false
1746 'checkIf returning false' => [
1747 '', true, $content, $conf, 1, false
1748 ],
1749 ];
1750 }
1751
1752 /**
1753 * Check if stdWrap_if works properly.
1754 *
1755 * Show:
1756 *
1757 * - Delegates to the method checkIf to check for 'true'.
1758 * - The parameter to checkIf is $conf['if.'].
1759 * - Is also 'true' if $conf['if.'] is empty (PHP method empty).
1760 * - 'False' triggers a stop of further rendering.
1761 * - Returns the content as is or '' if false.
1762 *
1763 * @test
1764 * @dataProvider stdWrap_ifDataProvider
1765 * @param mixed $expect The expected output.
1766 * @param bool $stop Expect stop further rendering.
1767 * @param mixed $content The given content.
1768 * @param mixed $config The given configuration.
1769 * @param int $times Times checkIf is called (0 or 1).
1770 * @param bool|null $will Return of checkIf (null if not called).
1771 * @return void
1772 */
1773 public function stdWrap_if($expect, $stop, $content, $conf, $times, $will)
1774 {
1775 $subject = $this->getAccessibleMock(
1776 ContentObjectRenderer::class, ['checkIf']);
1777 $subject->_set('stdWrapRecursionLevel', 1);
1778 $subject->_set('stopRendering', [1 => false]);
1779 $subject
1780 ->expects($this->exactly($times))
1781 ->method('checkIf')
1782 ->with($conf['if.'])
1783 ->willReturn($will);
1784 $this->assertSame($expect, $subject->stdWrap_if($content, $conf));
1785 $this->assertSame($stop, $subject->_get('stopRendering')[1]);
1786 }
1787
1788 /**
1789 * Data provider for stdWrap_intval
1790 *
1791 * @return array [$expect, $content]
1792 */
1793 public function stdWrap_intvalDataProvider()
1794 {
1795 return [
1796 // numbers
1797 'int' => [123, 123],
1798 'float' => [123, 123.45],
1799 'float does not round up' => [123, 123.55],
1800 // negative numbers
1801 'negative int' => [-123, -123],
1802 'negative float' => [-123, -123.45],
1803 'negative float does not round down' => [ -123, -123.55],
1804 // strings
1805 'word string' => [0, 'string'],
1806 'empty string' => [0, ''],
1807 'zero string' => [0, '0'],
1808 'int string' => [123, '123'],
1809 'float string' => [123, '123.55'],
1810 'negative float string' => [-123, '-123.55'],
1811 // other types
1812 'null' => [0, null],
1813 'true' => [1, true],
1814 'false' => [0, false]
1815 ];
1816 }
1817
1818 /**
1819 * Check that stdWrap_intval works properly.
1820 *
1821 * Show:
1822 *
1823 * - It does not round up.
1824 * - All types of input is casted to int:
1825 * - null: 0
1826 * - false: 0
1827 * - true: 1
1828 * -
1829 *
1830 *
1831 *
1832 * @test
1833 * @dataProvider stdWrap_intvalDataProvider
1834 * @param int $expect The expected output.
1835 * @param string $content The given input.
1836 * @return void
1837 */
1838 public function stdWrap_intval($expect, $content)
1839 {
1840 $this->assertSame($expect, $this->subject->stdWrap_intval($content));
1841 }
1842
1843 /**
1844 * Data provider for stdWrap_strPad.
1845 *
1846 * @return array [$expect, $content, $conf]
1847 */
1848 public function stdWrap_strPadDataProvider()
1849 {
1850 return [
1851 'pad string with default settings and length 10' => [
1852 'Alien ',
1853 'Alien',
1854 [
1855 'length' => '10',
1856 ],
1857 ],
1858 'pad string with padWith -= and type left and length 10' => [
1859 '-=-=-Alien',
1860 'Alien',
1861 [
1862 'length' => '10',
1863 'padWith' => '-=',
1864 'type' => 'left',
1865 ],
1866 ],
1867 'pad string with padWith _ and type both and length 10' => [
1868 '__Alien___',
1869 'Alien',
1870 [
1871 'length' => '10',
1872 'padWith' => '_',
1873 'type' => 'both',
1874 ],
1875 ],
1876 'pad string with padWith 0 and type both and length 10' => [
1877 '00Alien000',
1878 'Alien',
1879 [
1880 'length' => '10',
1881 'padWith' => '0',
1882 'type' => 'both',
1883 ],
1884 ],
1885 'pad string with padWith ___ and type both and length 6' => [
1886 'Alien_',
1887 'Alien',
1888 [
1889 'length' => '6',
1890 'padWith' => '___',
1891 'type' => 'both',
1892 ],
1893 ],
1894 'pad string with padWith _ and type both and length 12, using stdWrap for length' => [
1895 '___Alien____',
1896 'Alien',
1897 [
1898 'length' => '1',
1899 'length.' => [
1900 'wrap' => '|2',
1901 ],
1902 'padWith' => '_',
1903 'type' => 'both',
1904 ],
1905 ],
1906 'pad string with padWith _ and type both and length 12, using stdWrap for padWidth' => [
1907 '-_=Alien-_=-',
1908 'Alien',
1909 [
1910 'length' => '12',
1911 'padWith' => '_',
1912 'padWith.' => [
1913 'wrap' => '-|=',
1914 ],
1915 'type' => 'both',
1916 ],
1917 ],
1918 'pad string with padWith _ and type both and length 12, using stdWrap for type' => [
1919 '_______Alien',
1920 'Alien',
1921 [
1922 'length' => '12',
1923 'padWith' => '_',
1924 'type' => 'both',
1925 // make type become "left"
1926 'type.' => [
1927 'substring' => '2,1',
1928 'wrap' => 'lef|',
1929 ],
1930 ],
1931 ],
1932 ];
1933 }
1934
1935 /**
1936 * Check if stdWrap_strPad works properly.
1937 *
1938 * @test
1939 * @dataProvider stdWrap_strPadDataProvider
1940 * @param string $expect The expected output.
1941 * @param string $content The given input.
1942 * @param array $conf The configuration of 'strPad.'.
1943 * @return void
1944 */
1945 public function stdWrap_strPad($expect, $content, $conf)
1946 {
1947 $conf = ['strPad.' => $conf];
1948 $result = $this->subject->stdWrap_strPad($content, $conf);
1949 $this->assertSame($expect, $result);
1950 }
1951
1952 /**
1953 * Check that stdWrap_stdWrap works properly.
1954 *
1955 * Show:
1956 * - Delegates to method stdWrap.
1957 * - Parameter 1 is $content.
1958 * - Parameter 2 is $conf['stdWrap.'].
1959 * - Returns the return value.
1960 *
1961 * @test
1962 * @return void.
1963 */
1964 public function stdWrap_stdWrap()
1965 {
1966 $content = $this->getUniqueId('content');
1967 $conf = [
1968 'stdWrap' => $this->getUniqueId('not used'),
1969 'stdWrap.' => [$this->getUniqueId('stdWrap.')],
1970 ];
1971 $return = $this->getUniqueId('return');
1972 $subject = $this->getMockBuilder(ContentObjectRenderer::class)
1973 ->setMethods(['stdWrap'])->getMock();
1974 $subject
1975 ->expects($this->once())
1976 ->method('stdWrap')
1977 ->with($content, $conf['stdWrap.'])
1978 ->willReturn($return);
1979 $this->assertSame($return, $subject->stdWrap_stdWrap($content, $conf));
1980 }
1981
1982 /**
1983 * Data provider for the hash test
1984 *
1985 * @return array [$expect, $content, $conf]
1986 */
1987 public function hashDataProvider()
1988 {
1989 return [
1990 'md5' => [
1991 'bacb98acf97e0b6112b1d1b650b84971',
1992 'joh316',
1993 ['hash' => 'md5']
1994 ],
1995 'sha1' => [
1996 '063b3d108bed9f88fa618c6046de0dccadcf3158',
1997 'joh316',
1998 ['hash' => 'sha1']
1999 ],
2000 'stdWrap capability' => [
2001 'bacb98acf97e0b6112b1d1b650b84971',
2002 'joh316',
2003 [
2004 'hash' => '5',
2005 'hash.' => ['wrap' => 'md|']
2006 ]
2007 ],
2008 'non-existing hashing algorithm' => [
2009 '',
2010 'joh316',
2011 ['hash' => 'non-existing']
2012 ]
2013 ];
2014 }
2015
2016 /**
2017 * Check if stdWrap_hash works properly.
2018 *
2019 * Show:
2020 *
2021 * - Algorithms: sha1, md5
2022 * - Returns '' for invalid algorithm.
2023 * - Value can be processed by stdWrap.
2024 *
2025 * @test
2026 * @dataProvider hashDataProvider
2027 * @param string $expect The expected output.
2028 * @param string $content The given content.
2029 * @param array $conf The given configuration.
2030 * @return void
2031 */
2032 public function stdWrap_hash($expect, $content, $conf)
2033 {
2034 $this->assertSame($expect,
2035 $this->subject->stdWrap_hash($content, $conf));
2036 }
2037
2038 /**
2039 * @test
2040 */
2041 public function recursiveStdWrapProperlyRendersBasicString()
2042 {
2043 $stdWrapConfiguration = array(
2044 'noTrimWrap' => '|| 123|',
2045 'stdWrap.' => array(
2046 'wrap' => '<b>|</b>'
2047 )
2048 );
2049 $this->assertSame(
2050 '<b>Test</b> 123',
2051 $this->subject->stdWrap('Test', $stdWrapConfiguration)
2052 );
2053 }
2054
2055 /**
2056 * @test
2057 */
2058 public function recursiveStdWrapIsOnlyCalledOnce()
2059 {
2060 $stdWrapConfiguration = array(
2061 'append' => 'TEXT',
2062 'append.' => array(
2063 'data' => 'register:Counter'
2064 ),
2065 'stdWrap.' => array(
2066 'append' => 'LOAD_REGISTER',
2067 'append.' => array(
2068 'Counter.' => array(
2069 'prioriCalc' => 'intval',
2070 'cObject' => 'TEXT',
2071 'cObject.' => array(
2072 'data' => 'register:Counter',
2073 'wrap' => '|+1',
2074 )
2075 )
2076 )
2077 )
2078 );
2079 $this->assertSame(
2080 'Counter:1',
2081 $this->subject->stdWrap('Counter:', $stdWrapConfiguration)
2082 );
2083 }
2084
2085 /**
2086 * Data provider for the numberFormat test
2087 *
2088 * @return array multi-dimensional array with the second level like this:
2089 * @see numberFormat
2090 */
2091 public function numberFormatDataProvider()
2092 {
2093 $data = array(
2094 'testing decimals' => array(
2095 0.8,
2096 array(
2097 'decimals' => 2
2098 ),
2099 '0.80'
2100 ),
2101 'testing decimals with input as string' => array(
2102 '0.8',
2103 array(
2104 'decimals' => 2
2105 ),
2106 '0.80'
2107 ),
2108 'testing dec_point' => array(
2109 0.8,
2110 array(
2111 'decimals' => 1,
2112 'dec_point' => ','
2113 ),
2114 '0,8'
2115 ),
2116 'testing thousands_sep' => array(
2117 999.99,
2118 array(
2119 'decimals' => 0,
2120 'thousands_sep.' => array(
2121 'char' => 46
2122 )
2123 ),
2124 '1.000'
2125 ),
2126 'testing mixture' => array(
2127 1281731.45,
2128 array(
2129 'decimals' => 1,
2130 'dec_point.' => array(
2131 'char' => 44
2132 ),
2133 'thousands_sep.' => array(
2134 'char' => 46
2135 )
2136 ),
2137 '1.281.731,5'
2138 )
2139 );
2140 return $data;
2141 }
2142
2143 /**
2144 * Check if stdWrap.numberFormat and all of its properties work properly
2145 *
2146 * @dataProvider numberFormatDataProvider
2147 * @test
2148 */
2149 public function numberFormat($float, $formatConf, $expected)
2150 {
2151 $result = $this->subject->numberFormat($float, $formatConf);
2152 $this->assertEquals($expected, $result);
2153 }
2154
2155 /**
2156 * Check if stdWrap_replacement works properly.
2157 *
2158 * Show:
2159 *
2160 * - Delegates to method replacement.
2161 * - Parameter 1 is $content.
2162 * - Parameter 2 is $conf['replacement.'].
2163 * - Returns the return value.
2164 *
2165 * @test
2166 * @return void
2167 */
2168 public function stdWrap_replacement()
2169 {
2170 $content = $this->getUniqueId('content');
2171 $conf = [
2172 'replacement' => $this->getUniqueId('not used'),
2173 'replacement.' => [$this->getUniqueId('replacement.')],
2174 ];
2175 $return = $this->getUniqueId('return');
2176 $subject = $this->getMockBuilder(ContentObjectRenderer::class)
2177 ->setMethods(['replacement'])->getMock();
2178 $subject
2179 ->expects($this->once())
2180 ->method('replacement')
2181 ->with( $content, $conf['replacement.'])
2182 ->willReturn($return);
2183 $this->assertSame($return,
2184 $subject->stdWrap_replacement($content, $conf));
2185 }
2186
2187 /**
2188 * Data provider replacement
2189 *
2190 * @return array [$expect, $content, $conf]
2191 */
2192 public function replacementDataProvider()
2193 {
2194 return [
2195 'multiple replacements, including regex' => [
2196 'There is an animal, an animal and an animal around the block! Yeah!',
2197 'There_is_a_cat,_a_dog_and_a_tiger_in_da_hood!_Yeah!',
2198 [
2199 '20.' => [
2200 'search' => '_',
2201 'replace.' => ['char' => '32']
2202 ],
2203 '120.' => [
2204 'search' => 'in da hood',
2205 'replace' => 'around the block'
2206 ],
2207 '130.' => [
2208 'search' => '#a (Cat|Dog|Tiger)#i',
2209 'replace' => 'an animal',
2210 'useRegExp' => '1'
2211 ]
2212 ]
2213 ],
2214 'replacement with optionSplit, normal pattern' => [
2215 'There1is2a3cat,3a3dog3and3a3tiger3in3da3hood!3Yeah!',
2216 'There_is_a_cat,_a_dog_and_a_tiger_in_da_hood!_Yeah!',
2217 [
2218 '10.' => [
2219 'search' => '_',
2220 'replace' => '1 || 2 || 3',
2221 'useOptionSplitReplace' => '1'
2222 ]
2223 ]
2224 ],
2225 'replacement with optionSplit, using regex' => [
2226 'There is a tiny cat, a midsized dog and a big tiger in da hood! Yeah!',
2227 'There is a cat, a dog and a tiger in da hood! Yeah!',
2228 [
2229 '10.' => [
2230 'search' => '#(a) (Cat|Dog|Tiger)#i',
2231 'replace' => '${1} tiny ${2} || ${1} midsized ${2} || ${1} big ${2}',
2232 'useOptionSplitReplace' => '1',
2233 'useRegExp' => '1'
2234 ]
2235 ]
2236 ]
2237 ];
2238 }
2239
2240 /**
2241 * Check if stdWrap.replacement and all of its properties work properly
2242 *
2243 * @test
2244 * @dataProvider replacementDataProvider
2245 * @param string $content The given input.
2246 * @param string $expects The expected result.
2247 * @param array $conf The given configuration.
2248 * @return void
2249 */
2250 public function replacement($expects, $content, $conf)
2251 {
2252 $this->assertSame($expects,
2253 $this->subject->_call('replacement', $content, $conf));
2254 }
2255
2256 /**
2257 * @return array
2258 */
2259 public function stdWrapRawUrlEncodeDataProvider()
2260 {
2261 return [
2262 'https://typo3.org?id=10' => ['https://typo3.org?id=10', 'https%3A%2F%2Ftypo3.org%3Fid%3D10'],
2263 'https://typo3.org?id=10&foo=bar' => ['https://typo3.org?id=10&foo=bar', 'https%3A%2F%2Ftypo3.org%3Fid%3D10%26foo%3Dbar'],
2264 ];
2265 }
2266
2267 /**
2268 * Check if rawUrlEncode works properly
2269 *
2270 * @test
2271 * @dataProvider stdWrapRawUrlEncodeDataProvider
2272 */
2273 public function stdWrap_rawUrlEncode($input, $expected)
2274 {
2275 $this->assertEquals($expected, $this->subject->stdWrap_rawUrlEncode($input));
2276 }
2277
2278 /**
2279 * Data provider for the getQuery test
2280 *
2281 * @return array multi-dimensional array with the second level like this:
2282 * @see getQuery
2283 */
2284 public function getQueryDataProvider()
2285 {
2286 $data = array(
2287 'testing empty conf' => array(
2288 'tt_content',
2289 array(),
2290 array(
2291 'SELECT' => '*'
2292 )
2293 ),
2294 'testing #17284: adding uid/pid for workspaces' => array(
2295 'tt_content',
2296 array(
2297 'selectFields' => 'header,bodytext'
2298 ),
2299 array(
2300 'SELECT' => 'header,bodytext, tt_content.uid as uid, tt_content.pid as pid, tt_content.t3ver_state as t3ver_state'
2301 )
2302 ),
2303 'testing #17284: no need to add' => array(
2304 'tt_content',
2305 array(
2306 'selectFields' => 'tt_content.*'
2307 ),
2308 array(
2309 'SELECT' => 'tt_content.*'
2310 )
2311 ),
2312 'testing #17284: no need to add #2' => array(
2313 'tt_content',
2314 array(
2315 'selectFields' => '*'
2316 ),
2317 array(
2318 'SELECT' => '*'
2319 )
2320 ),
2321 'testing #29783: joined tables, prefix tablename' => array(
2322 'tt_content',
2323 array(
2324 'selectFields' => 'tt_content.header,be_users.username',
2325 'join' => 'be_users ON tt_content.cruser_id = be_users.uid'
2326 ),
2327 array(
2328 'SELECT' => 'tt_content.header,be_users.username, tt_content.uid as uid, tt_content.pid as pid, tt_content.t3ver_state as t3ver_state'
2329 )
2330 ),
2331 'testing #34152: single count(*), add nothing' => array(
2332 'tt_content',
2333 array(
2334 'selectFields' => 'count(*)'
2335 ),
2336 array(
2337 'SELECT' => 'count(*)'
2338 )
2339 ),
2340 'testing #34152: single max(crdate), add nothing' => array(
2341 'tt_content',
2342 array(
2343 'selectFields' => 'max(crdate)'
2344 ),
2345 array(
2346 'SELECT' => 'max(crdate)'
2347 )
2348 ),
2349 'testing #34152: single min(crdate), add nothing' => array(
2350 'tt_content',
2351 array(
2352 'selectFields' => 'min(crdate)'
2353 ),
2354 array(
2355 'SELECT' => 'min(crdate)'
2356 )
2357 ),
2358 'testing #34152: single sum(is_siteroot), add nothing' => array(
2359 'tt_content',
2360 array(
2361 'selectFields' => 'sum(is_siteroot)'
2362 ),
2363 array(
2364 'SELECT' => 'sum(is_siteroot)'
2365 )
2366 ),
2367 'testing #34152: single avg(crdate), add nothing' => array(
2368 'tt_content',
2369 array(
2370 'selectFields' => 'avg(crdate)'
2371 ),
2372 array(
2373 'SELECT' => 'avg(crdate)'
2374 )
2375 )
2376 );
2377 return $data;
2378 }
2379
2380 /**
2381 * Check if sanitizeSelectPart works as expected
2382 *
2383 * @dataProvider getQueryDataProvider
2384 * @test
2385 */
2386 public function getQuery($table, $conf, $expected)
2387 {
2388 $GLOBALS['TCA'] = array(
2389 'pages' => array(
2390 'ctrl' => array(
2391 'enablecolumns' => array(
2392 'disabled' => 'hidden'
2393 )
2394 )
2395 ),
2396 'tt_content' => array(
2397 'ctrl' => array(
2398 'enablecolumns' => array(
2399 'disabled' => 'hidden'
2400 ),
2401 'versioningWS' => true
2402 )
2403 ),
2404 );
2405 $result = $this->subject->getQuery($table, $conf, true);
2406 foreach ($expected as $field => $value) {
2407 $this->assertEquals($value, $result[$field]);
2408 }
2409 }
2410
2411 /**
2412 * @test
2413 */
2414 public function getQueryCallsGetTreeListWithNegativeValuesIfRecursiveIsSet()
2415 {
2416 $GLOBALS['TCA'] = array(
2417 'pages' => array(
2418 'ctrl' => array(
2419 'enablecolumns' => array(
2420 'disabled' => 'hidden'
2421 )
2422 )
2423 ),
2424 'tt_content' => array(
2425 'ctrl' => array(
2426 'enablecolumns' => array(
2427 'disabled' => 'hidden'
2428 )
2429 )
2430 ),
2431 );
2432 $this->subject = $this->getAccessibleMock(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class, array('getTreeList'));
2433 $this->subject->start(array(), 'tt_content');
2434 $conf = array(
2435 'recursive' => '15',
2436 'pidInList' => '16, -35'
2437 );
2438 $this->subject->expects($this->at(0))
2439 ->method('getTreeList')
2440 ->with(-16, 15)
2441 ->will($this->returnValue('15,16'));
2442 $this->subject->expects($this->at(1))
2443 ->method('getTreeList')
2444 ->with(-35, 15)
2445 ->will($this->returnValue('15,35'));
2446 $this->subject->getQuery('tt_content', $conf, true);
2447 }
2448
2449 /**
2450 * @test
2451 */
2452 public function getQueryCallsGetTreeListWithCurrentPageIfThisIsSet()
2453 {
2454 $GLOBALS['TCA'] = array(
2455 'pages' => array(
2456 'ctrl' => array(
2457 'enablecolumns' => array(
2458 'disabled' => 'hidden'
2459 )
2460 )
2461 ),
2462 'tt_content' => array(
2463 'ctrl' => array(
2464 'enablecolumns' => array(
2465 'disabled' => 'hidden'
2466 )
2467 )
2468 ),
2469 );
2470 $this->subject = $this->getAccessibleMock(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class, array('getTreeList'));
2471 $GLOBALS['TSFE']->id = 27;
2472 $this->subject->start(array(), 'tt_content');
2473 $conf = array(
2474 'pidInList' => 'this',
2475 'recursive' => '4'
2476 );
2477 $this->subject->expects($this->once())
2478 ->method('getTreeList')
2479 ->with(-27)
2480 ->will($this->returnValue('27'));
2481 $this->subject->getQuery('tt_content', $conf, true);
2482 }
2483
2484 /**
2485 * Data provider for the stdWrap_date test
2486 *
2487 * @return array [$expect, $content, $conf, $now]
2488 */
2489 public function stdWrap_dateDataProvider()
2490 {
2491 // Fictive execution time: 2015-10-02 12:00
2492 $now = 1443780000;
2493 return [
2494 'given timestamp' => [
2495 '02.10.2015',
2496 $now,
2497 ['date' => 'd.m.Y'],
2498 $now
2499 ],
2500 'empty string' => [
2501 '02.10.2015',
2502 '',
2503 ['date' => 'd.m.Y'],
2504 $now
2505 ],
2506 'testing null' => [
2507 '02.10.2015',
2508 null,
2509 ['date' => 'd.m.Y'],
2510 $now
2511 ],
2512 'given timestamp return GMT' => [
2513 '02.10.2015 10:00:00',
2514 $now,
2515 [
2516 'date' => 'd.m.Y H:i:s',
2517 'date.' => ['GMT' => true],
2518 ],
2519 $now
2520 ]
2521 ];
2522 }
2523
2524 /**
2525 * Check if stdWrap_date works properly.
2526 *
2527 * @test
2528 * @dataProvider stdWrap_dateDataProvider
2529 * @param string $expected The expected output.
2530 * @param mixed $content The given input.
2531 * @param array $conf The given configuration.
2532 * @param int $now Fictive execution time.
2533 * @return void
2534 */
2535 public function stdWrap_date($expected, $content, $conf, $now)
2536 {
2537 $GLOBALS['EXEC_TIME'] = $now;
2538 $this->assertEquals($expected,
2539 $this->subject->stdWrap_date($content, $conf));
2540 }
2541
2542 /**
2543 * Data provider for stdWrap_strftime
2544 *
2545 * @return array [$expect, $content, $conf, $now]
2546 */
2547 public function stdWrap_strftimeDataProvider()
2548 {
2549 // Fictive execution time is 2012-09-01 12:00 in UTC/GMT.
2550 $now = 1346500800;
2551 return [
2552 'given timestamp' => [
2553 '01-09-2012',
2554 $now,
2555 ['strftime' => '%d-%m-%Y'],
2556 $now
2557 ],
2558 'empty string' => [
2559 '01-09-2012',
2560 '',
2561 ['strftime' => '%d-%m-%Y'],
2562 $now
2563 ],
2564 'testing null' => [
2565 '01-09-2012',
2566 null,
2567 ['strftime' => '%d-%m-%Y'],
2568 $now
2569 ]
2570 ];
2571 }
2572
2573 /**
2574 * Check if stdWrap_strftime works properly.
2575 *
2576 * @test
2577 * @dataProvider stdWrap_strftimeDataProvider
2578 * @param string $expect The expected output.
2579 * @param mixed $content The given input.
2580 * @param array $conf The given configuration.
2581 * @param int $now Fictive execution time.
2582 * @return void
2583 */
2584 public function stdWrap_strftime($expect, $content, $conf, $now)
2585 {
2586 // Save current timezone and set to UTC to make the system under test
2587 // behave the same in all server timezone settings
2588 $timezoneBackup = date_default_timezone_get();
2589 date_default_timezone_set('UTC');
2590
2591 $GLOBALS['EXEC_TIME'] = $now;
2592 $result = $this->subject->stdWrap_strftime($content, $conf);
2593
2594 // Reset timezone
2595 date_default_timezone_set($timezoneBackup);
2596
2597 $this->assertSame($expect, $result);
2598 }
2599
2600 /**
2601 * Data provider for the stdWrap_strtotime test
2602 *
2603 * @return array [$expect, $content, $conf]
2604 */
2605 public function stdWrap_strtotimeDataProvider()
2606 {
2607 return [
2608 'date from content' => [
2609 1417651200, '2014-12-04',
2610 ['strtotime' => '1']
2611 ],
2612 'manipulation of date from content' => [
2613 1417996800, '2014-12-04',
2614 ['strtotime' => '+ 2 weekdays']
2615 ],
2616 'date from configuration' => [
2617 1417651200, '',
2618 ['strtotime' => '2014-12-04']
2619 ],
2620 'manipulation of date from configuration' => [
2621 1417996800, '',
2622 ['strtotime' => '2014-12-04 + 2 weekdays']
2623 ],
2624 'empty input' => [
2625 false, '',
2626 ['strtotime' => '1']
2627 ],
2628 'date from content and configuration' => [
2629 false, '2014-12-04',
2630 ['strtotime' => '2014-12-05']
2631 ]
2632 ];
2633 }
2634
2635 /**
2636 * Check if stdWrap_strtotime works properly.
2637 *
2638 * @test
2639 * @dataProvider stdWrap_strtotimeDataProvider
2640 * @param int $expect The expected output.
2641 * @param mixed $content The given input.
2642 * @param array $conf The given configuration.
2643 * @return void
2644 */
2645 public function stdWrap_strtotime($expect, $content, $conf)
2646 {
2647 // Set exec_time to a hard timestamp
2648 $GLOBALS['EXEC_TIME'] = 1417392000;
2649 // Save current timezone and set to UTC to make the system under test
2650 // behave the same in all server timezone settings
2651 $timezoneBackup = date_default_timezone_get();
2652 date_default_timezone_set('UTC');
2653
2654 $result = $this->subject->stdWrap_strtotime($content, $conf);
2655
2656 // Reset timezone
2657 date_default_timezone_set($timezoneBackup);
2658
2659 $this->assertEquals($expect, $result);
2660 }
2661
2662 /**
2663 * @test
2664 */
2665 public function stdWrap_ageCallsCalcAgeWithSubtractedTimestampAndSubPartOfArray()
2666 {
2667 $subject = $this->getMockBuilder(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class)
2668 ->setMethods(array('calcAge'))
2669 ->getMock();
2670 // Set exec_time to a hard timestamp
2671 $GLOBALS['EXEC_TIME'] = 10;
2672 $subject->expects($this->once())->method('calcAge')->with(1, 'Min| Hrs| Days| Yrs');
2673 $subject->stdWrap_age(9, array('age' => 'Min| Hrs| Days| Yrs'));
2674 }
2675
2676 /**
2677 * Data provider for calcAgeCalculatesAgeOfTimestamp
2678 *
2679 * @return array
2680 * @see calcAge
2681 */
2682 public function calcAgeCalculatesAgeOfTimestampDataProvider()
2683 {
2684 return array(
2685 'minutes' => array(
2686 120,
2687 ' min| hrs| days| yrs',
2688 '2 min',
2689 ),
2690 'hours' => array(
2691 7200,
2692 ' min| hrs| days| yrs',
2693 '2 hrs',
2694 ),
2695 'days' => array(
2696 604800,
2697 ' min| hrs| days| yrs',
2698 '7 days',
2699 ),
2700 'day with provided singular labels' => array(
2701 86400,
2702 ' min| hrs| days| yrs| min| hour| day| year',
2703 '1 day',
2704 ),
2705 'years' => array(
2706 1417997800,
2707 ' min| hrs| days| yrs',
2708 '45 yrs',
2709 ),
2710 'different labels' => array(
2711 120,
2712 ' Minutes| Hrs| Days| Yrs',
2713 '2 Minutes',
2714 ),
2715 'negative values' => array(
2716 -604800,
2717 ' min| hrs| days| yrs',
2718 '-7 days',
2719 ),
2720 'default label values for wrong label input' => array(
2721 121,
2722 10,
2723 '2 min',
2724 ),
2725 'default singular label values for wrong label input' => array(
2726 31536000,
2727 10,
2728 '1 year',
2729 )
2730 );
2731 }
2732
2733 /**
2734 * @param int $timestamp
2735 * @param string $labels
2736 * @param int $expectation
2737 * @dataProvider calcAgeCalculatesAgeOfTimestampDataProvider
2738 * @test
2739 */
2740 public function calcAgeCalculatesAgeOfTimestamp($timestamp, $labels, $expectation)
2741 {
2742 $result = $this->subject->calcAge($timestamp, $labels);
2743 $this->assertEquals($result, $expectation);
2744 }
2745
2746 /**
2747 * @return array
2748 */
2749 public function stdWrapReturnsExpectationDataProvider()
2750 {
2751 return [
2752 'Prevent silent bool conversion' => [
2753 '1+1',
2754 [
2755 'prioriCalc.' => [
2756 'wrap' => '|',
2757 ],
2758 ],
2759 '1+1',
2760 ],
2761 ];
2762 }
2763
2764 /**
2765 * @param string $content
2766 * @param array $configuration
2767 * @param string $expectation
2768 * @dataProvider stdWrapReturnsExpectationDataProvider
2769 * @test
2770 */
2771 public function stdWrapReturnsExpectation($content, array $configuration, $expectation)
2772 {
2773 $this->assertSame($expectation, $this->subject->stdWrap($content, $configuration));
2774 }
2775
2776 /**
2777 * Data provider for stdWrap_case test
2778 *
2779 * @return array
2780 */
2781 public function stdWrap_caseDataProvider()
2782 {
2783 return array(
2784 'lower case text to upper' => array(
2785 '<span>text</span>',
2786 array(
2787 'case' => 'upper',
2788 ),
2789 '<span>TEXT</span>',
2790 ),
2791 'upper case text to lower' => array(
2792 '<span>TEXT</span>',
2793 array(
2794 'case' => 'lower',
2795 ),
2796 '<span>text</span>',
2797 ),
2798 'capitalize text' => array(
2799 '<span>this is a text</span>',
2800 array(
2801 'case' => 'capitalize',
2802 ),
2803 '<span>This Is A Text</span>',
2804 ),
2805 'ucfirst text' => array(
2806 '<span>this is a text</span>',
2807 array(
2808 'case' => 'ucfirst',
2809 ),
2810 '<span>This is a text</span>',
2811 ),
2812 'lcfirst text' => array(
2813 '<span>This is a Text</span>',
2814 array(
2815 'case' => 'lcfirst',
2816 ),
2817 '<span>this is a Text</span>',
2818 ),
2819 'uppercamelcase text' => array(
2820 '<span>this_is_a_text</span>',
2821 array(
2822 'case' => 'uppercamelcase',
2823 ),
2824 '<span>ThisIsAText</span>',
2825 ),
2826 'lowercamelcase text' => array(
2827 '<span>this_is_a_text</span>',
2828 array(
2829 'case' => 'lowercamelcase',
2830 ),
2831 '<span>thisIsAText</span>',
2832 ),
2833 );
2834 }
2835
2836 /**
2837 * @param string|NULL $content
2838 * @param array $configuration
2839 * @param string $expected
2840 * @dataProvider stdWrap_caseDataProvider
2841 * @test
2842 */
2843 public function stdWrap_case($content, array $configuration, $expected)
2844 {
2845 $result = $this->subject->stdWrap_case($content, $configuration);
2846 $this->assertEquals($expected, $result);
2847 }
2848
2849 /**
2850 * Data provider for stdWrap_bytes test
2851 *
2852 * @return array
2853 */
2854 public function stdWrap_bytesDataProvider()
2855 {
2856 return array(
2857 'value 1234 default' => array(
2858 '1234',
2859 array(
2860 'bytes.' => array(
2861 'labels' => '',
2862 'base' => 0,
2863 ),
2864 ),
2865 '1.21 Ki',
2866 'en_US.UTF-8'
2867 ),
2868 'value 1234 si' => array(
2869 '1234',
2870 array(
2871 'bytes.' => array(
2872 'labels' => 'si',
2873 'base' => 0,
2874 ),
2875 ),
2876 '1.23 k',
2877 'en_US.UTF-8'
2878 ),
2879 'value 1234 iec' => array(
2880 '1234',
2881 array(
2882 'bytes.' => array(
2883 'labels' => 'iec',
2884 'base' => 0,
2885 ),
2886 ),
2887 '1.21 Ki',
2888 'en_US.UTF-8'
2889 ),
2890 'value 1234 a-i' => array(
2891 '1234',
2892 array(
2893 'bytes.' => array(
2894 'labels' => 'a|b|c|d|e|f|g|h|i',
2895 'base' => 1000,
2896 ),
2897 ),
2898 '1.23b',
2899 'en_US.UTF-8'
2900 ),
2901 'value 1234 a-i invalid base' => array(
2902 '1234',
2903 array(
2904 'bytes.' => array(
2905 'labels' => 'a|b|c|d|e|f|g|h|i',
2906 'base' => 54,
2907 ),
2908 ),
2909 '1.21b',
2910 'en_US.UTF-8'
2911 ),
2912 'value 1234567890 default' => array(
2913 '1234567890',
2914 array(
2915 'bytes.' => array(
2916 'labels' => '',
2917 'base' => 0,
2918 ),
2919 ),
2920 '1.15 Gi',
2921 'en_US.UTF-8'
2922 ),
2923 );
2924 }
2925
2926 /**
2927 * @param string|NULL $content
2928 * @param array $configuration
2929 * @param string $expected
2930 * @dataProvider stdWrap_bytesDataProvider
2931 * @test
2932 */
2933 public function stdWrap_bytes($content, array $configuration, $expected, $locale)
2934 {
2935 if (!setlocale(LC_NUMERIC, $locale)) {
2936 $this->markTestSkipped('Locale ' . $locale . ' is not available.');
2937 }
2938 $result = $this->subject->stdWrap_bytes($content, $configuration);
2939 $this->assertSame($expected, $result);
2940 }
2941
2942 /**
2943 * Data provider for stdWrap_substring test
2944 *
2945 * @return array
2946 */
2947 public function stdWrap_substringDataProvider()
2948 {
2949 return array(
2950 'sub -1' => array(
2951 'substring',
2952 array(
2953 'substring' => '-1',
2954 ),
2955 'g',
2956 ),
2957 'sub -1,0' => array(
2958 'substring',
2959 array(
2960 'substring' => '-1,0',
2961 ),
2962 'g',
2963 ),
2964 'sub -1,-1' => array(
2965 'substring',
2966 array(
2967 'substring' => '-1,-1',
2968 ),
2969 '',
2970 ),
2971 'sub -1,1' => array(
2972 'substring',
2973 array(
2974 'substring' => '-1,1',
2975 ),
2976 'g',
2977 ),
2978 'sub 0' => array(
2979 'substring',
2980 array(
2981 'substring' => '0',
2982 ),
2983 'substring',
2984 ),
2985 'sub 0,0' => array(
2986 'substring',
2987 array(
2988 'substring' => '0,0',
2989 ),
2990 'substring',
2991 ),
2992 'sub 0,-1' => array(
2993 'substring',
2994 array(
2995 'substring' => '0,-1',
2996 ),
2997 'substrin',
2998 ),
2999 'sub 0,1' => array(
3000 'substring',
3001 array(
3002 'substring' => '0,1',
3003 ),
3004 's',
3005 ),
3006 'sub 1' => array(
3007 'substring',
3008 array(
3009 'substring' => '1',
3010 ),
3011 'ubstring',
3012 ),
3013 'sub 1,0' => array(
3014 'substring',
3015 array(
3016 'substring' => '1,0',
3017 ),
3018 'ubstring',
3019 ),
3020 'sub 1,-1' => array(
3021 'substring',
3022 array(
3023 'substring' => '1,-1',
3024 ),
3025 'ubstrin',
3026 ),
3027 'sub 1,1' => array(
3028 'substring',
3029 array(
3030 'substring' => '1,1',
3031 ),
3032 'u',
3033 ),
3034 'sub' => array