‪TYPO3CMS  11.5
SiteBaseRedirectResolverTest.php
Go to the documentation of this file.
1 <?php
2 
3 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 
19 
20 use Psr\Http\Message\ResponseInterface;
21 use Psr\Http\Message\ServerRequestInterface;
22 use Psr\Http\Server\RequestHandlerInterface;
32 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
33 
34 class ‪SiteBaseRedirectResolverTest extends UnitTestCase
35 {
39  protected ‪$resetSingletonInstances = true;
40 
41  protected RequestHandlerInterface ‪$siteFoundRequestHandler;
42 
46  protected function ‪setUp(): void
47  {
48  parent::setUp();
49  // A request handler which expects a site to be found.
50  $this->siteFoundRequestHandler = new class () implements RequestHandlerInterface {
51  public function handle(ServerRequestInterface $request): ResponseInterface
52  {
55  $site = $request->getAttribute('site', false);
56  $language = $request->getAttribute('language', false);
57  if ($site && $language) {
58  return new ‪JsonResponse(
59  [
60  'site' => $site->getIdentifier(),
61  'language-id' => $language->getLanguageId(),
62  'language-base' => (string)$language->getBase(),
63  'rootpage' => $site->getRootPageId(),
64  ]
65  );
66  }
67  return new ‪NullResponse();
68  }
69  };
70  }
71 
76  {
77  $site1 = new ‪Site('outside-site', 13, [
78  'base' => 'https://twenty.one/',
79  'languages' => [
80  0 => [
81  'languageId' => 0,
82  'locale' => 'en_US.UTF-8',
83  'base' => '/en/',
84  ],
85  1 => [
86  'languageId' => 1,
87  'locale' => 'fr_CA.UTF-8',
88  'base' => '/fr',
89  ],
90  ],
91  ]);
92  $site2 = new ‪Site('sub-site', 14, [
93  'base' => 'https://twenty.one/mysubsite/',
94  'languages' => [
95  2 => [
96  'languageId' => 2,
97  'locale' => 'it_IT.UTF-8',
98  'base' => '/',
99  ],
100  ],
101  ]);
102 
103  return [
104  'redirect to first language' => [
105  'https://twenty.one/',
106  'https://twenty.one/en/',
107  $site1,
108  null,
109  '',
110  ],
111  'redirect to first language adding the slash' => [
112  'https://twenty.one/en',
113  'https://twenty.one/en/',
114  $site1,
115  null,
116  '',
117  ],
118  'redirect to second language removing a slash' => [
119  'https://twenty.one/fr/',
120  'https://twenty.one/fr',
121  $site1,
122  $site1->getLanguageById(1),
123  '/',
124  ],
125  'redirect to subsite by adding a slash' => [
126  'https://twenty.one/mysubsite',
127  'https://twenty.one/mysubsite/',
128  $site2,
129  null,
130  '',
131  ],
132  'redirect to first language and remove nested arguments' => [
133  'https://twenty.one/?foo[bar]=foobar&bar=foo',
134  'https://twenty.one/en/',
135  $site1,
136  null,
137  '',
138  ],
139  'redirect to second language removing a slash but keeping the nested arguments' => [
140  'https://twenty.one/fr/?foo[bar]=foobar&bar=foo',
141  'https://twenty.one/fr?foo%5Bbar%5D=foobar&bar=foo',
142  $site1,
143  $site1->getLanguageById(1),
144  '/',
145  ],
146  ];
147  }
148 
159  string $incomingUrl,
160  string $expectedRedirectUrl,
161  Site $site,
162  ?SiteLanguage $language,
163  string $tail
164  ): void {
165  $routeResult = new SiteRouteResult(new Uri($incomingUrl), $site, $language, $tail);
166  $request = new ServerRequest($incomingUrl, 'GET');
167  $request = $request->withAttribute('site', $site);
168  $request = $request->withAttribute('language', $language);
169  $request = $request->withAttribute('routing', $routeResult);
170 
171  $subject = new SiteBaseRedirectResolver();
172  $response = $subject->process($request, $this->siteFoundRequestHandler);
173  self::assertEquals(307, $response->getStatusCode());
174  self::assertEquals($expectedRedirectUrl, $response->getHeader('Location')[0] ?? '');
175  }
176 
181  {
182  return [
183  'disabled site language' => ['https://twenty.one/en/pilots/', 404, 0],
184  'enabled site language' => ['https://twenty.one/fr/pilots/', 200, 1],
185  ];
186  }
187 
197  string $url,
198  int $expectedStatusCode,
199  int $languageId
200  ): void {
201  $site = new Site('mixed-site', 13, [
202  'base' => '/',
203  'errorHandling' => [
204  [
205  'errorCode' => 404,
206  'errorHandler' => 'PHP',
207  'errorPhpClassFQCN' => PhpError::class,
208  ],
209  ],
210  'languages' => [
211  0 => [
212  'languageId' => 0,
213  'locale' => 'en_US.UTF-8',
214  'base' => '/en/',
215  'enabled' => false,
216  ],
217  1 => [
218  'languageId' => 1,
219  'locale' => 'fr_CA.UTF-8',
220  'base' => '/fr/',
221  'enabled' => true,
222  ],
223  ],
224  ]);
225 
226  // Request to default page
227  $request = new ServerRequest($url, 'GET');
228  $request = $request->withAttribute('site', $site);
229  $request = $request->withAttribute('language', $site->getLanguageById($languageId));
230  $subject = new SiteBaseRedirectResolver();
231  $response = $subject->process($request, $this->siteFoundRequestHandler);
232  self::assertEquals($expectedStatusCode, $response->getStatusCode());
233  }
234 
238  public function ‪doNotRedirectOnBaseWithoutQueryDataProvider(): array
239  {
240  $site1 = new Site('outside-site', 13, [
241  'base' => 'https://twenty.one/',
242  'languages' => [
243  0 => [
244  'languageId' => 0,
245  'locale' => 'en_US.UTF-8',
246  'base' => '/en/',
247  ],
248  1 => [
249  'languageId' => 1,
250  'locale' => 'fr_CA.UTF-8',
251  'base' => '/fr',
252  ],
253  ],
254  ]);
255  return [
256  'no redirect for base' => [
257  'https://twenty.one/en/',
258  $site1,
259  $site1->getLanguageById(0),
260  '',
261  ],
262  'no redirect for base when ID is given' => [
263  'https://twenty.one/index.php?id=2',
264  $site1,
265  $site1->getLanguageById(0),
266  '',
267  ],
268  'no redirect for base and nested arguments' => [
269  'https://twenty.one/en/?foo[bar]=foobar&bar=foo',
270  $site1,
271  $site1->getLanguageById(0),
272  '',
273  ],
274  ];
275  }
276 
285  public function ‪doNotRedirectOnBaseWithoutQuery(
286  string $incomingUrl,
287  Site $site,
288  ?SiteLanguage $language,
289  string $tail
290  ): void {
291  $routeResult = new SiteRouteResult(new Uri($incomingUrl), $site, $language, $tail);
292  $request = new ServerRequest($incomingUrl, 'GET');
293  $request = $request->withAttribute('site', $site);
294  $request = $request->withAttribute('language', $language);
295  $request = $request->withAttribute('routing', $routeResult);
296 
297  $subject = new SiteBaseRedirectResolver();
298  $response = $subject->process($request, $this->siteFoundRequestHandler);
299  self::assertEquals(200, $response->getStatusCode());
300  }
301 
305  public function ‪useDefaultLanguageIfNoLanguageIsGiven(): void
306  {
307  $incomingUrl = 'https://twenty.one/';
308  $site = new Site('random-site', 13, [
309  'base' => 'https://twenty.one/',
310  'languages' => [
311  0 => [
312  'languageId' => 0,
313  'locale' => 'en_US.UTF-8',
314  'base' => '/en/',
315  ],
316  1 => [
317  'languageId' => 1,
318  'locale' => 'fr_FR.UTF-8',
319  'base' => '/fr',
320  ],
321  2 => [
322  'languageId' => 2,
323  'locale' => 'fr_CA.UTF-8',
324  'base' => '/fr_ca',
325  ],
326  ],
327  ]);
328 
329  $routeResult = new SiteRouteResult(new Uri($incomingUrl), $site);
330  $request = new ServerRequest($incomingUrl, 'GET');
331  $request = $request->withAttribute('site', $site);
332  $request = $request->withAttribute('routing', $routeResult);
333 
334  $subject = new SiteBaseRedirectResolver();
335  $response = $subject->process($request, $this->siteFoundRequestHandler);
336  self::assertEquals('https://twenty.one/en/', $response->getHeader('Location')[0]);
337  }
338 
343  {
344  $incomingUrl = 'https://twenty.one/';
345  $site = new Site('random-site', 13, [
346  'base' => 'https://twenty.one/',
347  'languages' => [
348  0 => [
349  'languageId' => 0,
350  'enabled' => false,
351  'locale' => 'en_US.UTF-8',
352  'base' => '/en/',
353  ],
354  1 => [
355  'languageId' => 1,
356  'enabled' => false,
357  'locale' => 'fr_FR.UTF-8',
358  'base' => '/fr',
359  ],
360  2 => [
361  'languageId' => 2,
362  'locale' => 'fr_CA.UTF-8',
363  'base' => '/fr_ca',
364  ],
365  ],
366  ]);
367 
368  $routeResult = new SiteRouteResult(new Uri($incomingUrl), $site);
369  $request = new ServerRequest($incomingUrl, 'GET');
370  $request = $request->withAttribute('site', $site);
371  $request = $request->withAttribute('routing', $routeResult);
372 
373  $subject = new SiteBaseRedirectResolver();
374  $response = $subject->process($request, $this->siteFoundRequestHandler);
375  self::assertEquals('https://twenty.one/fr_ca', $response->getHeader('Location')[0]);
376  }
377 }
‪TYPO3\CMS\Frontend\Middleware\SiteBaseRedirectResolver
Definition: SiteBaseRedirectResolver.php:42
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\checkIf404IsSiteLanguageIsDisabledInFrontend
‪checkIf404IsSiteLanguageIsDisabledInFrontend(string $url, int $expectedStatusCode, int $languageId)
Definition: SiteBaseRedirectResolverTest.php:195
‪TYPO3\CMS\Core\Tests\Functional\Fixtures\Frontend\PhpError
Definition: PhpError.php:29
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest
Definition: SiteBaseRedirectResolverTest.php:35
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\$siteFoundRequestHandler
‪RequestHandlerInterface $siteFoundRequestHandler
Definition: SiteBaseRedirectResolverTest.php:40
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\checkIf404IsSiteLanguageIsDisabledInFrontendDataProvider
‪array checkIf404IsSiteLanguageIsDisabledInFrontendDataProvider()
Definition: SiteBaseRedirectResolverTest.php:179
‪TYPO3\CMS\Core\Http\NullResponse
Definition: NullResponse.php:26
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\setUp
‪setUp()
Definition: SiteBaseRedirectResolverTest.php:45
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\$resetSingletonInstances
‪bool $resetSingletonInstances
Definition: SiteBaseRedirectResolverTest.php:38
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\useDefaultLanguageIfNoLanguageIsGiven
‪useDefaultLanguageIfNoLanguageIsGiven()
Definition: SiteBaseRedirectResolverTest.php:304
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:29
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:42
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\doNotRedirectOnBaseWithoutQueryDataProvider
‪array doNotRedirectOnBaseWithoutQueryDataProvider()
Definition: SiteBaseRedirectResolverTest.php:237
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:26
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\doRedirectOnMissingOrSuperfluousRequestUrl
‪doRedirectOnMissingOrSuperfluousRequestUrl(string $incomingUrl, string $expectedRedirectUrl, Site $site, ?SiteLanguage $language, string $tail)
Definition: SiteBaseRedirectResolverTest.php:157
‪TYPO3\CMS\Core\Routing\SiteRouteResult
Definition: SiteRouteResult.php:30
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware
Definition: PageArgumentValidatorTest.php:18
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\useFirstAvailableLanguageIfDefaultLanguageIsNotEnabledAndLanguageIsGiven
‪useFirstAvailableLanguageIfDefaultLanguageIsNotEnabledAndLanguageIsGiven()
Definition: SiteBaseRedirectResolverTest.php:341
‪TYPO3\CMS\Core\Http\ServerRequest
Definition: ServerRequest.php:37
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\doNotRedirectOnBaseWithoutQuery
‪doNotRedirectOnBaseWithoutQuery(string $incomingUrl, Site $site, ?SiteLanguage $language, string $tail)
Definition: SiteBaseRedirectResolverTest.php:284
‪TYPO3\CMS\Core\Http\JsonResponse
Definition: JsonResponse.php:28
‪TYPO3\CMS\Frontend\Tests\Unit\Middleware\SiteBaseRedirectResolverTest\doRedirectOnMissingOrSuperfluousRequestUrlDataProvider
‪array doRedirectOnMissingOrSuperfluousRequestUrlDataProvider()
Definition: SiteBaseRedirectResolverTest.php:74