[TASK] Streamline expressionLanguage usage in core
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Tests / UnitDeprecated / Configuration / TypoScript / ConditionMatching / ConditionMatcherTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Frontend\Tests\UnitDeprecated\Configuration\TypoScript\ConditionMatching;
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 Prophecy\Argument;
19 use TYPO3\CMS\Core\Cache\CacheManager;
20 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
21 use TYPO3\CMS\Core\Configuration\TypoScript\Exception\InvalidTypoScriptConditionException;
22 use TYPO3\CMS\Core\Context\Context;
23 use TYPO3\CMS\Core\Context\UserAspect;
24 use TYPO3\CMS\Core\Http\ServerRequest;
25 use TYPO3\CMS\Core\Log\Logger;
26 use TYPO3\CMS\Core\Package\PackageInterface;
27 use TYPO3\CMS\Core\Package\PackageManager;
28 use TYPO3\CMS\Core\Site\Entity\Site;
29 use TYPO3\CMS\Core\Utility\GeneralUtility;
30 use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
31 use TYPO3\CMS\Frontend\Configuration\TypoScript\ConditionMatching\ConditionMatcher;
32 use TYPO3\CMS\Frontend\Tests\UnitDeprecated\Configuration\TypoScript\ConditionMatching\Fixtures\TestConditionException;
33 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
34
35 /**
36 * Test case
37 */
38 class ConditionMatcherTest extends UnitTestCase
39 {
40 /**
41 * @var ConditionMatcher
42 */
43 protected $subject;
44
45 /**
46 * @var string
47 */
48 protected $testGlobalNamespace;
49
50 /**
51 * @var bool Reset singletons
52 */
53 protected $resetSingletonInstances = true;
54
55 protected function setUp(): void
56 {
57 $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
58 $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
59 $cacheFrontendProphecy->has(Argument::any())->willReturn(false);
60 $cacheFrontendProphecy->set(Argument::any(), Argument::any())->willReturn(null);
61 $cacheManagerProphecy = $this->prophesize(CacheManager::class);
62 $cacheManagerProphecy->getCache('cache_core')->willReturn($cacheFrontendProphecy->reveal());
63 GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerProphecy->reveal());
64
65 $packageManagerProphecy = $this->prophesize(PackageManager::class);
66 $corePackageProphecy = $this->prophesize(PackageInterface::class);
67 $corePackageProphecy->getPackagePath()->willReturn(__DIR__ . '/../../../../../../../sysext/core/');
68 $packageManagerProphecy->getActivePackages()->willReturn([
69 $corePackageProphecy->reveal()
70 ]);
71 GeneralUtility::setSingletonInstance(PackageManager::class, $packageManagerProphecy->reveal());
72
73 $this->testGlobalNamespace = $this->getUniqueId('TEST');
74 $GLOBALS[$this->testGlobalNamespace] = [];
75 $GLOBALS['TSFE'] = new \stdClass();
76 $GLOBALS['TSFE']->page = [];
77 $GLOBALS['TSFE']->tmpl = new \stdClass();
78 $GLOBALS['TSFE']->tmpl->rootLine = [
79 2 => ['uid' => 121, 'pid' => 111],
80 1 => ['uid' => 111, 'pid' => 101],
81 0 => ['uid' => 101, 'pid' => 0]
82 ];
83
84 $frontedUserAuthentication = $this->getMockBuilder(FrontendUserAuthentication::class)
85 ->setMethods(['dummy'])
86 ->getMock();
87
88 $frontedUserAuthentication->user['uid'] = 13;
89 $frontedUserAuthentication->groupData['uid'] = [14];
90 $GLOBALS['TSFE']->fe_user = $frontedUserAuthentication;
91 $this->getFreshConditionMatcher();
92 }
93
94 protected function getFreshConditionMatcher()
95 {
96 $this->subject = new ConditionMatcher(new Context([
97 'frontend.user' => new UserAspect($GLOBALS['TSFE']->fe_user)
98 ]));
99 $this->subject->setLogger($this->prophesize(Logger::class)->reveal());
100 }
101
102 /**
103 * Tests whether a faulty expression fails.
104 *
105 * @test
106 */
107 public function simulateDisabledMatchAllConditionsFailsOnFaultyExpression(): void
108 {
109 $this->getFreshConditionMatcher();
110 $this->assertFalse($this->subject->match('[nullCondition = This expression would return FALSE in general]'));
111 }
112
113 /**
114 * Tests whether simulating positive matches for all conditions succeeds.
115 *
116 * @test
117 */
118 public function simulateEnabledMatchAllConditionsSucceeds(): void
119 {
120 $this->getFreshConditionMatcher();
121 $this->subject->setSimulateMatchResult(true);
122 $this->assertTrue($this->subject->match('[nullCondition = This expression would return FALSE in general]'));
123 }
124
125 /**
126 * Tests whether simulating positive matches for specific conditions succeeds.
127 *
128 * @test
129 */
130 public function simulateEnabledMatchSpecificConditionsSucceeds(): void
131 {
132 $this->getFreshConditionMatcher();
133 $testCondition = '[' . $this->getUniqueId('test') . ' = Any condition to simulate a positive match]';
134 $this->subject->setSimulateMatchConditions([$testCondition]);
135 $this->assertTrue($this->subject->match($testCondition));
136 }
137
138 /**
139 * Tests whether the language comparison matches.
140 *
141 * @test
142 */
143 public function languageConditionMatchesSingleLanguageExpression(): void
144 {
145 $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
146 $this->getFreshConditionMatcher();
147 $this->assertTrue($this->subject->match('[language = *de*]'));
148 $this->assertTrue($this->subject->match('[language = *de-de*]'));
149 }
150
151 /**
152 * Tests whether the language comparison matches.
153 *
154 * @test
155 */
156 public function languageConditionMatchesMultipleLanguagesExpression(): void
157 {
158 $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
159 $this->getFreshConditionMatcher();
160 $this->assertTrue($this->subject->match('[language = *en*,*de*]'));
161 $this->assertTrue($this->subject->match('[language = *en-us*,*de-de*]'));
162 }
163
164 /**
165 * Tests whether the language comparison matches.
166 *
167 * @test
168 */
169 public function languageConditionMatchesCompleteLanguagesExpression(): void
170 {
171 $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
172 $this->getFreshConditionMatcher();
173 $this->assertTrue($this->subject->match('[language = de-de,de;q=0.8,en-us;q=0.5,en;q=0.3]'));
174 }
175
176 /**
177 * Tests whether usergroup comparison matches.
178 *
179 * @test
180 */
181 public function usergroupConditionMatchesSingleGroupId(): void
182 {
183 $subject = new ConditionMatcher(new Context([
184 'frontend.user' => new UserAspect(new FrontendUserAuthentication(), [13, 14, 15])
185 ]));
186 $loggerProphecy = $this->prophesize(Logger::class);
187 $subject->setLogger($loggerProphecy->reveal());
188 $this->assertTrue($subject->match('[usergroup = 13]'));
189 }
190
191 /**
192 * Tests whether usergroup comparison matches.
193 *
194 * @test
195 */
196 public function usergroupConditionMatchesMultipleUserGroupId(): void
197 {
198 $subject = new ConditionMatcher(new Context([
199 'frontend.user' => new UserAspect(new FrontendUserAuthentication(), [13, 14, 15])
200 ]));
201 $loggerProphecy = $this->prophesize(Logger::class);
202 $subject->setLogger($loggerProphecy->reveal());
203 $this->assertTrue($subject->match('[usergroup = 999,15,14,13]'));
204 }
205
206 /**
207 * Tests whether usergroup comparison matches.
208 *
209 * @test
210 */
211 public function usergroupConditionDoesNotMatchDefaulUserGroupIds(): void
212 {
213 $subject = new ConditionMatcher(new Context([
214 'frontend.user' => new UserAspect(new FrontendUserAuthentication(), [0, -1])
215 ]));
216 $loggerProphecy = $this->prophesize(Logger::class);
217 $subject->setLogger($loggerProphecy->reveal());
218 $this->assertFalse($subject->match('[usergroup = 0,-1]'));
219 }
220
221 /**
222 * Tests whether user comparison matches.
223 *
224 * @test
225 */
226 public function loginUserConditionMatchesAnyLoggedInUser(): void
227 {
228 $this->getFreshConditionMatcher();
229 // @TODO: not work yet, looks like test setup issue
230 $this->assertTrue($this->subject->match('[loginUser = *]'));
231 }
232
233 /**
234 * Tests whether user comparison matches.
235 *
236 * @test
237 */
238 public function loginUserConditionMatchesSingleLoggedInUser(): void
239 {
240 $this->getFreshConditionMatcher();
241 // @TODO: not work yet, looks like test setup issue
242 $this->assertTrue($this->subject->match('[loginUser = 13]'));
243 }
244
245 /**
246 * Tests whether user comparison matches.
247 *
248 * @test
249 */
250 public function loginUserConditionMatchesMultipleLoggedInUsers(): void
251 {
252 $this->getFreshConditionMatcher();
253 // @TODO: not work yet, looks like test setup issue
254 $this->assertTrue($this->subject->match('[loginUser = 999,13]'));
255 }
256
257 /**
258 * Tests whether user comparison matches.
259 *
260 * @test
261 */
262 public function loginUserConditionDoesNotMatchIfNotUserIsLoggedId(): void
263 {
264 $user = new FrontendUserAuthentication();
265 $user->user['uid'] = 13;
266 $subject = new ConditionMatcher(new Context([
267 'frontend.user' => new UserAspect($user)
268 ]));
269 $loggerProphecy = $this->prophesize(Logger::class);
270 $subject->setLogger($loggerProphecy->reveal());
271 $this->assertFalse($subject->match('[loginUser = *]'));
272 $this->assertFalse($subject->match('[loginUser = 13]'));
273 }
274
275 /**
276 * Tests whether user is not logged in
277 *
278 * @test
279 */
280 public function loginUserConditionMatchIfUserIsNotLoggedIn(): void
281 {
282 $user = new FrontendUserAuthentication();
283 $subject = new ConditionMatcher(new Context([
284 'frontend.user' => new UserAspect($user)
285 ]));
286 $loggerProphecy = $this->prophesize(Logger::class);
287 $subject->setLogger($loggerProphecy->reveal());
288 $this->assertTrue($subject->match('[loginUser = ]'));
289 }
290
291 /**
292 * Tests whether numerical comparison matches.
293 *
294 * @test
295 */
296 public function globalVarConditionMatchesOnEqualExpression(): void
297 {
298 $this->assertTrue($this->subject->match('[globalVar = LIT:10 = 10]'));
299 $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 = 10.1]'));
300 $this->assertTrue($this->subject->match('[globalVar = LIT:10 == 10]'));
301 $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 == 10.1]'));
302 }
303
304 /**
305 * Tests whether numerical comparison matches.
306 *
307 * @test
308 */
309 public function globalVarConditionMatchesOnEqualExpressionWithMultipleValues(): void
310 {
311 $this->assertTrue($this->subject->match('[globalVar = LIT:10 = 10|20|30]'));
312 $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 = 10.1|20.2|30.3]'));
313 $this->assertTrue($this->subject->match('[globalVar = LIT:20 = 10|20|30]'));
314 $this->assertTrue($this->subject->match('[globalVar = LIT:20.2 = 10.1|20.2|30.3]'));
315 $this->assertTrue($this->subject->match('[globalVar = LIT:10 == 10|20|30]'));
316 $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 == 10.1|20.2|30.3]'));
317 $this->assertTrue($this->subject->match('[globalVar = LIT:20 == 10|20|30]'));
318 $this->assertTrue($this->subject->match('[globalVar = LIT:20.2 == 10.1|20.2|30.3]'));
319 }
320
321 /**
322 * Tests whether numerical comparison matches.
323 *
324 * @test
325 */
326 public function globalVarConditionMatchesOnNotEqualExpression(): void
327 {
328 $this->assertTrue($this->subject->match('[globalVar = LIT:10 != 20]'));
329 $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 != 10.2]'));
330 }
331
332 /**
333 * Tests whether numerical comparison does not match.
334 *
335 * @test
336 */
337 public function globalVarConditionDoesNotMatchOnNotEqualExpression(): void
338 {
339 $this->assertFalse($this->subject->match('[globalVar = LIT:10 != 10]'));
340 }
341
342 /**
343 * Tests whether numerical comparison matches.
344 *
345 * @test
346 */
347 public function globalVarConditionMatchesOnNotEqualExpressionWithMultipleValues(): void
348 {
349 $this->assertTrue($this->subject->match('[globalVar = LIT:10 != 20|30]'));
350 $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 != 10.2|20.3]'));
351 }
352
353 /**
354 * Tests whether numerical comparison matches.
355 *
356 * @test
357 */
358 public function globalVarConditionMatchesOnLowerThanExpression(): void
359 {
360 $this->assertTrue($this->subject->match('[globalVar = LIT:10 < 20]'));
361 $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 < 10.2]'));
362 }
363
364 /**
365 * Tests whether numerical comparison matches.
366 *
367 * @test
368 */
369 public function globalVarConditionMatchesOnLowerThanOrEqualExpression(): void
370 {
371 $this->assertTrue($this->subject->match('[globalVar = LIT:10 <= 10]'));
372 $this->assertTrue($this->subject->match('[globalVar = LIT:10 <= 20]'));
373 $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 <= 10.1]'));
374 $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 <= 10.2]'));
375 }
376
377 /**
378 * Tests whether numerical comparison matches.
379 *
380 * @test
381 */
382 public function globalVarConditionMatchesOnGreaterThanExpression(): void
383 {
384 $this->assertTrue($this->subject->match('[globalVar = LIT:20 > 10]'));
385 $this->assertTrue($this->subject->match('[globalVar = LIT:10.2 > 10.1]'));
386 }
387
388 /**
389 * Tests whether numerical comparison matches.
390 *
391 * @test
392 */
393 public function globalVarConditionMatchesOnGreaterThanOrEqualExpression(): void
394 {
395 $this->assertTrue($this->subject->match('[globalVar = LIT:10 >= 10]'));
396 $this->assertTrue($this->subject->match('[globalVar = LIT:20 >= 10]'));
397 $this->assertTrue($this->subject->match('[globalVar = LIT:10.1 >= 10.1]'));
398 $this->assertTrue($this->subject->match('[globalVar = LIT:10.2 >= 10.1]'));
399 }
400
401 /**
402 * Tests whether numerical comparison matches.
403 *
404 * @test
405 */
406 public function globalVarConditionMatchesOnEmptyExpressionWithNoValueSet(): void
407 {
408 $testKey = $this->getUniqueId('test');
409 $this->assertTrue($this->subject->match('[globalVar = GP:' . $testKey . '=]'));
410 $this->assertTrue($this->subject->match('[globalVar = GP:' . $testKey . ' = ]'));
411 }
412
413 /**
414 * Tests whether numerical comparison matches.
415 *
416 * @test
417 */
418 public function globalVarConditionDoesNotMatchOnEmptyExpressionWithValueSetToZero(): void
419 {
420 $testKey = $this->getUniqueId('test');
421 $_GET = [];
422 $_POST = [$testKey => 0];
423 $this->assertFalse($this->subject->match('[globalVar = GP:' . $testKey . '=]'));
424 $this->assertFalse($this->subject->match('[globalVar = GP:' . $testKey . ' = ]'));
425 }
426
427 /**
428 * Tests whether an array with zero as key matches its value
429 *
430 * @test
431 */
432 public function globalVarConditionMatchesOnArrayExpressionWithZeroAsKey(): void
433 {
434 $testKey = $this->getUniqueId('test');
435 $testValue = '1';
436 $_GET = [];
437 $_POST = [$testKey => ['0' => $testValue]];
438 $this->assertTrue($this->subject->match('[globalVar = GP:' . $testKey . '|0=' . $testValue . ']'));
439 }
440
441 /**
442 * Tests whether string comparison matches.
443 *
444 * @test
445 */
446 public function globalStringConditionMatchesOnEqualExpression(): void
447 {
448 $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3.Test.Condition]'));
449 $this->assertFalse($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3]'));
450 }
451
452 /**
453 * Tests whether string comparison matches.
454 *
455 * @test
456 */
457 public function globalStringConditionMatchesOnEmptyExpressionWithValueSetToEmptyString(): void
458 {
459 $testKey = $this->getUniqueId('test');
460 $_GET = [];
461 $_POST = [$testKey => ''];
462 $this->assertTrue($this->subject->match('[globalString = GP:' . $testKey . '=]'));
463 $this->assertTrue($this->subject->match('[globalString = GP:' . $testKey . ' = ]'));
464 }
465
466 /**
467 * Tests whether string comparison matches.
468 *
469 * @test
470 */
471 public function globalStringConditionMatchesOnEmptyLiteralExpressionWithValueSetToEmptyString(): void
472 {
473 $this->assertTrue($this->subject->match('[globalString = LIT:=]'));
474 $this->assertTrue($this->subject->match('[globalString = LIT: = ]'));
475 }
476
477 /**
478 * Tests whether string comparison matches.
479 *
480 * @test
481 */
482 public function globalStringConditionMatchesWildcardExpression(): void
483 {
484 $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3?Test?Condition]'));
485 $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3.T*t.Condition]'));
486 $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = TYPO3?T*t?Condition]'));
487 }
488
489 /**
490 * Tests whether string comparison matches.
491 *
492 * @test
493 */
494 public function globalStringConditionMatchesRegularExpression(): void
495 {
496 $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = /^[A-Za-z3.]+$/]'));
497 $this->assertTrue($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = /^TYPO3\\..+Condition$/]'));
498 $this->assertFalse($this->subject->match('[globalString = LIT:TYPO3.Test.Condition = /^FALSE/]'));
499 }
500
501 /**
502 * Tests whether string comparison matches.
503 *
504 * @test
505 */
506 public function globalStringConditionMatchesEmptyRegularExpression(): void
507 {
508 $testKey = $this->getUniqueId('test');
509 $GLOBALS['_SERVER'][$testKey] = '';
510 $this->assertTrue($this->subject->match('[globalString = _SERVER|' . $testKey . ' = /^$/]'));
511 }
512
513 /**
514 * Tests whether treeLevel comparison matches.
515 *
516 * @test
517 */
518 public function treeLevelConditionMatchesSingleValue(): void
519 {
520 $this->assertTrue($this->subject->match('[treeLevel = 2]'));
521 }
522
523 /**
524 * Tests whether treeLevel comparison matches.
525 *
526 * @test
527 */
528 public function treeLevelConditionMatchesMultipleValues(): void
529 {
530 $this->assertTrue($this->subject->match('[treeLevel = 999,998,2]'));
531 }
532
533 /**
534 * Tests whether treeLevel comparison matches.
535 *
536 * @test
537 */
538 public function treeLevelConditionDoesNotMatchFaultyValue(): void
539 {
540 $this->assertFalse($this->subject->match('[treeLevel = 999]'));
541 }
542
543 /**
544 * @return array
545 */
546 public function pageDataProvider(): array
547 {
548 return [
549 '[page|layout = 0]' => ['[page|layout = 0]', true],
550 '[page|layout = 1]' => ['[page|layout = 1]', false],
551 '[page|title = Foo]' => ['[page|title = Foo]', true],
552 ];
553 }
554
555 /**
556 * @test
557 * @dataProvider pageDataProvider
558 * @param string $expression
559 * @param bool $expected
560 */
561 public function checkConditionMatcherForPage(string $expression, bool $expected): void
562 {
563 $GLOBALS['TSFE']->page = ['title' => 'Foo', 'layout' => 0];
564 $this->getFreshConditionMatcher();
565 $this->assertSame($expected, $this->subject->match($expression));
566 }
567
568 /**
569 * Tests whether a page Id is found in the previous rootline entries.
570 *
571 * @test
572 */
573 public function PIDupinRootlineConditionMatchesSinglePageIdInRootline(): void
574 {
575 $GLOBALS['TSFE']->id = 121;
576 $this->getFreshConditionMatcher();
577 $this->assertTrue($this->subject->match('[PIDupinRootline = 111]'));
578 }
579
580 /**
581 * Tests whether a page Id is found in the previous rootline entries.
582 *
583 * @test
584 */
585 public function PIDupinRootlineConditionMatchesMultiplePageIdsInRootline(): void
586 {
587 $GLOBALS['TSFE']->id = 121;
588 $this->getFreshConditionMatcher();
589 $this->assertTrue($this->subject->match('[PIDupinRootline = 999,111,101]'));
590 }
591
592 /**
593 * Tests whether a page Id is found in the previous rootline entries.
594 *
595 * @test
596 */
597 public function PIDupinRootlineConditionDoesNotMatchPageIdNotInRootline(): void
598 {
599 $GLOBALS['TSFE']->id = 121;
600 $this->getFreshConditionMatcher();
601 $this->assertFalse($this->subject->match('[PIDupinRootline = 999]'));
602 }
603
604 /**
605 * Tests whether a page Id is found in the previous rootline entries.
606 *
607 * @test
608 */
609 public function PIDupinRootlineConditionDoesNotMatchLastPageIdInRootline(): void
610 {
611 $GLOBALS['TSFE']->id = 121;
612 $this->getFreshConditionMatcher();
613 $this->assertFalse($this->subject->match('[PIDupinRootline = 121]'));
614 }
615
616 /**
617 * Tests whether a page Id is found in all rootline entries.
618 *
619 * @test
620 */
621 public function PIDinRootlineConditionMatchesSinglePageIdInRootline(): void
622 {
623 $GLOBALS['TSFE']->id = 121;
624 $this->getFreshConditionMatcher();
625 $this->assertTrue($this->subject->match('[PIDinRootline = 111]'));
626 }
627
628 /**
629 * Tests whether a page Id is found in all rootline entries.
630 *
631 * @test
632 */
633 public function PIDinRootlineConditionMatchesMultiplePageIdsInRootline(): void
634 {
635 $GLOBALS['TSFE']->id = 121;
636 $this->getFreshConditionMatcher();
637 $this->assertTrue($this->subject->match('[PIDinRootline = 999,111,101]'));
638 }
639
640 /**
641 * Tests whether a page Id is found in all rootline entries.
642 *
643 * @test
644 */
645 public function PIDinRootlineConditionMatchesLastPageIdInRootline(): void
646 {
647 $GLOBALS['TSFE']->id = 121;
648 $this->getFreshConditionMatcher();
649 $this->assertTrue($this->subject->match('[PIDinRootline = 121]'));
650 }
651
652 /**
653 * Tests whether a page Id is found in all rootline entries.
654 *
655 * @test
656 */
657 public function PIDinRootlineConditionDoesNotMatchPageIdNotInRootline(): void
658 {
659 $GLOBALS['TSFE']->id = 121;
660 $this->assertFalse($this->subject->match('[PIDinRootline = 999]'));
661 }
662
663 /**
664 * Tests whether the compatibility version can be evaluated.
665 * (e.g. 7.9 is compatible to 7.0 but not to 15.0)
666 *
667 * @test
668 */
669 public function compatVersionConditionMatchesOlderRelease(): void
670 {
671 $this->assertTrue($this->subject->match('[compatVersion = 7.0]'));
672 }
673
674 /**
675 * Tests whether the compatibility version can be evaluated.
676 * (e.g. 7.9 is compatible to 7.0 but not to 15.0)
677 *
678 * @test
679 */
680 public function compatVersionConditionMatchesSameRelease(): void
681 {
682 $this->assertTrue($this->subject->match('[compatVersion = ' . TYPO3_branch . ']'));
683 }
684
685 /**
686 * Tests whether the compatibility version can be evaluated.
687 * (e.g. 7.9 is compatible to 7.0 but not to 15.0)
688 *
689 * @test
690 */
691 public function compatVersionConditionDoesNotMatchNewerRelease(): void
692 {
693 $this->assertFalse($this->subject->match('[compatVersion = 15.0]'));
694 }
695
696 /**
697 * Tests whether the generic fetching of variables works with the namespace 'GP'.
698 *
699 * @test
700 */
701 public function genericGetVariablesSucceedsWithNamespaceGP(): void
702 {
703 $_GET = ['testGet' => 'getTest'];
704 $_POST = ['testPost' => 'postTest'];
705 $this->getFreshConditionMatcher();
706 $this->assertTrue($this->subject->match('[globalString = GP:testGet = getTest]'));
707 $this->assertTrue($this->subject->match('[globalString = GP:testPost = postTest]'));
708 }
709
710 /**
711 * Tests whether the generic fetching of variables works with the namespace 'TSFE'.
712 *
713 * @test
714 */
715 public function genericGetVariablesSucceedsWithNamespaceTSFE(): void
716 {
717 $GLOBALS['TSFE']->id = 1234567;
718 $GLOBALS['TSFE']->testSimpleObject = new \stdClass();
719 $GLOBALS['TSFE']->testSimpleObject->testSimpleVariable = 'testValue';
720
721 $this->getFreshConditionMatcher();
722 $this->assertTrue($this->subject->match('[globalString = TSFE:id = 1234567]'));
723 $this->assertTrue($this->subject->match('[globalString = TSFE:testSimpleObject|testSimpleVariable = testValue]'));
724 }
725
726 /**
727 * Tests whether the generic fetching of variables works with the namespace 'session'.
728 *
729 * @test
730 */
731 public function genericGetVariablesSucceedsWithNamespaceSession(): void
732 {
733 $prophecy = $this->prophesize(FrontendUserAuthentication::class);
734 $prophecy->getSessionData(Argument::exact('foo'))->willReturn(['bar' => 1234567]);
735 $GLOBALS['TSFE']->fe_user = $prophecy->reveal();
736
737 $this->getFreshConditionMatcher();
738 $this->assertTrue($this->subject->match('[globalString = session:foo|bar = 1234567]'));
739 }
740
741 /**
742 * Tests whether the generic fetching of variables works with the namespace 'ENV'.
743 *
744 * @test
745 */
746 public function genericGetVariablesSucceedsWithNamespaceENV(): void
747 {
748 $testKey = $this->getUniqueId('test');
749 putenv($testKey . '=testValue');
750 $this->getFreshConditionMatcher();
751 $this->assertTrue($this->subject->match('[globalString = ENV:' . $testKey . ' = testValue]'));
752 }
753
754 /**
755 * Tests whether the generic fetching of variables works with the namespace 'IENV'.
756 *
757 * @test
758 */
759 public function genericGetVariablesSucceedsWithNamespaceIENV(): void
760 {
761 $_SERVER['HTTP_HOST'] = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY') . ':1234567';
762 // getIndpEnv() is polluted after above call, clear cache to have it recalculate for subject execption
763 GeneralUtility::flushInternalRuntimeCaches();
764 $this->getFreshConditionMatcher();
765 $this->assertTrue($this->subject->match('[globalString = IENV:TYPO3_PORT = 1234567]'));
766 }
767
768 /**
769 * Tests whether the generic fetching of variables works with any global namespace.
770 *
771 * @test
772 */
773 public function genericGetVariablesSucceedsWithAnyGlobalNamespace(): void
774 {
775 $GLOBALS[$this->testGlobalNamespace] = [
776 'first' => 'testFirst',
777 'second' => ['third' => 'testThird']
778 ];
779 $this->getFreshConditionMatcher();
780 $this->assertTrue($this->subject->match('[globalString = ' . $this->testGlobalNamespace . '|first = testFirst]'));
781 $this->assertTrue($this->subject->match('[globalString = ' . $this->testGlobalNamespace . '|second|third = testThird]'));
782 }
783
784 /**
785 * Tests whether any property of a site language matches the request
786 *
787 * @test
788 */
789 public function siteLanguageMatchesCondition(): void
790 {
791 $site = new Site('angelo', 13, [
792 'languages' => [
793 [
794 'languageId' => 0,
795 'title' => 'United States',
796 'locale' => 'en_US.UTF-8',
797 ],
798 [
799 'languageId' => 2,
800 'title' => 'UK',
801 'locale' => 'en_UK.UTF-8',
802 ]
803 ]
804 ]);
805 $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
806 $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('language', $site->getLanguageById(0));
807 $this->getFreshConditionMatcher();
808 $this->assertTrue($this->subject->match('[siteLanguage = locale = en_US.UTF-8]'));
809 $this->assertTrue($this->subject->match('[siteLanguage = locale = de_DE, locale = en_US.UTF-8]'));
810 }
811
812 /**
813 * Tests whether any property of a site language does NOT match the request
814 *
815 * @test
816 */
817 public function siteLanguageDoesNotMatchCondition(): void
818 {
819 $site = new Site('angelo', 13, [
820 'languages' => [
821 [
822 'languageId' => 0,
823 'title' => 'United States',
824 'locale' => 'en_US.UTF-8',
825 ],
826 [
827 'languageId' => 2,
828 'title' => 'UK',
829 'locale' => 'en_UK.UTF-8',
830 ]
831 ]
832 ]);
833 $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
834 $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('language', $site->getLanguageById(0));
835 $this->getFreshConditionMatcher();
836 $this->assertFalse($this->subject->match('[siteLanguage = locale = en_UK.UTF-8]'));
837 $this->assertFalse($this->subject->match('[siteLanguage = locale = de_DE, title = UK]'));
838 }
839
840 /**
841 * Tests whether any property of a site matches the request
842 *
843 * @test
844 */
845 public function siteMatchesCondition(): void
846 {
847 $site = new Site('angelo', 13, ['languages' => [], 'base' => 'https://typo3.org/']);
848 $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
849 $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('site', $site);
850 $this->getFreshConditionMatcher();
851 $this->assertTrue($this->subject->match('[site = identifier = angelo]'));
852 $this->assertTrue($this->subject->match('[site = rootPageId = 13]'));
853 $this->assertTrue($this->subject->match('[site = base = https://typo3.org/]'));
854 }
855
856 /**
857 * Tests whether any property of a site that does NOT match the request
858 *
859 * @test
860 */
861 public function siteDoesNotMatchCondition(): void
862 {
863 $site = new Site('angelo', 13, [
864 'languages' => [
865 [
866 'languageId' => 0,
867 'title' => 'United States',
868 'locale' => 'en_US.UTF-8',
869 ],
870 [
871 'languageId' => 2,
872 'title' => 'UK',
873 'locale' => 'en_UK.UTF-8',
874 ]
875 ]
876 ]);
877 $GLOBALS['TYPO3_REQUEST'] = new ServerRequest();
878 $GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']->withAttribute('site', $site);
879 $this->getFreshConditionMatcher();
880 $this->assertFalse($this->subject->match('[site = identifier = berta]'));
881 $this->assertFalse($this->subject->match('[site = rootPageId = 14, rootPageId=23]'));
882 }
883
884 /**
885 * @test
886 */
887 public function matchThrowsExceptionIfConditionClassDoesNotInheritFromAbstractCondition(): void
888 {
889 $this->expectException(InvalidTypoScriptConditionException::class);
890 $this->expectExceptionCode(1410286153);
891 $this->getFreshConditionMatcher();
892 $loggerProphecy = $this->prophesize(Logger::class);
893 $this->subject->setLogger($loggerProphecy->reveal());
894 $this->subject->match('[stdClass = foo]');
895 }
896
897 /**
898 * @test
899 */
900 public function matchCallsTestConditionAndHandsOverParameters(): void
901 {
902 $this->expectException(TestConditionException::class);
903 $this->expectExceptionCode(1411581139);
904 $this->getFreshConditionMatcher();
905 $loggerProphecy = $this->prophesize(Logger::class);
906 $this->subject->setLogger($loggerProphecy->reveal());
907 $this->subject->match('[TYPO3\\CMS\\Frontend\\Tests\\UnitDeprecated\\Configuration\\TypoScript\\ConditionMatching\\Fixtures\\TestCondition = 7, != 6]');
908 }
909 }