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