0fdfa1cebe8b865b287c7256d2df44f80546e407
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Tests / Unit / Controller / TypoScriptFrontendControllerTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Frontend\Tests\Unit\Controller;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Core\Context\Context;
19 use TYPO3\CMS\Core\Http\ServerRequestFactory;
20 use TYPO3\CMS\Core\Page\PageRenderer;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
23 use TYPO3\CMS\Frontend\Page\PageRepository;
24 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
25
26 /**
27 * Test case
28 */
29 class TypoScriptFrontendControllerTest extends UnitTestCase
30 {
31 /**
32 * @var bool Reset singletons created by subject
33 */
34 protected $resetSingletonInstances = true;
35
36 /**
37 * @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|TypoScriptFrontendController
38 */
39 protected $subject;
40
41 protected function setUp()
42 {
43 GeneralUtility::flushInternalRuntimeCaches();
44 $this->subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
45 $this->subject->_set('context', new Context());
46 $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = '170928423746123078941623042360abceb12341234231';
47
48 $pageRepository = $this->getMockBuilder(PageRepository::class)->getMock();
49 $this->subject->sys_page = $pageRepository;
50
51 $pageRenderer = $this->getMockBuilder(PageRenderer::class)->getMock();
52 $this->subject->_set('pageRenderer', $pageRenderer);
53 }
54
55 /**
56 * Tests concerning rendering content
57 */
58
59 /**
60 * @test
61 */
62 public function headerAndFooterMarkersAreReplacedDuringIntProcessing()
63 {
64 $GLOBALS['TSFE'] = $this->setupTsfeMockForHeaderFooterReplacementCheck();
65 $GLOBALS['TSFE']->INTincScript();
66 $this->assertContains('headerData', $GLOBALS['TSFE']->content);
67 $this->assertContains('footerData', $GLOBALS['TSFE']->content);
68 }
69
70 /**
71 * This is the callback that mimics a USER_INT extension
72 */
73 public function INTincScript_processCallback()
74 {
75 $GLOBALS['TSFE']->additionalHeaderData[] = 'headerData';
76 $GLOBALS['TSFE']->additionalFooterData[] = 'footerData';
77 }
78
79 /**
80 * Setup a \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController object only for testing the header and footer
81 * replacement during USER_INT rendering
82 *
83 * @return \PHPUnit_Framework_MockObject_MockObject|TypoScriptFrontendController
84 */
85 protected function setupTsfeMockForHeaderFooterReplacementCheck()
86 {
87 /** @var \PHPUnit_Framework_MockObject_MockObject|TypoScriptFrontendController $tsfe */
88 $tsfe = $this->getMockBuilder(TypoScriptFrontendController::class)
89 ->setMethods([
90 'INTincScript_process',
91 'INTincScript_loadJSCode',
92 'setAbsRefPrefix',
93 'regeneratePageTitle'
94 ])->disableOriginalConstructor()
95 ->getMock();
96 $tsfe->expects($this->exactly(2))->method('INTincScript_process')->will($this->returnCallback([$this, 'INTincScript_processCallback']));
97 $tsfe->content = file_get_contents(__DIR__ . '/Fixtures/renderedPage.html');
98 $config = [
99 'INTincScript_ext' => [
100 'divKey' => '679b52796e75d474ccbbed486b6837ab',
101 ],
102 'INTincScript' => [
103 'INT_SCRIPT.679b52796e75d474ccbbed486b6837ab' => [],
104 ]
105 ];
106 $tsfe->config = $config;
107
108 return $tsfe;
109 }
110
111 /**
112 * Tests concerning sL
113 */
114
115 /**
116 * @test
117 */
118 public function localizationReturnsUnchangedStringIfNotLocallangLabel()
119 {
120 $string = $this->getUniqueId();
121 $this->subject->page = [];
122 $this->subject->settingLanguage();
123 $this->assertEquals($string, $this->subject->sL($string));
124 }
125
126 /**
127 * Tests concerning getSysDomainCache
128 */
129
130 /**
131 * @return array
132 */
133 public function getSysDomainCacheDataProvider()
134 {
135 return [
136 'typo3.org' => [
137 'typo3.org',
138 ],
139 'foo.bar' => [
140 'foo.bar',
141 ],
142 'example.com' => [
143 'example.com',
144 ],
145 ];
146 }
147
148 /**
149 * @return array
150 */
151 public function baseUrlWrapHandlesDifferentUrlsDataProvider()
152 {
153 return [
154 'without base url' => [
155 '',
156 'fileadmin/user_uploads/image.jpg',
157 'fileadmin/user_uploads/image.jpg'
158 ],
159 'with base url' => [
160 'http://www.google.com/',
161 'fileadmin/user_uploads/image.jpg',
162 'http://www.google.com/fileadmin/user_uploads/image.jpg'
163 ],
164 'without base url but with url prepended with a forward slash' => [
165 '',
166 '/fileadmin/user_uploads/image.jpg',
167 '/fileadmin/user_uploads/image.jpg',
168 ],
169 'with base url but with url prepended with a forward slash' => [
170 'http://www.google.com/',
171 '/fileadmin/user_uploads/image.jpg',
172 '/fileadmin/user_uploads/image.jpg',
173 ],
174 ];
175 }
176
177 /**
178 * @dataProvider baseUrlWrapHandlesDifferentUrlsDataProvider
179 * @test
180 * @param string $baseUrl
181 * @param string $url
182 * @param string $expected
183 */
184 public function baseUrlWrapHandlesDifferentUrls($baseUrl, $url, $expected)
185 {
186 $this->subject->baseUrl = $baseUrl;
187 $this->assertSame($expected, $this->subject->baseUrlWrap($url));
188 }
189
190 /**
191 * @return array
192 */
193 public function initializeSearchWordDataBuildsCorrectRegexDataProvider()
194 {
195 return [
196 'one simple search word' => [
197 ['test'],
198 false,
199 'test',
200 ],
201 'one simple search word with standalone words' => [
202 ['test'],
203 true,
204 '[[:space:]]test[[:space:]]',
205 ],
206 'two simple search words' => [
207 ['test', 'test2'],
208 false,
209 'test|test2',
210 ],
211 'two simple search words with standalone words' => [
212 ['test', 'test2'],
213 true,
214 '[[:space:]]test[[:space:]]|[[:space:]]test2[[:space:]]',
215 ],
216 'word with regex chars' => [
217 ['A \\ word with / a bunch of [] regex () chars .*'],
218 false,
219 'A \\\\ word with \\/ a bunch of \\[\\] regex \\(\\) chars \\.\\*',
220 ],
221 ];
222 }
223
224 /**
225 * @test
226 * @dataProvider initializeSearchWordDataBuildsCorrectRegexDataProvider
227 *
228 * @param array $searchWordGetParameters The values that should be loaded in the sword_list GET parameter.
229 * @param bool $enableStandaloneSearchWords If TRUE the sword_standAlone option will be enabled.
230 * @param string $expectedRegex The expected regex after processing the search words.
231 */
232 public function initializeSearchWordDataBuildsCorrectRegex(array $searchWordGetParameters, $enableStandaloneSearchWords, $expectedRegex)
233 {
234 $_GET['sword_list'] = $searchWordGetParameters;
235 $_SERVER['HTTP_HOST'] = 'localhost';
236 $_SERVER['SCRIPT_NAME'] = '/index.php';
237
238 $this->subject->page = [];
239 if ($enableStandaloneSearchWords) {
240 $this->subject->config = ['config' => ['sword_standAlone' => 1]];
241 }
242
243 GeneralUtility::flushInternalRuntimeCaches();
244 $request = ServerRequestFactory::fromGlobals();
245 $this->subject->preparePageContentGeneration($request);
246 $this->assertEquals($this->subject->sWordRegEx, $expectedRegex);
247 }
248
249 /**
250 * @test
251 * @dataProvider splitLinkVarsDataProvider
252 *
253 * @param $string
254 * @param $expected
255 */
256 public function splitLinkVarsStringSplitsStringByComma($string, $expected)
257 {
258 $this->assertEquals($expected, $this->subject->_callRef('splitLinkVarsString', $string));
259 }
260
261 /**
262 * @return array
263 */
264 public function splitLinkVarsDataProvider()
265 {
266 return [
267 [
268 'L',
269 ['L']
270 ],
271 [
272 'L,a',
273 [
274 'L',
275 'a'
276 ]
277 ],
278 [
279 'L, a',
280 [
281 'L',
282 'a'
283 ]
284 ],
285 [
286 'L , a',
287 [
288 'L',
289 'a'
290 ]
291 ],
292 [
293 ' L, a ',
294 [
295 'L',
296 'a'
297 ]
298 ],
299 [
300 'L(1)',
301 [
302 'L(1)'
303 ]
304 ],
305 [
306 'L(1),a',
307 [
308 'L(1)',
309 'a'
310 ]
311 ],
312 [
313 'L(1) , a',
314 [
315 'L(1)',
316 'a'
317 ]
318 ],
319 [
320 'a,L(1)',
321 [
322 'a',
323 'L(1)'
324 ]
325 ],
326 [
327 'L(1),a(2-3)',
328 [
329 'L(1)',
330 'a(2-3)'
331 ]
332 ],
333 [
334 'L(1),a((2-3))',
335 [
336 'L(1)',
337 'a((2-3))'
338 ]
339 ],
340 [
341 'L(1),a(a{2,4})',
342 [
343 'L(1)',
344 'a(a{2,4})'
345 ]
346 ],
347 [
348 'L(1),a(/a{2,4}\,()/)',
349 [
350 'L(1)',
351 'a(/a{2,4}\,()/)'
352 ]
353 ],
354 [
355 'L,a , b(c) , dd(/g{1,2}/), eee(, ()f) , 2',
356 [
357 'L',
358 'a',
359 'b(c)',
360 'dd(/g{1,2}/)',
361 'eee(, ()f)',
362 '2'
363 ]
364 ]
365 ];
366 }
367
368 /**
369 * @test
370 * @dataProvider calculateLinkVarsDataProvider
371 * @param string $linkVars
372 * @param array $getVars
373 * @param string $expected
374 */
375 public function calculateLinkVarsConsidersCorrectVariables(string $linkVars, array $getVars, string $expected)
376 {
377 $this->subject->config['config']['linkVars'] = $linkVars;
378 $this->subject->calculateLinkVars($getVars);
379 $this->assertEquals($expected, $this->subject->linkVars);
380 }
381
382 public function calculateLinkVarsDataProvider(): array
383 {
384 return [
385 'simple variable' => [
386 'L',
387 [
388 'L' => 1
389 ],
390 '&L=1'
391 ],
392 'missing variable' => [
393 'L',
394 [
395 ],
396 ''
397 ],
398 'restricted variables' => [
399 'L(1-3),bar(3),foo(array),blub(array)',
400 [
401 'L' => 1,
402 'bar' => 2,
403 'foo' => [ 1, 2, 'f' => [ 4, 5 ] ],
404 'blub' => 123
405 ],
406 '&L=1&foo[0]=1&foo[1]=2&foo[f][0]=4&foo[f][1]=5'
407 ],
408 'nested variables' => [
409 'bar|foo(1-2)',
410 [
411 'bar' => [
412 'foo' => 1,
413 'unused' => 'never'
414 ]
415 ],
416 '&bar[foo]=1'
417 ],
418 ];
419 }
420
421 /**
422 * @test
423 */
424 public function initializeSearchWordDataDoesNothingWithNullValue()
425 {
426 $subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
427 $subject->_call('initializeSearchWordData', null);
428 $this->assertEquals('', $subject->sWordRegEx);
429 $this->assertEquals('', $subject->sWordList);
430 }
431
432 /**
433 * @test
434 */
435 public function initializeSearchWordDataDoesNothingWithEmptyStringValue()
436 {
437 $subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
438 $subject->_call('initializeSearchWordData', '');
439 $this->assertEquals('', $subject->sWordRegEx);
440 $this->assertEquals('', $subject->sWordList);
441 }
442
443 /**
444 * @test
445 */
446 public function initializeSearchWordDataDoesNothingWithEmptyArrayValue()
447 {
448 $subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
449 $subject->_call('initializeSearchWordData', []);
450 $this->assertEquals('', $subject->sWordRegEx);
451 $this->assertEquals([], $subject->sWordList);
452 }
453
454 /**
455 * @test
456 */
457 public function initializeSearchWordDataFillsProperRegexpWithArray()
458 {
459 $subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
460 $subject->_call('initializeSearchWordData', ['stop', 'word']);
461 $this->assertEquals('stop|word', $subject->sWordRegEx);
462 $this->assertEquals(['stop', 'word'], $subject->sWordList);
463 }
464
465 /**
466 * @test
467 */
468 public function initializeSearchWordDataFillsProperRegexpWithArrayAndStandaloneOption()
469 {
470 $subject = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
471 $subject->config['config']['sword_standAlone'] = 1;
472 $subject->_call('initializeSearchWordData', ['stop', 'word']);
473 $this->assertEquals('[[:space:]]stop[[:space:]]|[[:space:]]word[[:space:]]', $subject->sWordRegEx);
474 $this->assertEquals(['stop', 'word'], $subject->sWordList);
475 }
476 }