71f657f4cecf23987b540f7e013f3b0bcedc0e2a
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Tests / Functional / SiteHandling / EnhancerSiteRequestTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Frontend\Tests\Functional\SiteHandling;
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\Core\Bootstrap;
19 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
20 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
21 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
22 use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequestContext;
23
24 /**
25 * Test case for frontend requests having site handling configured using enhancers.
26 */
27 class EnhancerSiteRequestTest extends AbstractTestCase
28 {
29 /**
30 * @var string
31 */
32 private $siteTitle = 'A Company that Manufactures Everything Inc';
33
34 /**
35 * @var InternalRequestContext
36 */
37 private $internalRequestContext;
38
39 public static function setUpBeforeClass()
40 {
41 parent::setUpBeforeClass();
42 static::initializeDatabaseSnapshot();
43 }
44
45 public static function tearDownAfterClass()
46 {
47 static::destroyDatabaseSnapshot();
48 parent::tearDownAfterClass();
49 }
50
51 protected function setUp()
52 {
53 parent::setUp();
54
55 // these settings are forwarded to the frontend sub-request as well
56 $this->internalRequestContext = (new InternalRequestContext())
57 ->withGlobalSettings(['TYPO3_CONF_VARS' => static::TYPO3_CONF_VARS]);
58
59 $this->writeSiteConfiguration(
60 'acme-com',
61 $this->buildSiteConfiguration(1000, 'https://acme.com/'),
62 [
63 $this->buildDefaultLanguageConfiguration('EN', 'https://acme.us/'),
64 $this->buildLanguageConfiguration('FR', 'https://acme.fr/', ['EN']),
65 $this->buildLanguageConfiguration('FR-CA', 'https://acme.ca/', ['FR', 'EN']),
66 ]
67 );
68
69 $this->withDatabaseSnapshot(function () {
70 $this->setUpDatabase();
71 });
72 }
73
74 protected function setUpDatabase()
75 {
76 $backendUser = $this->setUpBackendUserFromFixture(1);
77 Bootstrap::initializeLanguageObject();
78
79 $scenarioFile = __DIR__ . '/Fixtures/SlugScenario.yaml';
80 $factory = DataHandlerFactory::fromYamlFile($scenarioFile);
81 $writer = DataHandlerWriter::withBackendUser($backendUser);
82 $writer->invokeFactory($factory);
83 static::failIfArrayIsNotEmpty(
84 $writer->getErrors()
85 );
86
87 $this->setUpFrontendRootPage(
88 1000,
89 [
90 'typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/LinkRequest.typoscript',
91 ],
92 [
93 'title' => 'ACME Root',
94 'sitetitle' => $this->siteTitle,
95 ]
96 );
97 }
98
99 protected function tearDown()
100 {
101 unset($this->internalRequestContext);
102 parent::tearDown();
103 }
104
105 /**
106 * @param array $aspect
107 * @param array $enhancerLanguageUris
108 * @param array $enhancers
109 * @param string $variableName
110 * @param string $templateSuffix
111 * @return array
112 */
113 protected function createDataSet(
114 array $aspect,
115 array $enhancerLanguageUris,
116 array $enhancers,
117 string $variableName = 'value',
118 string $templateSuffix = ''
119 ): array {
120 $dataSet = [];
121 foreach ($enhancers as $enhancer) {
122 $enhancerType = $enhancer['enhancer']['type'];
123 foreach ($enhancerLanguageUris[$enhancerType] as $languageId => $uri) {
124 $expectation = $enhancer['arguments'];
125 $expectation['staticArguments'] = $expectation['staticArguments'] ?? [];
126 $expectation['dynamicArguments'] = $expectation['dynamicArguments'] ?? [];
127 $expectation['queryArguments'] = $expectation['queryArguments'] ?? [];
128 if (preg_match('#\?cHash=([a-z0-9]+)#i', $uri, $matches)) {
129 $expectation['dynamicArguments']['cHash'] = $matches[1];
130 $expectation['queryArguments']['cHash'] = $matches[1];
131 }
132 $dataSet[] = [
133 array_merge(
134 $enhancer['enhancer'],
135 ['aspects' => [$variableName => $aspect]]
136 ),
137 $uri,
138 $languageId,
139 $expectation,
140 ];
141 }
142 }
143 return $this->keysFromTemplate(
144 $dataSet,
145 'enhancer:%1$s, lang:%3$d' . $templateSuffix,
146 function (array $items) {
147 array_splice(
148 $items,
149 0,
150 1,
151 $items[0]['type']
152 );
153 return $items;
154 }
155 );
156 }
157
158 /**
159 * @param array $options
160 * @param bool $isStatic
161 * @return array
162 */
163 protected function getEnhancers(array $options = [], bool $isStatic = false): array
164 {
165 $inArguments = $isStatic ? 'staticArguments' : 'dynamicArguments';
166 $options = array_merge(['name' => 'enhance', 'value' => 100], $options);
167 return [
168 [
169 'arguments' => [
170 $inArguments => [
171 'value' => (string)$options['value'],
172 ],
173 ],
174 'enhancer' => [
175 'type' => 'Simple',
176 'routePath' => sprintf('/%s/{value}', $options['name']),
177 '_arguments' => [],
178 ],
179 ],
180 [
181 'arguments' => [
182 $inArguments => [
183 'testing' => [
184 'value' => (string)$options['value'],
185 ],
186 ],
187 ],
188 'enhancer' => [
189 'type' => 'Plugin',
190 'routePath' => sprintf('/%s/{value}', $options['name']),
191 'namespace' => 'testing',
192 '_arguments' => [],
193 ],
194 ],
195 [
196 'arguments' => array_merge_recursive([
197 $inArguments => [
198 'tx_testing_link' => [
199 'value' => (string)$options['value'],
200 ],
201 ],
202 ], [
203 'staticArguments' => [
204 'tx_testing_link' => [
205 'controller' => 'Link',
206 'action' => 'index',
207 ],
208 ],
209 ]),
210 'enhancer' => [
211 'type' => 'Extbase',
212 'routes' => [
213 [
214 'routePath' => sprintf('/%s/{value}', $options['name']),
215 '_controller' => 'Link::index',
216 '_arguments' => [],
217 ],
218 ],
219 'extension' => 'testing',
220 'plugin' => 'link',
221 ],
222 ],
223 ];
224 }
225
226 /**
227 * @return array
228 */
229 public function localeModifierDataProvider(): array
230 {
231 $aspect = [
232 'type' => 'LocaleModifier',
233 'default' => 'enhance',
234 'localeMap' => [
235 [
236 'locale' => 'fr_FR',
237 'value' => 'augmenter'
238 ]
239 ],
240 ];
241
242 $enhancerLanguageUris = [
243 'Simple' => [
244 '0' => 'https://acme.us/welcome/enhance/100?cHash=46227b4ce096dc78a4e71463326c9020',
245 '1' => 'https://acme.fr/bienvenue/augmenter/100?cHash=46227b4ce096dc78a4e71463326c9020',
246 ],
247 'Plugin' => [
248 '0' => 'https://acme.us/welcome/enhance/100?cHash=e24d3d2d5503baba670d827c3b9470c8',
249 '1' => 'https://acme.fr/bienvenue/augmenter/100?cHash=e24d3d2d5503baba670d827c3b9470c8',
250 ],
251 'Extbase' => [
252 '0' => 'https://acme.us/welcome/enhance/100?cHash=eef21771ab3c3dac3514b4479eedd5ff',
253 '1' => 'https://acme.fr/bienvenue/augmenter/100?cHash=eef21771ab3c3dac3514b4479eedd5ff',
254 ]
255 ];
256
257 return $this->createDataSet(
258 $aspect,
259 $enhancerLanguageUris,
260 $this->getEnhancers(['name' => '{enhance_name}']),
261 'enhance_name'
262 );
263 }
264
265 /**
266 * @param array $enhancer
267 * @param string $targetUri
268 * @param int $expectedLanguageId
269 * @param string $expectation
270 *
271 * @test
272 * @dataProvider localeModifierDataProvider
273 */
274 public function localeModifierIsApplied(array $enhancer, string $targetUri, int $expectedLanguageId, array $expectation)
275 {
276 $this->assertPageArgumentsEquals(
277 $enhancer,
278 $targetUri,
279 $expectedLanguageId,
280 $expectation
281 );
282 }
283
284 /**
285 * @return array
286 */
287 public function persistedAliasMapperDataProvider(): array
288 {
289 $aspect = [
290 'type' => 'PersistedAliasMapper',
291 'tableName' => 'pages',
292 'routeFieldName' => 'slug',
293 'routeValuePrefix' => '/',
294 ];
295
296 $enhancerLanguageUris = $this->populateToKeys(
297 ['Simple', 'Plugin', 'Extbase'],
298 [
299 '0' => 'https://acme.us/welcome/enhance/welcome',
300 '1' => 'https://acme.fr/bienvenue/enhance/bienvenue',
301 ]
302 );
303
304 return $this->createDataSet(
305 $aspect,
306 $enhancerLanguageUris,
307 $this->getEnhancers(['value' => 1100], true)
308 );
309 }
310
311 /**
312 * @param array $enhancer
313 * @param string $targetUri
314 * @param int $expectedLanguageId
315 * @param string $expectation
316 *
317 * @test
318 * @dataProvider persistedAliasMapperDataProvider
319 */
320 public function persistedAliasMapperIsApplied(array $enhancer, string $targetUri, int $expectedLanguageId, array $expectation)
321 {
322 $this->assertPageArgumentsEquals(
323 $enhancer,
324 $targetUri,
325 $expectedLanguageId,
326 $expectation
327 );
328 }
329
330 /**
331 * @return array
332 */
333 public function persistedPatternMapperDataProvider(): array
334 {
335 $aspect = [
336 'type' => 'PersistedPatternMapper',
337 'tableName' => 'pages',
338 'routeFieldPattern' => '^(?P<subtitle>.+)-(?P<uid>\d+)$',
339 'routeFieldResult' => '{subtitle}-{uid}',
340 ];
341
342 $enhancerLanguageUris = $this->populateToKeys(
343 ['Simple', 'Plugin', 'Extbase'],
344 [
345 '0' => 'https://acme.us/welcome/enhance/hello-and-welcome-1100',
346 '1' => 'https://acme.fr/bienvenue/enhance/salut-et-bienvenue-1100',
347 ]
348 );
349
350 return $this->createDataSet(
351 $aspect,
352 $enhancerLanguageUris,
353 $this->getEnhancers(['value' => 1100], true)
354 );
355 }
356
357 /**
358 * @param array $enhancer
359 * @param string $targetUri
360 * @param int $expectedLanguageId
361 * @param string $expectation
362 *
363 * @test
364 * @dataProvider persistedPatternMapperDataProvider
365 */
366 public function persistedPatternMapperIsApplied(array $enhancer, string $targetUri, int $expectedLanguageId, array $expectation)
367 {
368 $this->assertPageArgumentsEquals(
369 $enhancer,
370 $targetUri,
371 $expectedLanguageId,
372 $expectation
373 );
374 }
375
376 /**
377 * @return array
378 */
379 public function staticValueMapperDataProvider(): array
380 {
381 $aspect = [
382 'type' => 'StaticValueMapper',
383 'map' => [
384 'hundred' => 100,
385 ],
386 'localeMap' => [
387 [
388 'locale' => 'fr_FR',
389 'map' => [
390 'cent' => 100,
391 ],
392 ]
393 ],
394 ];
395
396 $enhancerLanguageUris = $this->populateToKeys(
397 ['Simple', 'Plugin', 'Extbase'],
398 [
399 '0' => 'https://acme.us/welcome/enhance/hundred',
400 '1' => 'https://acme.fr/bienvenue/enhance/cent',
401 ]
402 );
403
404 return $this->createDataSet(
405 $aspect,
406 $enhancerLanguageUris,
407 $this->getEnhancers([], true)
408 );
409 }
410
411 /**
412 * @param array $enhancer
413 * @param string $targetUri
414 * @param int $expectedLanguageId
415 * @param string $expectation
416 *
417 * @test
418 * @dataProvider staticValueMapperDataProvider
419 */
420 public function staticValueMapperIsApplied(array $enhancer, string $targetUri, int $expectedLanguageId, array $expectation)
421 {
422 $this->assertPageArgumentsEquals(
423 $enhancer,
424 $targetUri,
425 $expectedLanguageId,
426 $expectation
427 );
428 }
429
430 /**
431 * @return array
432 */
433 public function staticRangeMapperDataProvider(): array
434 {
435 $aspect = [
436 'type' => 'StaticRangeMapper',
437 'start' => '1',
438 'end' => '100',
439 ];
440
441 $dataSet = [];
442 foreach (range(10, 100, 30) as $value) {
443 $enhancerLanguageUris = $this->populateToKeys(
444 ['Simple', 'Plugin', 'Extbase'],
445 [
446 '0' => sprintf('https://acme.us/welcome/enhance/%s', $value),
447 '1' => sprintf('https://acme.fr/bienvenue/enhance/%s', $value),
448 ]
449 );
450
451 $dataSet = array_merge(
452 $dataSet,
453 $this->createDataSet(
454 $aspect,
455 $enhancerLanguageUris,
456 $this->getEnhancers(['value' => $value], true),
457 'value',
458 sprintf(', value:%d', $value)
459 )
460 );
461 }
462 return $dataSet;
463 }
464
465 /**
466 * @param array $enhancer
467 * @param string $targetUri
468 * @param int $expectedLanguageId
469 * @param string $expectation
470 *
471 * @test
472 * @dataProvider staticRangeMapperDataProvider
473 */
474 public function staticRangeMapperIsApplied(array $enhancer, string $targetUri, int $expectedLanguageId, array $expectation)
475 {
476 $this->assertPageArgumentsEquals(
477 $enhancer,
478 $targetUri,
479 $expectedLanguageId,
480 $expectation
481 );
482 }
483
484 /**
485 * @param array $enhancer
486 * @param string $targetUri
487 * @param int $expectedLanguageId
488 * @param array $expectation
489 */
490 protected function assertPageArgumentsEquals(array $enhancer, string $targetUri, int $expectedLanguageId, array $expectation)
491 {
492 $this->mergeSiteConfiguration('acme-com', [
493 'routeEnhancers' => ['Enhancer' => $enhancer]
494 ]);
495
496 $allParameters = array_replace_recursive(
497 $expectation['dynamicArguments'],
498 $expectation['staticArguments']
499 );
500 $expectation['pageId'] = 1100;
501 $expectation['languageId'] = $expectedLanguageId;
502 $expectation['requestQueryParams'] = $allParameters;
503 $expectation['_GET'] = $allParameters;
504
505 $response = $this->executeFrontendRequest(
506 new InternalRequest($targetUri),
507 $this->internalRequestContext,
508 true
509 );
510
511 $pageArguments = json_decode((string)$response->getBody(), true);
512 static::assertEquals($expectation, $pageArguments);
513 }
514 }