‪TYPO3CMS  9.5
PersistedAliasMapperTest.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
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 
27 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
28 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
29 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
30 
31 class ‪PersistedAliasMapperTest extends FunctionalTestCase
32 {
33  private const ‪ASPECT_CONFIGURATION = [
34  'tableName' => 'tt_content',
35  'routeFieldName' => 'header',
36  ];
37 
38  private const ‪SLUG_CONFIGURATION = [
39  'type' => 'slug',
40  'generatorOptions' => [
41  'prefixParentPageSlug' => false,
42  ],
43  'fallbackCharacter' => '-',
44  'eval' => 'required,uniqueInSite',
45  'default' => ''
46  ];
47 
48  private const ‪LANGUAGE_MAP = [
49  'es-es' => 3,
50  'fr-ca' => 2,
51  'fr-fr' => 1,
52  'default' => 0,
53  ];
54 
55  private const ‪SITE_ADDITION = [
56  'acme' => 0,
57  'other' => 4000,
58  ];
59 
63  private ‪$subject;
64 
68  private ‪$sites;
69 
70  public static function ‪setUpBeforeClass(): void
71  {
72  parent::setUpBeforeClass();
73  static::initializeDatabaseSnapshot();
74  }
75 
76  public static function ‪tearDownAfterClass(): void
77  {
78  static::destroyDatabaseSnapshot();
79  parent::tearDownAfterClass();
80  }
81 
82  protected function ‪setUp(): void
83  {
84  parent::setUp();
85  $this->withDatabaseSnapshot(function () {
86  $this->‪setUpDatabase();
87  });
88 
89  // declare tt_content.header as `slug` field having `uniqueInSite` set
90  $tableName = self::ASPECT_CONFIGURATION['tableName'];
91  $fieldName = self::ASPECT_CONFIGURATION['routeFieldName'];
92  ‪$GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config'] = ‪self::SLUG_CONFIGURATION;
93 
94  $languages = [
95  [
96  'languageId' => 3,
97  'base' => '/es-es/',
98  'locale' => 'es_ES.UTF-8',
99  'fallbackType' => 'fallback',
100  'fallbacks' => [0],
101  'title' => 'Spanish',
102  ],
103  [
104  'languageId' => 2,
105  'base' => '/fr-ca/',
106  'locale' => 'fr_CA.UTF-8',
107  'fallbackType' => 'fallback',
108  'fallbacks' => [1, 0],
109  'title' => 'Franco-Canadian',
110  ],
111  [
112  'languageId' => 1,
113  'base' => '/fr-fr/',
114  'locale' => 'fr_FR.UTF-8',
115  'fallbackType' => 'fallback',
116  'fallbacks' => [0],
117  'French',
118  ],
119  [
120  'languageId' => 0,
121  'base' => 'en_US.UTF-8',
122  'locale' => '/en-us/',
123  ],
124  ];
125  $this->sites = [
126  'acme' => new Site('acme-inc', 1000, [
127  'identifier' => 'acme-inc',
128  'rootPageId' => 1000,
129  'base' => 'https://acme.com/',
130  'languages' => $languages,
131  ]),
132  'other' => new Site('other-inc', 5000, [
133  'identifier' => 'other-inc',
134  'rootPageId' => 5000,
135  'base' => 'https://other.com/',
136  'languages' => $languages,
137  ]),
138  ];
139  $this->‪writeSiteConfiguration($this->sites['acme']);
140  $this->‪writeSiteConfiguration($this->sites['other']);
141  $this->subject = new PersistedAliasMapper(self::ASPECT_CONFIGURATION);
142  $this->subject->setSiteLanguage($this->sites['acme']->getLanguageById(0));
143  $this->subject->setSite($this->sites['acme']);
144  }
145 
146  protected function ‪setUpDatabase()
147  {
148  $backendUser = $this->setUpBackendUserFromFixture(1);
150 
151  $scenarioFile = __DIR__ . '/Fixtures/AspectScenario.yaml';
152  $factory = DataHandlerFactory::fromYamlFile($scenarioFile);
153  $writer = DataHandlerWriter::withBackendUser($backendUser);
154  $writer->invokeFactory($factory);
155  if (!empty($writer->getErrors())) {
156  self::fail(var_export($writer->getErrors(), true));
157  }
158  }
159 
160  protected function ‪tearDown(): void
161  {
162  unset($this->subject, $this->sites);
163  parent::tearDown();
164  }
165 
166  public function ‪languageAwareRecordsAreResolvedDataProvider(): array
167  {
168  $baseDataSet = [
169  'non-existing, default language' => ['this-value-does-not-exist', 'default', null],
170 
171  '30xx-slug, default language' => ['30xx-slug', 'default', '3010'],
172  '30xx-slug, fr-fr language' => ['30xx-slug', 'fr-fr', '3010'],
173  '30xx-slug, fr-ca language' => ['30xx-slug', 'fr-ca', '3010'],
174 
175  '30xx-slug-fr-ca, fr-ca language' => ['30xx-slug-fr-ca', 'fr-ca', '3010'],
176  // '30xx-slug-fr-ca' available in default language as well, fallbacks to that one
177  '30xx-slug-fr-ca, fr-fr language' => ['30xx-slug-fr-ca', 'fr-fr', '3030'],
178  // '30xx-slug-fr-ca' available in default language, use it directly
179  '30xx-slug-fr-ca, default language' => ['30xx-slug-fr-ca', 'default', '3030'],
180 
181  '30xx-slug-fr, fr-ca language' => ['30xx-slug-fr', 'fr-ca', '3010'],
182  '30xx-slug-fr, fr-fr language' => ['30xx-slug-fr', 'fr-fr', '3010'],
183  // '30xx-slug-fr-ca' available in default language, use it directly
184  '30xx-slug-fr, default language' => ['30xx-slug-fr', 'default', '3020'],
185 
186  // basically the same, but being stored in reverse order in database
187  '40xx-slug, default language' => ['40xx-slug', 'default', '4040'],
188  '40xx-slug, fr-fr language' => ['40xx-slug', 'fr-fr', '4040'],
189  '40xx-slug, fr-ca language' => ['40xx-slug', 'fr-ca', '4040'],
190 
191  '40xx-slug-fr-ca, fr-ca language' => ['40xx-slug-fr-ca', 'fr-ca', '4040'],
192  // '40xx-slug-fr-ca' available in default language as well, fallbacks to that one
193  '40xx-slug-fr-ca, fr-fr language' => ['40xx-slug-fr-ca', 'fr-fr', '4030'],
194  // '40xx-slug-fr-ca' available in default language, use it directly
195  '40xx-slug-fr-ca, default language' => ['40xx-slug-fr-ca', 'default', '4030'],
196 
197  '40xx-slug-fr, fr-ca language' => ['40xx-slug-fr', 'fr-ca', '4040'],
198  '40xx-slug-fr, fr-fr language' => ['40xx-slug-fr', 'fr-fr', '4040'],
199  // '40xx-slug-fr-ca' available in default language, use it directly
200  '40xx-slug-fr, default language' => ['40xx-slug-fr', 'default', '4020'],
201  ];
202  // permute $baseDataSet to be either prepended
203  // with site identifier argument 'acme' or 'other'
204  $dataSet = [];
205  foreach (['acme', 'other'] as $site) {
206  foreach ($baseDataSet as $key => $arguments) {
207  array_unshift($arguments, $site);
208  $dataSet[$site . ':' . $key] = $arguments;
209  }
210  }
211  return $dataSet;
212  }
213 
223  public function ‪languageAwareRecordsAreResolved(string $identifier, string $requestValue, string $language, ?string $expectation): void
224  {
225  $this->subject->setSiteLanguage(
226  $this->sites[$identifier]->getLanguageById(self::LANGUAGE_MAP[$language])
227  );
228  $this->subject->setSite(
229  $this->sites[$identifier]
230  );
231  if ($expectation !== null) {
232  $expectation += self::SITE_ADDITION[$identifier];
233  $expectation = (string)$expectation;
234  }
235  self::assertSame($expectation, $this->subject->resolve($requestValue));
236  }
237 
238  public function ‪recordVisibilityDataProvider(): array
239  {
240  $rawContext = new ‪Context();
241  $visibleContext = new ‪Context();
242  $visibleContext->setAspect(
243  'visibility',
244  new ‪VisibilityAspect(false, true, false)
245  );
246  $frontendGroupsContext = new ‪Context();
247  $frontendGroupsContext->setAspect(
248  'frontend.user',
249  new ‪UserAspect(null, [13])
250  );
251  $scheduledContext = new ‪Context();
252  $scheduledContext->setAspect(
253  'date',
254  new ‪DateTimeAspect(new \DateTimeImmutable('@20000'))
255  );
256 
257  return [
258  'hidden-visibility-slug, raw context' => [
259  $rawContext,
260  ['slug' => 'hidden-visibility-slug', 'uid' => '4051'],
261  false,
262  ],
263  // fe_group slugs are always considered
264  'restricted-visibility-slug, raw context' => [
265  $rawContext,
266  ['slug' => 'restricted-visibility-slug', 'uid' => '4052'],
267  true,
268  ],
269  'scheduled-visibility-slug, raw context' => [
270  $rawContext,
271  ['slug' => 'scheduled-visibility-slug', 'uid' => '4053'],
272  false,
273  ],
274  'hidden-visibility-slug, visibility context (include hidden content)' => [
275  $visibleContext,
276  ['slug' => 'hidden-visibility-slug', 'uid' => '4051'],
277  true,
278  ],
279  // fe_group slugs are always considered
280  'restricted-visibility-slug, frontend-groups context (13)' => [
281  $frontendGroupsContext,
282  ['slug' => 'restricted-visibility-slug', 'uid' => '4052'],
283  true,
284  ],
285  'scheduled-visibility-slug, scheduled context (timestamp 20000)' => [
286  $scheduledContext,
287  ['slug' => 'scheduled-visibility-slug', 'uid' => '4053'],
288  false, // @todo actually `true`, Start-/EndTimeRestriction do not support Context, yet
289  ],
290  ];
291  }
292 
301  public function ‪recordVisibilityIsConsideredForResolving(Context $context, array $parameters, bool $expectation): void
302  {
303  $this->subject->setContext($context);
304  $expectedResult = $expectation ? $parameters['uid'] : null;
305  self::assertSame($expectedResult, $this->subject->resolve($parameters['slug']));
306  }
307 
316  public function ‪recordVisibilityIsConsideredForGeneration(Context $context, array $parameters, bool $expectation): void
317  {
318  $this->subject->setContext($context);
319  $expectedResult = $expectation ? $parameters['slug'] : null;
320  self::assertSame($expectedResult, $this->subject->generate($parameters['uid']));
321  }
322 
323  private function ‪writeSiteConfiguration(‪Site $site): void
324  {
325  try {
326  // ensure no previous site configuration influences the test
327  $path = $this->instancePath . '/typo3conf/sites';
328  GeneralUtility::rmdir($path . '/' . $site->‪getIdentifier(), true);
329  GeneralUtility::makeInstance(SiteConfiguration::class, $path)->write($site->‪getIdentifier(), $site->‪getConfiguration());
330  } catch (\‪Exception $exception) {
331  self::markTestSkipped($exception->getMessage());
332  }
333  }
334 }
‪TYPO3\CMS\Core\Context\VisibilityAspect
Definition: VisibilityAspect.php:29
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\recordVisibilityIsConsideredForGeneration
‪recordVisibilityIsConsideredForGeneration(Context $context, array $parameters, bool $expectation)
Definition: PersistedAliasMapperTest.php:314
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\LANGUAGE_MAP
‪const LANGUAGE_MAP
Definition: PersistedAliasMapperTest.php:48
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\tearDown
‪tearDown()
Definition: PersistedAliasMapperTest.php:158
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\tearDownAfterClass
‪static tearDownAfterClass()
Definition: PersistedAliasMapperTest.php:74
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\SLUG_CONFIGURATION
‪const SLUG_CONFIGURATION
Definition: PersistedAliasMapperTest.php:38
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\recordVisibilityDataProvider
‪recordVisibilityDataProvider()
Definition: PersistedAliasMapperTest.php:236
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect
Definition: PersistedAliasMapperTest.php:3
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:49
‪TYPO3\CMS\Core\Configuration\SiteConfiguration
Definition: SiteConfiguration.php:38
‪TYPO3\CMS\Core\Site\Entity\Site\getConfiguration
‪array getConfiguration()
Definition: Site.php:310
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\setUpBeforeClass
‪static setUpBeforeClass()
Definition: PersistedAliasMapperTest.php:68
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:39
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\languageAwareRecordsAreResolvedDataProvider
‪languageAwareRecordsAreResolvedDataProvider()
Definition: PersistedAliasMapperTest.php:164
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\$sites
‪Site[] $sites
Definition: PersistedAliasMapperTest.php:66
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\setUpDatabase
‪setUpDatabase()
Definition: PersistedAliasMapperTest.php:144
‪TYPO3\CMS\Core\Site\Entity\Site\getIdentifier
‪string getIdentifier()
Definition: Site.php:176
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\languageAwareRecordsAreResolved
‪languageAwareRecordsAreResolved(string $identifier, string $requestValue, string $language, ?string $expectation)
Definition: PersistedAliasMapperTest.php:221
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\SITE_ADDITION
‪const SITE_ADDITION
Definition: PersistedAliasMapperTest.php:55
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\writeSiteConfiguration
‪writeSiteConfiguration(Site $site)
Definition: PersistedAliasMapperTest.php:321
‪TYPO3\CMS\Core\Routing\Aspect\PersistedAliasMapper
Definition: PersistedAliasMapper.php:54
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\$subject
‪PersistedAliasMapper $subject
Definition: PersistedAliasMapperTest.php:62
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest
Definition: PersistedAliasMapperTest.php:32
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:50
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\recordVisibilityIsConsideredForResolving
‪recordVisibilityIsConsideredForResolving(Context $context, array $parameters, bool $expectation)
Definition: PersistedAliasMapperTest.php:299
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\ASPECT_CONFIGURATION
‪const ASPECT_CONFIGURATION
Definition: PersistedAliasMapperTest.php:33
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Context\DateTimeAspect
Definition: DateTimeAspect.php:33
‪TYPO3\CMS\Core\Context\UserAspect
Definition: UserAspect.php:36
‪TYPO3\CMS\Core\Tests\Functional\Routing\Aspect\PersistedAliasMapperTest\setUp
‪setUp()
Definition: PersistedAliasMapperTest.php:80
‪TYPO3\CMS\Core\Core\Bootstrap\initializeLanguageObject
‪static Bootstrap null initializeLanguageObject()
Definition: Bootstrap.php:986