[BUGFIX] Standalone- and TemplateView must not require ucfirst file names
[Packages/TYPO3.CMS.git] / typo3 / sysext / fluid / Tests / Unit / View / TemplateViewTest.php
1 <?php
2 namespace TYPO3\CMS\Fluid\Tests\Unit\View;
3
4 /* *
5 * This script is backported from the TYPO3 Flow package "TYPO3.Fluid". *
6 * *
7 * It is free software; you can redistribute it and/or modify it under *
8 * the terms of the GNU Lesser General Public License, either version 3 *
9 * of the License, or (at your option) any later version. *
10 * *
11 * The TYPO3 project - inspiring people to share! *
12 * */
13
14 include_once(__DIR__ . '/Fixtures/TransparentSyntaxTreeNode.php');
15 include_once(__DIR__ . '/Fixtures/TemplateViewFixture.php');
16
17 use org\bovigo\vfs\vfsStreamWrapper;
18 use TYPO3\CMS\Core\Cache\CacheManager;
19 use TYPO3\CMS\Core\Cache\Frontend\PhpFrontend;
20 use TYPO3\CMS\Core\Tests\AccessibleObjectInterface;
21 use TYPO3\CMS\Core\Tests\UnitTestCase;
22 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
23 use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
24 use TYPO3\CMS\Extbase\Mvc\Web\Request as WebRequest;
25 use TYPO3\CMS\Extbase\Object\ObjectManager;
26 use TYPO3\CMS\Fluid\Core\Compiler\TemplateCompiler;
27 use TYPO3\CMS\Fluid\Core\Parser\ParsedTemplateInterface;
28 use TYPO3\CMS\Fluid\Core\Parser\TemplateParser;
29 use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
30 use TYPO3\CMS\Fluid\Core\ViewHelper\ViewHelperVariableContainer;
31 use TYPO3\CMS\Fluid\View\TemplateView;
32 use TYPO3\CMS\Core\Utility\GeneralUtility;
33 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
34
35 /**
36 * Test case
37 */
38 class TemplateViewTest extends UnitTestCase {
39
40 /**
41 * Test for #42123
42 * "Widgets with underscores in class names do not work because the subpackage key is not handled correctly."
43 * @test
44 */
45 public function expandGenericPathPatternWorksWithOldNamingSchemeOfSubPackage() {
46 $mockControllerContext = $this->setupMockControllerContextForPathResolving('MyPackage', 'ViewHelpers_Widget', 'Paginate', 'html');
47 $templateView = $this->getAccessibleMock(TemplateView::class, array('dummy'), array(), '', FALSE);
48 $templateView->_set('controllerContext', $mockControllerContext);
49 $expected = array(ExtensionManagementUtility::extPath('frontend') . 'Resources/Private/Templates/ViewHelpers/Widget/Paginate/@action.html');
50 $actual = $templateView->_call('expandGenericPathPattern', '@templateRoot/@subpackage/@controller/@action.@format', FALSE, FALSE);
51 $this->assertEquals($expected, $actual);
52 }
53
54 /**
55 * Test for #42123
56 * "Widgets with underscores in class names do not work because the subpackage key is not handled correctly."
57 * @test
58 */
59 public function expandGenericPathPatternWorksWithNewNamingSchemeOfSubPackage() {
60 $mockControllerContext = $this->setupMockControllerContextForPathResolving('MyPackage', 'ViewHelpers\\Widget', 'Paginate', 'html');
61 $templateView = $this->getAccessibleMock(TemplateView::class, array('dummy'), array(), '', FALSE);
62 $templateView->_set('controllerContext', $mockControllerContext);
63 $expected = array(ExtensionManagementUtility::extPath('frontend') . 'Resources/Private/Templates/ViewHelpers/Widget/Paginate/@action.html');
64 $actual = $templateView->_call('expandGenericPathPattern', '@templateRoot/@subpackage/@controller/@action.@format', FALSE, FALSE);
65 $this->assertEquals($expected, $actual);
66 }
67
68 /**
69 * Helper to build mock controller context needed to test expandGenericPathPattern.
70 *
71 * @param string $packageKey
72 * @param string $subPackageKey
73 * @param string $controllerName
74 * @param string $format
75 * @return ControllerContext
76 */
77 protected function setupMockControllerContextForPathResolving($packageKey, $subPackageKey, $controllerName, $format) {
78 $controllerObjectName = "TYPO3\\$packageKey\\" . ($subPackageKey != $subPackageKey . '\\' ? : '') . 'Controller\\' . $controllerName . 'Controller';
79 $mockRequest = $this->getMock(WebRequest::class);
80 $mockRequest->expects($this->any())->method('getControllerExtensionKey')->will($this->returnValue('frontend'));
81 $mockRequest->expects($this->any())->method('getControllerPackageKey')->will($this->returnValue($packageKey));
82 $mockRequest->expects($this->any())->method('getControllerSubPackageKey')->will($this->returnValue($subPackageKey));
83 $mockRequest->expects($this->any())->method('getControllerName')->will($this->returnValue($controllerName));
84 $mockRequest->expects($this->any())->method('getControllerObjectName')->will($this->returnValue($controllerObjectName));
85 $mockRequest->expects($this->any())->method('getFormat')->will($this->returnValue($format));
86
87 $mockControllerContext = $this->getMock(ControllerContext::class, array('getRequest'), array(), '', FALSE);
88 $mockControllerContext->expects($this->any())->method('getRequest')->will($this->returnValue($mockRequest));
89
90 return $mockControllerContext;
91 }
92
93 /**
94 * @return array
95 */
96 public function expandGenericPathPatternDataProvider() {
97 return array(
98 // bubbling controller & subpackage parts and optional format
99 array(
100 'package' => 'Some.Package',
101 'subPackage' => 'Some\\Sub\\Package',
102 'controller' => 'SomeController',
103 'format' => 'html',
104 'templateRootPath' => 'Resources/Private/Templates',
105 'templateRootPaths' => NULL,
106 'partialRootPath' => 'Resources/Private/Partials',
107 'partialRootPaths' => NULL,
108 'layoutRootPath' => 'Resources/Private/Layouts',
109 'layoutRootPaths' => NULL,
110 'bubbleControllerAndSubpackage' => TRUE,
111 'formatIsOptional' => TRUE,
112 'pattern' => '@templateRoot/@subpackage/@controller/@action.@format',
113 'expectedResult' => array(
114 'Resources/Private/Templates/Some/Sub/Package/SomeController/@action.html',
115 'Resources/Private/Templates/Some/Sub/Package/SomeController/@action',
116 'Resources/Private/Templates/Some/Sub/Package/@action.html',
117 'Resources/Private/Templates/Some/Sub/Package/@action',
118 'Resources/Private/Templates/Sub/Package/@action.html',
119 'Resources/Private/Templates/Sub/Package/@action',
120 'Resources/Private/Templates/Package/@action.html',
121 'Resources/Private/Templates/Package/@action',
122 'Resources/Private/Templates/@action.html',
123 'Resources/Private/Templates/@action',
124 )
125 ),
126 // just optional format
127 array(
128 'package' => 'Some.Package',
129 'subPackage' => 'Some\\Sub\\Package',
130 'controller' => 'SomeController',
131 'format' => 'html',
132 'templateRootPath' => 'Resources/Private/Templates/',
133 'templateRootPaths' => NULL,
134 'partialRootPath' => 'Resources/Private/Partials',
135 'partialRootPaths' => NULL,
136 'layoutRootPath' => 'Resources/Private/Layouts',
137 'layoutRootPaths' => NULL,
138 'bubbleControllerAndSubpackage' => FALSE,
139 'formatIsOptional' => TRUE,
140 'pattern' => '@templateRoot/@subpackage/@controller/@action.@format',
141 'expectedResult' => array(
142 'Resources/Private/Templates/Some/Sub/Package/SomeController/@action.html',
143 'Resources/Private/Templates/Some/Sub/Package/SomeController/@action',
144 )
145 ),
146 // just bubbling controller & subpackage parts
147 array(
148 'package' => 'Some.Package',
149 'subPackage' => 'Some\\Sub\\Package',
150 'controller' => 'SomeController',
151 'format' => 'json',
152 'templateRootPath' => 'Resources/Private/Templates',
153 'templateRootPaths' => NULL,
154 'partialRootPath' => 'Resources/Private/Partials',
155 'partialRootPaths' => NULL,
156 'layoutRootPath' => 'Resources/Private/Layouts',
157 'layoutRootPaths' => NULL,
158 'bubbleControllerAndSubpackage' => TRUE,
159 'formatIsOptional' => FALSE,
160 'pattern' => '@partialRoot/@subpackage/@controller/@action.@format',
161 'expectedResult' => array(
162 'Resources/Private/Partials/Some/Sub/Package/SomeController/@action.json',
163 'Resources/Private/Partials/Some/Sub/Package/@action.json',
164 'Resources/Private/Partials/Sub/Package/@action.json',
165 'Resources/Private/Partials/Package/@action.json',
166 'Resources/Private/Partials/@action.json',
167 )
168 ),
169 // layoutRootPath
170 array(
171 'package' => 'Some.Package',
172 'subPackage' => NULL,
173 'controller' => NULL,
174 'format' => 'xml',
175 'templateRootPath' => 'Resources/Private/Templates',
176 'templateRootPaths' => NULL,
177 'partialRootPath' => 'Resources/Private/Partials',
178 'partialRootPaths' => NULL,
179 'layoutRootPath' => 'Resources/Private/Layouts',
180 'layoutRootPaths' => NULL,
181 'bubbleControllerAndSubpackage' => TRUE,
182 'formatIsOptional' => TRUE,
183 'pattern' => '@layoutRoot/@subpackage/@controller/@action.@format',
184 'expectedResult' => array(
185 'Resources/Private/Layouts/@action.xml',
186 'Resources/Private/Layouts/@action',
187 )
188 ),
189 // partialRootPath
190 array(
191 'package' => 'Some.Package',
192 'subPackage' => 'Some\\Sub\\Package',
193 'controller' => NULL,
194 'format' => 'html',
195 'templateRootPath' => 'Resources/Private/Templates',
196 'templateRootPaths' => NULL,
197 'partialRootPath' => 'Resources/Private/Partials',
198 'partialRootPaths' => NULL,
199 'layoutRootPath' => 'Resources/Private/Layouts',
200 'layoutRootPaths' => NULL,
201 'bubbleControllerAndSubpackage' => TRUE,
202 'formatIsOptional' => TRUE,
203 'pattern' => '@templateRoot/@subpackage/@controller/@action.@format',
204 'expectedResult' => array(
205 'Resources/Private/Templates/Some/Sub/Package/@action.html',
206 'Resources/Private/Templates/Some/Sub/Package/@action',
207 'Resources/Private/Templates/Sub/Package/@action.html',
208 'Resources/Private/Templates/Sub/Package/@action',
209 'Resources/Private/Templates/Package/@action.html',
210 'Resources/Private/Templates/Package/@action',
211 'Resources/Private/Templates/@action.html',
212 'Resources/Private/Templates/@action',
213 )
214 ),
215 // optional format as directory name
216 array(
217 'package' => 'Some.Package',
218 'subPackage' => 'Some\\Sub\\Package',
219 'controller' => 'SomeController',
220 'format' => 'xml',
221 'templateRootPath' => 'Resources/Private/Templates_@format',
222 'templateRootPaths' => NULL,
223 'partialRootPath' => 'Resources/Private/Partials',
224 'partialRootPaths' => NULL,
225 'layoutRootPath' => 'Resources/Private/Layouts',
226 'layoutRootPaths' => NULL,
227 'bubbleControllerAndSubpackage' => FALSE,
228 'formatIsOptional' => TRUE,
229 'pattern' => '@templateRoot/@subpackage/@controller/@action',
230 'expectedResult' => array(
231 'Resources/Private/Templates_xml/Some/Sub/Package/SomeController/@action',
232 'Resources/Private/Templates_/Some/Sub/Package/SomeController/@action',
233 )
234 ),
235 // mandatory format as directory name
236 array(
237 'package' => 'Some.Package',
238 'subPackage' => 'Some\\Sub\\Package',
239 'controller' => 'SomeController',
240 'format' => 'json',
241 'templateRootPath' => 'Resources/Private/Templates_@format',
242 'templateRootPaths' => NULL,
243 'partialRootPath' => 'Resources/Private/Partials',
244 'partialRootPaths' => NULL,
245 'layoutRootPath' => 'Resources/Private/Layouts',
246 'layoutRootPaths' => NULL,
247 'bubbleControllerAndSubpackage' => FALSE,
248 'formatIsOptional' => FALSE,
249 'pattern' => '@templateRoot/@subpackage/@controller/@action',
250 'expectedResult' => array(
251 'Resources/Private/Templates_json/Some/Sub/Package/SomeController/@action',
252 )
253 ),
254 // paths must not contain double slashes
255 array(
256 'package' => 'Some.Package',
257 'subPackage' => NULL,
258 'controller' => 'SomeController',
259 'format' => 'html',
260 'templateRootPath' => 'Resources/Private/Templates',
261 'templateRootPaths' => NULL,
262 'partialRootPath' => 'Resources/Private/Partials',
263 'partialRootPaths' => NULL,
264 'layoutRootPath' => 'Some/Root/Path/',
265 'layoutRootPaths' => NULL,
266 'bubbleControllerAndSubpackage' => TRUE,
267 'formatIsOptional' => TRUE,
268 'pattern' => '@layoutRoot/@subpackage/@controller/@action.@format',
269 'expectedResult' => array(
270 'Some/Root/Path/SomeController/@action.html',
271 'Some/Root/Path/SomeController/@action',
272 'Some/Root/Path/@action.html',
273 'Some/Root/Path/@action',
274 )
275 ),
276 // paths must be unique
277 array(
278 'package' => 'Some.Package',
279 'subPackage' => 'Some\\Sub\\Package',
280 'controller' => 'SomeController',
281 'format' => 'json',
282 'templateRootPath' => 'Resources/Private/Templates',
283 'templateRootPaths' => NULL,
284 'partialRootPath' => 'Resources/Private/Partials',
285 'partialRootPaths' => NULL,
286 'layoutRootPath' => 'Resources/Private/Layouts',
287 'layoutRootPaths' => NULL,
288 'bubbleControllerAndSubpackage' => TRUE,
289 'formatIsOptional' => FALSE,
290 'pattern' => 'foo',
291 'expectedResult' => array(
292 'foo',
293 )
294 ),
295 // template fallback paths
296 array(
297 'package' => 'Some.Package',
298 'subPackage' => 'Some\\Sub\\Package',
299 'controller' => 'SomeController',
300 'format' => 'html',
301 'templateRootPath' => 'Resources/Private/Templates',
302 'templateRootPaths' => array('Resources/Private/Templates', 'Some/Fallback/Path'),
303 'partialRootPath' => 'Resources/Private/Partials',
304 'partialRootPaths' => NULL,
305 'layoutRootPath' => 'Resources/Private/Layouts',
306 'layoutRootPaths' => NULL,
307 'bubbleControllerAndSubpackage' => FALSE,
308 'formatIsOptional' => TRUE,
309 'pattern' => '@templateRoot/@subpackage/@controller/@action.@format',
310 'expectedResult' => array(
311 'Resources/Private/Templates/Some/Sub/Package/SomeController/@action.html',
312 'Resources/Private/Templates/Some/Sub/Package/SomeController/@action',
313 'Some/Fallback/Path/Some/Sub/Package/SomeController/@action.html',
314 'Some/Fallback/Path/Some/Sub/Package/SomeController/@action',
315 )
316 ),
317 // template fallback paths with bubbleControllerAndSubpackage
318 array(
319 'package' => 'Some.Package',
320 'subPackage' => 'Some\\Sub\\Package',
321 'controller' => 'SomeController',
322 'format' => 'html',
323 'templateRootPath' => 'Resources/Private/Templates',
324 'templateRootPaths' => array('Resources/Private/Templates', 'Some/Fallback/Path'),
325 'partialRootPath' => 'Resources/Private/Partials',
326 'partialRootPaths' => NULL,
327 'layoutRootPath' => 'Resources/Private/Layouts',
328 'layoutRootPaths' => NULL,
329 'bubbleControllerAndSubpackage' => TRUE,
330 'formatIsOptional' => FALSE,
331 'pattern' => '@templateRoot/@subpackage/@controller/@action.@format',
332 'expectedResult' => array(
333 'Resources/Private/Templates/Some/Sub/Package/SomeController/@action.html',
334 'Resources/Private/Templates/Some/Sub/Package/@action.html',
335 'Resources/Private/Templates/Sub/Package/@action.html',
336 'Resources/Private/Templates/Package/@action.html',
337 'Resources/Private/Templates/@action.html',
338 'Some/Fallback/Path/Some/Sub/Package/SomeController/@action.html',
339 'Some/Fallback/Path/Some/Sub/Package/@action.html',
340 'Some/Fallback/Path/Sub/Package/@action.html',
341 'Some/Fallback/Path/Package/@action.html',
342 'Some/Fallback/Path/@action.html',
343 )
344 ),
345 // partial fallback paths
346 array(
347 'package' => 'Some.Package',
348 'subPackage' => 'Some\\Sub\\Package',
349 'controller' => 'SomeController',
350 'format' => 'html',
351 'templateRootPath' => 'Resources/Private/Templates',
352 'templateRootPaths' => NULL,
353 'partialRootPath' => 'Resources/Private/Partials',
354 'partialRootPaths' => array('Default/Resources/Path', 'Fallback/'),
355 'layoutRootPath' => 'Resources/Private/Layouts',
356 'layoutRootPaths' => NULL,
357 'bubbleControllerAndSubpackage' => FALSE,
358 'formatIsOptional' => TRUE,
359 'pattern' => '@partialRoot/@subpackage/@controller/@partial.@format',
360 'expectedResult' => array(
361 'Default/Resources/Path/Some/Sub/Package/SomeController/@partial.html',
362 'Default/Resources/Path/Some/Sub/Package/SomeController/@partial',
363 'Fallback/Some/Sub/Package/SomeController/@partial.html',
364 'Fallback/Some/Sub/Package/SomeController/@partial',
365 )
366 ),
367 // partial fallback paths with bubbleControllerAndSubpackage
368 array(
369 'package' => 'Some.Package',
370 'subPackage' => 'Some\\Sub\\Package',
371 'controller' => 'SomeController',
372 'format' => 'html',
373 'templateRootPath' => 'Resources/Private/Templates',
374 'templateRootPaths' => array('Resources/Private/Templates', 'Some/Fallback/Path'),
375 'partialRootPath' => 'Resources/Private/Partials',
376 'partialRootPaths' => array('Default/Resources/Path', 'Fallback1/', 'Fallback2'),
377 'layoutRootPath' => 'Resources/Private/Layouts',
378 'layoutRootPaths' => NULL,
379 'bubbleControllerAndSubpackage' => TRUE,
380 'formatIsOptional' => TRUE,
381 'pattern' => '@partialRoot/@controller/@subpackage/@partial',
382 'expectedResult' => array(
383 'Default/Resources/Path/SomeController/Some/Sub/Package/@partial',
384 'Default/Resources/Path/Some/Sub/Package/@partial',
385 'Default/Resources/Path/Sub/Package/@partial',
386 'Default/Resources/Path/Package/@partial',
387 'Default/Resources/Path/@partial',
388 'Fallback1/SomeController/Some/Sub/Package/@partial',
389 'Fallback1/Some/Sub/Package/@partial',
390 'Fallback1/Sub/Package/@partial',
391 'Fallback1/Package/@partial',
392 'Fallback1/@partial',
393 'Fallback2/SomeController/Some/Sub/Package/@partial',
394 'Fallback2/Some/Sub/Package/@partial',
395 'Fallback2/Sub/Package/@partial',
396 'Fallback2/Package/@partial',
397 'Fallback2/@partial',
398 )
399 ),
400 // layout fallback paths
401 array(
402 'package' => 'Some.Package',
403 'subPackage' => 'Some\\Sub\\Package',
404 'controller' => 'SomeController',
405 'format' => 'html',
406 'templateRootPath' => 'Resources/Private/Templates',
407 'templateRootPaths' => array('Resources/Private/Templates', 'Some/Fallback/Path'),
408 'partialRootPath' => 'Resources/Private/Partials',
409 'partialRootPaths' => array('foo', 'bar'),
410 'layoutRootPath' => 'Resources/Private/Layouts',
411 'layoutRootPaths' => array('Default/Layout/Path', 'Fallback/Path'),
412 'bubbleControllerAndSubpackage' => FALSE,
413 'formatIsOptional' => FALSE,
414 'pattern' => '@layoutRoot/@subpackage/@controller/@layout.@format',
415 'expectedResult' => array(
416 'Default/Layout/Path/Some/Sub/Package/SomeController/@layout.html',
417 'Fallback/Path/Some/Sub/Package/SomeController/@layout.html',
418 )
419 ),
420 // layout fallback paths with bubbleControllerAndSubpackage
421 array(
422 'package' => 'Some.Package',
423 'subPackage' => 'Some\\Sub\\Package',
424 'controller' => 'SomeController',
425 'format' => 'html',
426 'templateRootPath' => 'Resources/Private/Templates',
427 'templateRootPaths' => NULL,
428 'partialRootPath' => 'Resources/Private/Partials',
429 'partialRootPaths' => NULL,
430 'layoutRootPath' => 'Resources/Private/Layouts',
431 'layoutRootPaths' => array('Resources/Layouts', 'Some/Fallback/Path'),
432 'bubbleControllerAndSubpackage' => TRUE,
433 'formatIsOptional' => TRUE,
434 'pattern' => 'Static/@layoutRoot/@subpackage/@controller/@layout.@format',
435 'expectedResult' => array(
436 'Static/Resources/Layouts/Some/Sub/Package/SomeController/@layout.html',
437 'Static/Resources/Layouts/Some/Sub/Package/SomeController/@layout',
438 'Static/Resources/Layouts/Some/Sub/Package/@layout.html',
439 'Static/Resources/Layouts/Some/Sub/Package/@layout',
440 'Static/Resources/Layouts/Sub/Package/@layout.html',
441 'Static/Resources/Layouts/Sub/Package/@layout',
442 'Static/Resources/Layouts/Package/@layout.html',
443 'Static/Resources/Layouts/Package/@layout',
444 'Static/Resources/Layouts/@layout.html',
445 'Static/Resources/Layouts/@layout',
446 'Static/Some/Fallback/Path/Some/Sub/Package/SomeController/@layout.html',
447 'Static/Some/Fallback/Path/Some/Sub/Package/SomeController/@layout',
448 'Static/Some/Fallback/Path/Some/Sub/Package/@layout.html',
449 'Static/Some/Fallback/Path/Some/Sub/Package/@layout',
450 'Static/Some/Fallback/Path/Sub/Package/@layout.html',
451 'Static/Some/Fallback/Path/Sub/Package/@layout',
452 'Static/Some/Fallback/Path/Package/@layout.html',
453 'Static/Some/Fallback/Path/Package/@layout',
454 'Static/Some/Fallback/Path/@layout.html',
455 'Static/Some/Fallback/Path/@layout',
456 )
457 ),
458 // combined fallback paths
459 array(
460 'package' => 'Some.Package',
461 'subPackage' => 'Some\\Sub\\Package',
462 'controller' => 'SomeController',
463 'format' => 'html',
464 'templateRootPath' => 'Resources/Private/Templates',
465 'templateRootPaths' => array('Resources/Templates', 'Templates/Fallback1', 'Templates/Fallback2'),
466 'partialRootPath' => 'Resources/Private/Partials',
467 'partialRootPaths' => array('Resources/Partials'),
468 'layoutRootPath' => 'Resources/Private/Layouts',
469 'layoutRootPaths' => array('Resources/Layouts', 'Layouts/Fallback1'),
470 'bubbleControllerAndSubpackage' => FALSE,
471 'formatIsOptional' => TRUE,
472 'pattern' => '@layoutRoot/@templateRoot/@partialRoot/@subpackage/@controller/foo',
473 'expectedResult' => array(
474 'Resources/Layouts/Resources/Templates/Resources/Partials/Some/Sub/Package/SomeController/foo',
475 'Layouts/Fallback1/Resources/Templates/Resources/Partials/Some/Sub/Package/SomeController/foo',
476 'Resources/Layouts/Templates/Fallback1/Resources/Partials/Some/Sub/Package/SomeController/foo',
477 'Layouts/Fallback1/Templates/Fallback1/Resources/Partials/Some/Sub/Package/SomeController/foo',
478 'Resources/Layouts/Templates/Fallback2/Resources/Partials/Some/Sub/Package/SomeController/foo',
479 'Layouts/Fallback1/Templates/Fallback2/Resources/Partials/Some/Sub/Package/SomeController/foo',
480 )
481 ),
482 );
483 }
484
485 /**
486 * @test
487 * @dataProvider expandGenericPathPatternDataProvider()
488 *
489 * @param string $package
490 * @param string $subPackage
491 * @param string $controller
492 * @param string $format
493 * @param string $templateRootPath
494 * @param array $templateRootPaths
495 * @param string $partialRootPath
496 * @param array $partialRootPaths
497 * @param string $layoutRootPath
498 * @param array $layoutRootPaths
499 * @param bool $bubbleControllerAndSubpackage
500 * @param bool $formatIsOptional
501 * @param string $pattern
502 * @param string $expectedResult
503 */
504 public function expandGenericPathPatternTests($package, $subPackage, $controller, $format, $templateRootPath, array $templateRootPaths = NULL, $partialRootPath, array $partialRootPaths = NULL, $layoutRootPath, array $layoutRootPaths = NULL, $bubbleControllerAndSubpackage, $formatIsOptional, $pattern, $expectedResult) {
505 $mockControllerContext = $this->setupMockControllerContextForPathResolving($package, $subPackage, $controller, $format);
506
507 /** @var TemplateView|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $templateView */
508 $templateView = $this->getAccessibleMock(TemplateView::class, array('dummy'), array(), '', FALSE);
509 $templateView->setControllerContext($mockControllerContext);
510 if ($templateRootPath !== NULL) {
511 $templateView->setTemplateRootPath($templateRootPath);
512 }
513 if ($templateRootPaths !== NULL) {
514 $templateView->setTemplateRootPaths($templateRootPaths);
515 }
516
517 if ($partialRootPath !== NULL) {
518 $templateView->setPartialRootPath($partialRootPath);
519 }
520 if ($partialRootPaths !== NULL) {
521 $templateView->setPartialRootPaths($partialRootPaths);
522 }
523
524 if ($layoutRootPath !== NULL) {
525 $templateView->setLayoutRootPath($layoutRootPath);
526 }
527 if ($layoutRootPaths !== NULL) {
528 $templateView->setLayoutRootPaths($layoutRootPaths);
529 }
530
531 $actualResult = $templateView->_call('expandGenericPathPattern', $pattern, $bubbleControllerAndSubpackage, $formatIsOptional);
532 $this->assertEquals($expectedResult, $actualResult);
533 }
534
535 /**
536 * @test
537 */
538 public function expandGenericPathPatternWorksWithBubblingDisabledAndFormatNotOptional() {
539 $mockControllerContext = $this->setupMockControllerContextForPathResolving('MyPackage', NULL, 'My', 'html');
540
541 $templateView = $this->getAccessibleMock(TemplateView::class, array('getTemplateRootPaths'), array(), '', FALSE);
542 $templateView->_set('controllerContext', $mockControllerContext);
543 $templateView->expects($this->any())->method('getTemplateRootPaths')->will($this->returnValue(array('Resources/Private/')));
544
545 $expected = array('Resources/Private/Templates/My/@action.html');
546 $actual = $templateView->_call('expandGenericPathPattern', '@templateRoot/Templates/@subpackage/@controller/@action.@format', FALSE, FALSE);
547 $this->assertEquals($expected, $actual);
548 }
549
550
551 /**
552 * @test
553 */
554 public function expandGenericPathPatternWorksWithSubpackageAndBubblingDisabledAndFormatNotOptional() {
555 $mockControllerContext = $this->setupMockControllerContextForPathResolving('MyPackage', 'MySubPackage', 'My', 'html');
556
557 $templateView = $this->getAccessibleMock(TemplateView::class, array('getTemplateRootPaths'), array(), '', FALSE);
558 $templateView->_set('controllerContext', $mockControllerContext);
559 $templateView->expects($this->any())->method('getTemplateRootPaths')->will($this->returnValue(array('Resources/Private/')));
560 $actual = $templateView->_call('expandGenericPathPattern', '@templateRoot/Templates/@subpackage/@controller/@action.@format', FALSE, FALSE);
561
562 $expected = array(
563 'Resources/Private/Templates/MySubPackage/My/@action.html'
564 );
565 $this->assertEquals($expected, $actual);
566 }
567
568 /**
569 * @test
570 */
571 public function expandGenericPathPatternWorksWithSubpackageAndBubblingDisabledAndFormatOptional() {
572 $mockControllerContext = $this->setupMockControllerContextForPathResolving('MyPackage', 'MySubPackage', 'My', 'html');
573
574 $templateView = $this->getAccessibleMock(TemplateView::class, array('getTemplateRootPaths'), array(), '', FALSE);
575 $templateView->_set('controllerContext', $mockControllerContext);
576 $templateView->expects($this->any())->method('getTemplateRootPaths')->will($this->returnValue(array('Resources/Private/')));
577 $actual = $templateView->_call('expandGenericPathPattern', '@templateRoot/Templates/@subpackage/@controller/@action.@format', FALSE, TRUE);
578
579 $expected = array(
580 'Resources/Private/Templates/MySubPackage/My/@action.html',
581 'Resources/Private/Templates/MySubPackage/My/@action'
582 );
583 $this->assertEquals($expected, $actual);
584 }
585
586 /**
587 * @test
588 */
589 public function expandGenericPathPatternWorksWithSubpackageAndBubblingEnabledAndFormatOptional() {
590 $mockControllerContext = $this->setupMockControllerContextForPathResolving('MyPackage', 'MySubPackage', 'My', 'html');
591
592 $templateView = $this->getAccessibleMock(TemplateView::class, array('getTemplateRootPaths'), array(), '', FALSE);
593 $templateView->_set('controllerContext', $mockControllerContext);
594 $templateView->expects($this->any())->method('getTemplateRootPaths')->will($this->returnValue(array('Resources/Private/')));
595 $actual = $templateView->_call('expandGenericPathPattern', '@templateRoot/Templates/@subpackage/@controller/@action.@format', TRUE, TRUE);
596
597 $expected = array(
598 'Resources/Private/Templates/MySubPackage/My/@action.html',
599 'Resources/Private/Templates/MySubPackage/My/@action',
600 'Resources/Private/Templates/MySubPackage/@action.html',
601 'Resources/Private/Templates/MySubPackage/@action',
602 'Resources/Private/Templates/@action.html',
603 'Resources/Private/Templates/@action'
604 );
605 $this->assertEquals($expected, $actual);
606 }
607
608 /**
609 * @test
610 */
611 public function getTemplateRootPathsReturnsUserSpecifiedTemplatePaths() {
612 /** @var TemplateView|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $templateView */
613 $templateView = $this->getAccessibleMock(TemplateView::class, array('dummy'), array(), '', FALSE);
614 $templateView->setTemplateRootPath('/foo/bar');
615 $expected = array('/foo/bar');
616 $actual = $templateView->_call('getTemplateRootPaths');
617 $this->assertEquals($expected, $actual, 'A set template root path was not returned correctly.');
618 }
619
620 /**
621 * @test
622 */
623 public function setTemplateRootPathOverrulesSetTemplateRootPaths() {
624 /** @var TemplateView|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $templateView */
625 $templateView = $this->getAccessibleMock(TemplateView::class, array('dummy'), array(), '', FALSE);
626 $templateView->setTemplateRootPath('/foo/bar');
627 $templateView->setTemplateRootPaths(array('/overruled/path'));
628 $expected = array('/overruled/path');
629 $actual = $templateView->_call('getTemplateRootPaths');
630 $this->assertEquals($expected, $actual, 'A set template root path was not returned correctly.');
631 }
632
633 /**
634 * @test
635 */
636 public function getPartialRootPathsReturnsUserSpecifiedPartialPath() {
637 /** @var TemplateView|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $templateView */
638 $templateView = $this->getAccessibleMock(TemplateView::class, array('dummy'), array(), '', FALSE);
639 $templateView->setPartialRootPath('/foo/bar');
640 $expected = array('/foo/bar');
641 $actual = $templateView->_call('getPartialRootPaths');
642 $this->assertEquals($expected, $actual, 'A set partial root path was not returned correctly.');
643 }
644
645 /**
646 * @test
647 */
648 public function getLayoutRootPathsReturnsUserSpecifiedPartialPath() {
649 /** @var TemplateView|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $templateView */
650 $templateView = $this->getAccessibleMock(TemplateView::class, array('dummy'), array(), '', FALSE);
651 $templateView->setLayoutRootPath('/foo/bar');
652 $expected = array('/foo/bar');
653 $actual = $templateView->_call('getLayoutRootPaths');
654 $this->assertEquals($expected, $actual, 'A set partial root path was not returned correctly.');
655 }
656
657 /**
658 * @test
659 */
660 public function pathToPartialIsResolvedCorrectly() {
661 vfsStreamWrapper::register();
662 mkdir('vfs://MyPartials');
663 \file_put_contents('vfs://MyPartials/SomePartial', 'contentsOfSomePartial');
664
665 $paths = array(
666 'vfs://NonExistentDir/UnknowFile.html',
667 'vfs://MyPartials/SomePartial.html',
668 'vfs://MyPartials/SomePartial'
669 );
670
671 /** @var TemplateView|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $templateView */
672 $templateView = $this->getAccessibleMock(TemplateView::class, array('expandGenericPathPattern', 'resolveFileNamePath'), array(), '', FALSE);
673 $templateView->expects($this->once())->method('expandGenericPathPattern')->with('@partialRoot/@subpackage/@partial.@format', TRUE, TRUE)->will($this->returnValue($paths));
674 $templateView->expects($this->any())->method('resolveFileNamePath')->will($this->onConsecutiveCalls(
675 $paths[0],
676 $paths[1],
677 $paths[2]
678 ));
679
680 $templateView->setTemplateRootPath('MyTemplates');
681 $templateView->setPartialRootPath('MyPartials');
682 $templateView->setLayoutRootPath('MyLayouts');
683
684 $this->assertSame('contentsOfSomePartial', $templateView->_call('getPartialSource', 'SomePartial'));
685 }
686
687 /**
688 * @test
689 */
690 public function resolveTemplatePathAndFilenameChecksDifferentPathPatternsAndReturnsTheFirstPathWhichExists() {
691 vfsStreamWrapper::register();
692 mkdir('vfs://MyTemplates');
693 \file_put_contents('vfs://MyTemplates/MyCoolAction.html', 'contentsOfMyCoolAction');
694
695 $paths = array(
696 'vfs://NonExistentDir/UnknownFile.html',
697 'vfs://MyTemplates/@action.html'
698 );
699
700 /** @var TemplateView|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $templateView */
701 $templateView = $this->getAccessibleMock(TemplateView::class, array('expandGenericPathPattern', 'resolveFileNamePath'), array(), '', FALSE);
702 $templateView->expects($this->once())->method('expandGenericPathPattern')->with('@templateRoot/@subpackage/@controller/@action.@format', FALSE, FALSE)->will($this->returnValue($paths));
703 $templateView->expects($this->any())->method('resolveFileNamePath')->will($this->onConsecutiveCalls(
704 $paths[0],
705 'vfs://MyTemplates/MyCoolAction.html'
706 ));
707
708 $templateView->setTemplateRootPath('MyTemplates');
709 $templateView->setPartialRootPath('MyPartials');
710 $templateView->setLayoutRootPath('MyLayouts');
711
712 $this->assertSame('contentsOfMyCoolAction', $templateView->_call('getTemplateSource', 'myCoolAction'));
713
714 }
715
716 /**
717 * @test
718 */
719 public function resolveTemplatePathAndFilenameReturnsTheExplicitlyConfiguredTemplatePathAndFilename() {
720 vfsStreamWrapper::register();
721 mkdir('vfs://MyTemplates');
722 \file_put_contents('vfs://MyTemplates/MyCoolAction.html', 'contentsOfMyCoolAction');
723
724 $templateView = $this->getAccessibleMock(TemplateView::class, array('resolveFileNamePath'), array(), '', FALSE);
725 $templateView->expects($this->any())->method('resolveFileNamePath')->willReturnArgument(0);
726 $templateView->_set('templatePathAndFilename', 'vfs://MyTemplates/MyCoolAction.html');
727
728 $this->assertSame('contentsOfMyCoolAction', $templateView->_call('getTemplateSource'));
729 }
730
731 /**
732 * @test
733 */
734 public function getLayoutPathAndFilenameRespectsCasingOfLayoutName() {
735 $singletonInstances = GeneralUtility::getSingletonInstances();
736
737 $mockParsedTemplate = $this->getMock(ParsedTemplateInterface::class);
738 $mockTemplateParser = $this->getMock(TemplateParser::class);
739 $mockTemplateParser->expects($this->any())->method('parse')->will($this->returnValue($mockParsedTemplate));
740
741 /** @var ObjectManager|\PHPUnit_Framework_MockObject_MockObject $mockObjectManager */
742 $mockObjectManager = $this->getMock(ObjectManager::class);
743 $mockObjectManager->expects($this->any())->method('get')->will($this->returnCallback(array($this, 'objectManagerCallback')));
744
745 $mockRequest = $this->getMock(WebRequest::class);
746 $mockControllerContext = $this->getMock(ControllerContext::class);
747 $mockControllerContext->expects($this->any())->method('getRequest')->will($this->returnValue($mockRequest));
748
749 $mockViewHelperVariableContainer = $this->getMock(ViewHelperVariableContainer::class);
750 /** @var RenderingContext|\PHPUnit_Framework_MockObject_MockObject $mockRenderingContext */
751 $mockRenderingContext = $this->getMock(RenderingContext::class);
752 $mockRenderingContext->expects($this->any())->method('getControllerContext')->will($this->returnValue($mockControllerContext));
753 $mockRenderingContext->expects($this->any())->method('getViewHelperVariableContainer')->will($this->returnValue($mockViewHelperVariableContainer));
754
755 /** @var TemplateView|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $view */
756 $view = $this->getAccessibleMock(TemplateView::class, array('testFileExistence', 'buildParserConfiguration'), array(), '', FALSE);
757 $view->_set('templateParser', $mockTemplateParser);
758 $view->_set('objectManager', $mockObjectManager);
759 $view->setRenderingContext($mockRenderingContext);
760
761 $mockTemplateCompiler = $this->getMock(TemplateCompiler::class);
762 $view->_set('templateCompiler', $mockTemplateCompiler);
763 GeneralUtility::setSingletonInstance(ObjectManager::class, $mockObjectManager);
764 $mockContentObject = $this->getMock(ContentObjectRenderer::class);
765 GeneralUtility::addInstance(ContentObjectRenderer::class, $mockContentObject);
766
767 /** @var CacheManager|\PHPUnit_Framework_MockObject_MockObject $mockCacheManager */
768 $mockCacheManager = $this->getMock(CacheManager::class, array(), array(), '', FALSE);
769 $mockCache = $this->getMock(PhpFrontend::class, array(), array(), '', FALSE);
770 $mockCacheManager->expects($this->any())->method('getCache')->will($this->returnValue($mockCache));
771 GeneralUtility::setSingletonInstance(CacheManager::class, $mockCacheManager);
772
773 $mockRequest->expects($this->any())->method('getFormat')->will($this->returnValue('html'));
774 $view->setLayoutRootPaths(array('some/Default/Directory'));
775 $view->setTemplateRootPaths(array('some/Default/Directory'));
776 $view->setPartialRootPaths(array('some/Default/Directory'));
777 $view->expects($this->at(0))->method('testFileExistence')->with(PATH_site . 'some/Default/Directory/LayoutName.html')->willReturn(FALSE);
778 $view->expects($this->at(1))->method('testFileExistence')->with(PATH_site . 'some/Default/Directory/layoutName.html')->willReturn(TRUE);
779 $this->assertSame(PATH_site . 'some/Default/Directory/layoutName.html', $view->_call('getLayoutPathAndFilename', 'layoutName'));
780
781 GeneralUtility::purgeInstances();
782 GeneralUtility::resetSingletonInstances($singletonInstances);
783 }
784 }