‪TYPO3CMS  ‪main
RedirectServiceTest.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 PHPUnit\Framework\MockObject\MockObject;
21 use Psr\Log\NullLogger;
29 use TYPO3\CMS\Core\LinkHandling\TypoLinkCodecService;
44 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
45 
46 final class ‪RedirectServiceTest extends UnitTestCase
47 {
48  protected bool ‪$resetSingletonInstances = true;
49 
51  protected MockObject&‪LinkService ‪$linkServiceMock;
52 
54 
55  protected MockObject&‪SiteFinder ‪$siteFinder;
57 
58  protected function ‪setUp(): void
59  {
60  parent::setUp();
61  $logger = new NullLogger();
62  $this->redirectCacheServiceMock = $this->getMockBuilder(RedirectCacheService::class)->disableOriginalConstructor()->getMock();
63  $this->linkServiceMock = $this->getMockBuilder(LinkService::class)->disableOriginalConstructor()->getMock();
64  $this->siteFinder = $this->getMockBuilder(SiteFinder::class)->disableOriginalConstructor()->getMock();
65  $this->redirectRepository = $this->getMockBuilder(RedirectRepository::class)->disableOriginalConstructor()->getMock();
66 
67  $this->redirectService = new ‪RedirectService(
68  $this->redirectCacheServiceMock,
69  $this->linkServiceMock,
70  $this->siteFinder,
73  new ‪Context(),
75  $this->createMock(Logger::class),
77  new ‪ErrorController(),
78  new ‪SysTemplateRepository(new ‪NoopEventDispatcher(), $this->createMock(ConnectionPool::class), new ‪Context()),
79  )
80  );
81  $this->redirectService->setLogger($logger);
82 
83  ‪$GLOBALS['SIM_ACCESS_TIME'] = 42;
84  }
85 
90  {
91  $this->redirectCacheServiceMock->method('getRedirects')->willReturnMap([
92  ['example.com', []],
93  ['*', []],
94  ]);
95 
96  $result = $this->redirectService->matchRedirect('example.com', 'foo');
97 
98  self::assertNull($result);
99  }
100 
105  public function ‪matchRedirectReturnsRedirectOnFlatMatch(string $path = ''): void
106  {
107  $row = [
108  'target' => 'https://example.com',
109  'force_https' => '0',
110  'keep_query_parameters' => '0',
111  'target_statuscode' => '307',
112  'disabled' => '0',
113  'starttime' => '0',
114  'endtime' => '0',
115  ];
116  $this->redirectCacheServiceMock->method('getRedirects')->willReturnMap([
117  [
118  'example.com',
119  [
120  'flat' => [
121  $path . '/' => [
122  1 => $row,
123  ],
124  ],
125  ],
126  ],
127  [
128  '*',
129  [],
130  ],
131  ]);
132 
133  $result = $this->redirectService->matchRedirect('example.com', rawurlencode($path));
134 
135  self::assertSame($row, $result);
136  }
137 
139  {
140  return [
141  'default case' => [
142  'foo',
143  ],
144  'umlauts' => [
145  'äöü',
146  ],
147  'various special chars' => [
148  'special-chars-«-∑-€-®-†-Ω-¨-ø-π-å-‚-∂-ƒ-©-ª-º-∆-@-¥-≈-ç-√-∫-~-µ-∞-…-–',
149  ],
150  'chinese' => [
151  '应用',
152  ],
153  'hindi' => [
154  'कंपनी',
155  ],
156  'cyrilic' => [
157  'cyrilic-АВГДЄЅЗИѲІКЛМНѮѺПЧ',
158  ],
159  ];
160  }
161 
166  {
167  $row = [
168  'target' => 'https://example.com',
169  'force_https' => '0',
170  'keep_query_parameters' => '0',
171  'respect_query_parameters' => '1',
172  'target_statuscode' => '307',
173  'disabled' => '0',
174  'starttime' => '0',
175  'endtime' => '0',
176  ];
177  $this->redirectCacheServiceMock->method('getRedirects')->willReturnMap([
178  [
179  'example.com',
180  [
181  'respect_query_parameters' => [
182  'index.php?id=123' => [
183  1 => $row,
184  ],
185  ],
186  ],
187  ],
188  [
189  '*',
190  [],
191  ],
192  ]);
193 
194  $result = $this->redirectService->matchRedirect('example.com', 'index.php', 'id=123');
195 
196  self::assertSame($row, $result);
197  }
198 
203  {
204  $row = [
205  'target' => 'https://example.com',
206  'force_https' => '0',
207  'keep_query_parameters' => '0',
208  'respect_query_parameters' => '1',
209  'target_statuscode' => '307',
210  'disabled' => '0',
211  'starttime' => '0',
212  'endtime' => '0',
213  ];
214  $this->redirectCacheServiceMock->method('getRedirects')->willReturnMap([
215  [
216  'example.com',
217  [
218  'respect_query_parameters' => [
219  'index.php/?id=123' => [
220  1 => $row,
221  ],
222  ],
223  ],
224  ],
225  [
226  '*',
227  [],
228  ],
229  ]);
230 
231  $result = $this->redirectService->matchRedirect('example.com', 'index.php', 'id=123');
232 
233  self::assertSame($row, $result);
234  }
235 
240  {
241  $row = [
242  'target' => 'https://example.com/target',
243  'force_https' => '0',
244  'keep_query_parameters' => '0',
245  'respect_query_parameters' => '1',
246  'target_statuscode' => '307',
247  'disabled' => '0',
248  'starttime' => '0',
249  'endtime' => '0',
250  ];
251  $this->redirectCacheServiceMock->method('getRedirects')->willReturnMap([
252  [
253  'example.com',
254  [
255  'respect_query_parameters' => [
256  'index.php?id=123&a=b' => [
257  1 => $row,
258  ],
259  ],
260  ],
261  ],
262  [
263  '*',
264  [],
265  ],
266  ]);
267 
268  $result = $this->redirectService->matchRedirect('example.com', 'index.php', 'id=123&a=b');
269 
270  self::assertSame($row, $result);
271  }
272 
277  {
278  $row = [
279  'target' => 'https://example.com/target',
280  'force_https' => '0',
281  'keep_query_parameters' => '0',
282  'respect_query_parameters' => '1',
283  'target_statuscode' => '307',
284  'disabled' => '0',
285  'starttime' => '0',
286  'endtime' => '0',
287  ];
288  $this->redirectCacheServiceMock->method('getRedirects')->willReturnMap([
289  [
290  'example.com',
291  [
292  'respect_query_parameters' => [
293  'index.php?id=123&a=b' => [
294  1 => $row,
295  ],
296  ],
297  ],
298  ],
299  [
300  '*',
301  [],
302  ],
303  ]);
304 
305  $result = $this->redirectService->matchRedirect('example.com', 'index.php', 'id=123&a=a');
306 
307  self::assertNull($result);
308  }
309 
314  {
315  $row1 = [
316  'target' => 'https://example.com/no-promotion',
317  'force_https' => '0',
318  'keep_query_parameters' => '0',
319  'respect_query_parameters' => '0',
320  'target_statuscode' => '307',
321  'disabled' => '0',
322  'starttime' => '0',
323  'endtime' => '0',
324  ];
325  $row2 = [
326  'target' => 'https://example.com/promotion',
327  'force_https' => '0',
328  'keep_query_parameters' => '0',
329  'respect_query_parameters' => '1',
330  'target_statuscode' => '307',
331  'disabled' => '0',
332  'starttime' => '0',
333  'endtime' => '0',
334  ];
335  $this->redirectCacheServiceMock->method('getRedirects')->willReturnMap([
336  [
337  'example.com',
338  [
339  'flat' => [
340  'special/page/' =>
341  [
342  1 => $row1,
343  ],
344  ],
345  'respect_query_parameters' => [
346  'special/page?key=998877' => [
347  1 => $row2,
348  ],
349  ],
350  ],
351  ],
352  [
353  '*',
354  [],
355  ],
356  ]);
357 
358  $result = $this->redirectService->matchRedirect('example.com', 'special/page', 'key=998877');
359 
360  self::assertSame($row2, $result);
361  }
362 
367  {
368  $row1 = [
369  'target' => 'https://example.com',
370  'force_https' => '0',
371  'keep_query_parameters' => '0',
372  'target_statuscode' => '307',
373  'disabled' => '0',
374  'starttime' => '0',
375  'endtime' => '0',
376  ];
377  $row2 = [
378  'target' => 'https://example.net',
379  'force_https' => '0',
380  'keep_query_parameters' => '0',
381  'target_statuscode' => '307',
382  'disabled' => '0',
383  'starttime' => '0',
384  'endtime' => '0',
385  ];
386 
387  $this->redirectCacheServiceMock->method('getRedirects')->willReturnMap([
388  [
389  'example.com',
390  [
391  'flat' => [
392  'foo/' => [
393  1 => $row1,
394  ],
395  ],
396  ],
397  ],
398  [
399  '*',
400  [
401  'flat' => [
402  'foo/' => [
403  2 => $row2,
404  ],
405  ],
406  ],
407  ],
408  ]);
409 
410  $result = $this->redirectService->matchRedirect('example.com', 'foo');
411 
412  self::assertSame($row1, $result);
413  }
414 
419  {
420  $row = [
421  'target' => 'https://example.com',
422  'force_https' => '0',
423  'respect_query_parameters' => '0',
424  'keep_query_parameters' => '0',
425  'target_statuscode' => '307',
426  'disabled' => '0',
427  'starttime' => '0',
428  'endtime' => '0',
429  ];
430  $this->redirectCacheServiceMock->method('getRedirects')->willReturnMap([
431  [
432  'example.com',
433  [
434  'regexp_flat' => [
435  '/f.*?/' => [
436  1 => $row,
437  ],
438  ],
439  ],
440  ],
441  [
442  '*',
443  [],
444  ],
445  ]);
446 
447  $result = $this->redirectService->matchRedirect('example.com', 'foo');
448 
449  self::assertSame($row, $result);
450  }
451 
456  {
457  $row1 = [
458  'target' => 'https://example.com',
459  'force_https' => '0',
460  'keep_query_parameters' => '0',
461  'target_statuscode' => '307',
462  'starttime' => '0',
463  'endtime' => '0',
464  'disabled' => '1',
465  ];
466  $row2 = [
467  'target' => 'https://example.net',
468  'force_https' => '0',
469  'keep_query_parameters' => '0',
470  'target_statuscode' => '307',
471  'starttime' => '0',
472  'endtime' => '0',
473  'disabled' => '0',
474  ];
475  $this->redirectCacheServiceMock->method('getRedirects')->willReturnMap([
476  [
477  'example.com',
478  [
479  'flat' => [
480  'foo/' => [
481  1 => $row1,
482  2 => $row2,
483  ],
484  ],
485  ],
486  ],
487  [
488  '*',
489  [],
490  ],
491  ]);
492 
493  $result = $this->redirectService->matchRedirect('example.com', 'foo');
494 
495  self::assertSame($row2, $result);
496  }
497 
502  {
503  $this->linkServiceMock->method('resolve')->with(self::anything())->willThrowException(new ‪InvalidPathException('', 1516531195));
504  GeneralUtility::addInstance(TypoLinkCodecService::class, new TypoLinkCodecService(new ‪NoopEventDispatcher()));
505 
506  $result = $this->redirectService->getTargetUrl(['target' => 'invalid'], new ‪ServerRequest(new ‪Uri()));
507 
508  self::assertNull($result);
509  }
510 
514  public function ‪getTargetUrlReturnsUrlForTypeUrl(): void
515  {
516  $redirectTargetMatch = [
517  'target' => 'https://example.com',
518  'force_https' => '0',
519  'keep_query_parameters' => '0',
520  ];
521  $linkDetails = [
522  'type' => ‪LinkService::TYPE_URL,
523  'url' => 'https://example.com/',
524  ];
525  $this->linkServiceMock->method('resolve')->with($redirectTargetMatch['target'])->willReturn($linkDetails);
526  GeneralUtility::addInstance(TypoLinkCodecService::class, new TypoLinkCodecService(new ‪NoopEventDispatcher()));
527 
528  $source = new ‪Uri('https://example.com');
529  $request = new ‪ServerRequest($source);
530  $request = $request->withAttribute('site', new ‪Site('dummy', 13, []));
531  $result = $this->redirectService->getTargetUrl($redirectTargetMatch, $request);
532 
533  $uri = new ‪Uri('https://example.com/');
534  self::assertEquals($uri, $result);
535  }
536 
540  public function ‪getTargetUrlReturnsUrlForTypeFile(): void
541  {
542  $fileMock = $this->getMockBuilder(File::class)->disableOriginalConstructor()->getMock();
543  $fileMock->method('getPublicUrl')->willReturn('https://example.com/file.txt');
544  $redirectTargetMatch = [
545  'target' => 'https://example.com',
546  'force_https' => '0',
547  'keep_query_parameters' => '0',
548  ];
549  $linkDetails = [
550  'type' => ‪LinkService::TYPE_FILE,
551  'file' => $fileMock,
552  ];
553  $this->linkServiceMock->method('resolve')->with($redirectTargetMatch['target'])->willReturn($linkDetails);
554  GeneralUtility::addInstance(TypoLinkCodecService::class, new TypoLinkCodecService(new ‪NoopEventDispatcher()));
555 
556  $source = new ‪Uri('https://example.com');
557  $request = new ‪ServerRequest($source);
558  $request = $request->withAttribute('site', new ‪Site('dummy', 13, []));
559  $result = $this->redirectService->getTargetUrl($redirectTargetMatch, $request);
560 
561  $uri = new ‪Uri('https://example.com/file.txt');
562  self::assertEquals($uri, $result);
563  }
564 
569  {
570  $folderMock = $this->getMockBuilder(Folder::class)->disableOriginalConstructor()->getMock();
571  $folderMock->method('getPublicUrl')->willReturn('https://example.com/folder/');
572  $redirectTargetMatch = [
573  'target' => 'https://example.com',
574  'force_https' => '0',
575  'keep_query_parameters' => '0',
576  ];
577  $folder = $folderMock;
578  $linkDetails = [
579  'type' => ‪LinkService::TYPE_FOLDER,
580  'folder' => $folder,
581  ];
582  $this->linkServiceMock->method('resolve')->with($redirectTargetMatch['target'])->willReturn($linkDetails);
583  GeneralUtility::addInstance(TypoLinkCodecService::class, new TypoLinkCodecService(new ‪NoopEventDispatcher()));
584 
585  $source = new ‪Uri('https://example.com/');
586  $request = new ‪ServerRequest($source);
587  $request = $request->withAttribute('site', new ‪Site('dummy', 13, []));
588  $result = $this->redirectService->getTargetUrl($redirectTargetMatch, $request);
589 
590  $uri = new ‪Uri('https://example.com/folder/');
591  self::assertEquals($uri, $result);
592  }
593 
597  public function ‪getTargetUrlRespectsForceHttps(): void
598  {
599  $redirectTargetMatch = [
600  'target' => 'https://example.com',
601  'keep_query_parameters' => '0',
602  'force_https' => '1',
603  ];
604  $linkDetails = [
605  'type' => ‪LinkService::TYPE_URL,
606  'url' => 'http://example.com',
607  ];
608  $this->linkServiceMock->method('resolve')->with($redirectTargetMatch['target'])->willReturn($linkDetails);
609  GeneralUtility::addInstance(TypoLinkCodecService::class, new TypoLinkCodecService(new ‪NoopEventDispatcher()));
610 
611  $source = new ‪Uri('https://example.com');
612  $request = new ‪ServerRequest($source);
613  $request = $request->withAttribute('site', new ‪Site('dummy', 13, []));
614  $result = $this->redirectService->getTargetUrl($redirectTargetMatch, $request);
615 
616  $uri = new ‪Uri('https://example.com');
617  self::assertEquals($uri, $result);
618  }
619 
624  {
625  $redirectTargetMatch = [
626  'target' => 'https://example.com',
627  'force_https' => '0',
628  'keep_query_parameters' => '1',
629  ];
630  $linkDetails = [
631  'type' => ‪LinkService::TYPE_URL,
632  'url' => 'https://example.com/?foo=1&bar=2',
633  ];
634  $this->linkServiceMock->method('resolve')->with($redirectTargetMatch['target'])->willReturn($linkDetails);
635  GeneralUtility::addInstance(TypoLinkCodecService::class, new TypoLinkCodecService(new ‪NoopEventDispatcher()));
636 
637  $source = new ‪Uri('https://example.com/?bar=2&baz=4&foo=1');
638  $request = new ‪ServerRequest($source);
639  $request = $request->withQueryParams(['bar' => 3, 'baz' => 4]);
640  $request = $request->withAttribute('site', new ‪Site('dummy', 13, []));
641  $result = $this->redirectService->getTargetUrl($redirectTargetMatch, $request);
642 
643  $uri = new ‪Uri('https://example.com/?bar=2&baz=4&foo=1');
644  self::assertEquals($uri, $result);
645  }
646 
651  {
652  ‪$redirectService = $this->getAccessibleMock(
653  RedirectService::class,
654  ['getUriFromCustomLinkDetails'],
655  [
656  $this->redirectCacheServiceMock,
657  $this->linkServiceMock,
658  $this->siteFinder,
661  new ‪Context(),
663  $this->createMock(Logger::class),
665  new ‪ErrorController(),
666  new ‪SysTemplateRepository(new ‪NoopEventDispatcher(), $this->createMock(ConnectionPool::class), new ‪Context()),
667  ),
668  ],
669  '',
670  );
671 
672  $logger = new NullLogger();
673  ‪$redirectService->setLogger($logger);
674 
675  $pageRecord = 't3://page?uid=13';
676  $redirectTargetMatch = [
677  'target' => $pageRecord . ' - - - foo=bar',
678  'force_https' => 1,
679  'keep_query_parameters' => 1,
680  ];
681 
682  $linkDetails = [
683  'pageuid' => 13,
684  'type' => ‪LinkService::TYPE_PAGE,
685  'typoLinkParameter' => $pageRecord,
686  ];
687  $this->linkServiceMock->method('resolve')->with($pageRecord)->willReturn($linkDetails);
688  GeneralUtility::addInstance(TypoLinkCodecService::class, new TypoLinkCodecService(new ‪NoopEventDispatcher()));
689 
690  $queryParams = [];
691  $queryParams['foo'] = 'bar';
692  $uri = new ‪Uri('/page?foo=bar');
693 
694  $frontendUserAuthentication = new ‪FrontendUserAuthentication();
695  $site = new ‪Site('dummy', 13, []);
696  $request = new ‪ServerRequest($uri);
697  $request = $request->withQueryParams($queryParams);
698  $request = $request->withAttribute('site', $site);
699  $request = $request->withAttribute('frontend.user', $frontendUserAuthentication);
700  ‪$redirectService->method('getUriFromCustomLinkDetails')
701  ->with($redirectTargetMatch, $site, $linkDetails, $queryParams, $request)
702  ->willReturn($uri);
703  $result = ‪$redirectService->‪getTargetUrl($redirectTargetMatch, $request);
704 
705  self::assertEquals($uri, $result);
706  }
707 
712  {
713  $redirectTargetMatch = [
714  'source_path' => '#^/foo/(.*)#',
715  'target' => 'https://anotherdomain.com/$1',
716  'force_https' => '0',
717  'keep_query_parameters' => '1',
718  'is_regexp' => 1,
719  ];
720  $linkDetails = [
721  'type' => ‪LinkService::TYPE_URL,
722  'url' => 'https://anotherdomain.com/$1',
723  ];
724  $this->linkServiceMock->method('resolve')->with($redirectTargetMatch['target'])->willReturn($linkDetails);
725  GeneralUtility::addInstance(TypoLinkCodecService::class, new TypoLinkCodecService(new ‪NoopEventDispatcher()));
726 
727  $source = new ‪Uri('https://example.com/foo/bar');
728  $request = new ‪ServerRequest($source);
729  $request = $request->withAttribute('site', new ‪Site('dummy', 13, []));
730  $result = $this->redirectService->getTargetUrl($redirectTargetMatch, $request);
731 
732  $uri = new ‪Uri('https://anotherdomain.com/bar');
733  self::assertEquals($uri, $result);
734  }
735 
737  {
738  $cyrilicPlain = 'АВГДЄЅЗИѲІКЛМНѮѺПЧ';
739  return [
740  'index.php with query capture group - plain value' => [
741  '#^/index.php\?option=com_content&page=(.*)#',
742  'https://anotherdomain.com/$1',
743  'https://example.com/index.php?option=com_content&page=target',
744  'https://anotherdomain.com/target',
745  ],
746  'index.php with query capture group - cyrilic value' => [
747  '#^/index.php\?option=com_content&page=(.*)#',
748  'https://anotherdomain.com/$1',
749  sprintf('https://example.com/index.php?option=com_content&page=%s', $cyrilicPlain),
750  sprintf('https://anotherdomain.com/%s', $cyrilicPlain),
751  ],
752  'capture group in path and query capture group - cyrilic value' => [
753  '#^/index-(.*).php\?option=com_content&page=(.*)#',
754  'https://anotherdomain.com/$1/$2',
755  sprintf('https://example.com/index-%s.php?option=com_content&page=cyrilic-%s', $cyrilicPlain, $cyrilicPlain),
756  sprintf('https://anotherdomain.com/%s/cyrilic-%s', $cyrilicPlain, $cyrilicPlain),
757  ],
758  'cyrilic path with non-cyrilic capture group' => [
759  sprintf('#^/index-%s.php\?option=com_content&page=(.*)#', $cyrilicPlain),
760  'https://anotherdomain.com/$1',
761  sprintf('https://example.com/index-%s.php?option=com_content&page=cyrilic-%s', $cyrilicPlain, $cyrilicPlain),
762  sprintf('https://anotherdomain.com/cyrilic-%s', $cyrilicPlain),
763  ],
764  'cyrilic path with cyrilic capture group' => [
765  sprintf('#^/index-%s.php\?option=com_content&page=(.*)#', $cyrilicPlain),
766  'https://anotherdomain.com/$1',
767  sprintf('https://example.com/index-%s.php?option=com_content&page=cyrilic-%s', $cyrilicPlain, $cyrilicPlain),
768  sprintf('https://anotherdomain.com/cyrilic-%s', $cyrilicPlain),
769  ],
770  'cyrilic path with cyrilic capture group with cyrilic prefix' => [
771  sprintf('#^/index-%s.php\?option=com_content&page=%s(.*)#', $cyrilicPlain, $cyrilicPlain),
772  'https://anotherdomain.com/$1',
773  sprintf('https://example.com/index-%s.php?option=com_content&page=%scyrilic-%s', $cyrilicPlain, $cyrilicPlain, $cyrilicPlain),
774  sprintf('https://anotherdomain.com/cyrilic-%s', $cyrilicPlain),
775  ],
776  ];
777  }
778 
784  string $redirectSourcePath,
785  string $redirectTarget,
786  string $requestUri,
787  string $expectedRedirectUri
788  ) {
789  $redirectTargetMatch = [
790  'uid' => 1,
791  'source_path' => $redirectSourcePath,
792  'target' => $redirectTarget,
793  'force_https' => '0',
794  'keep_query_parameters' => 0,
795  'is_regexp' => 1,
796  'respect_query_parameters' => 1,
797  ];
798  $linkDetails = [
799  'type' => ‪LinkService::TYPE_URL,
800  'url' => $redirectTarget,
801  'query' => '',
802  ];
803  $this->linkServiceMock->method('resolve')->with($redirectTargetMatch['target'])->willReturn($linkDetails);
804  GeneralUtility::addInstance(TypoLinkCodecService::class, new TypoLinkCodecService(new ‪NoopEventDispatcher()));
805 
806  $source = new ‪Uri($requestUri);
807  $queryParams = [];
808  parse_str($source->getQuery(), $queryParams);
809  $request = new ‪ServerRequest($source);
810  $request = $request->withQueryParams($queryParams);
811  $request = $request->withAttribute('site', new ‪Site('dummy', 13, []));
812  $result = $this->redirectService->getTargetUrl($redirectTargetMatch, $request);
813 
814  $uri = new ‪Uri($expectedRedirectUri);
815  self::assertEquals($uri, $result);
816  }
817 
819  {
820  $cyrilicPlain = 'АВГДЄЅЗИѲІКЛМНѮѺПЧ';
821  return [
822  'index with path slash with query capture group - plain value' => [
823  '#^/index/\?option=com_content&page=(.*)#',
824  'https://anotherdomain.com/$1',
825  'https://example.com/index/?option=com_content&page=target',
826  'https://anotherdomain.com/target?option=com_content&page=target',
827  ],
828  'index with query capture group - cyrilic value' => [
829  '#^/index/\?option=com_content&page=(.*)#',
830  'https://anotherdomain.com/$1',
831  sprintf('https://example.com/index/?option=com_content&page=%s', $cyrilicPlain),
832  sprintf('https://anotherdomain.com/%s?option=com_content&page=%s', $cyrilicPlain, $cyrilicPlain),
833  ],
834  'capture group in path and query capture group - cyrilic value' => [
835  '#^/index-(.*)/\?option=com_content&page=(.*)#',
836  'https://anotherdomain.com/$1/$2',
837  sprintf('https://example.com/index-%s/?option=com_content&page=cyrilic-%s', $cyrilicPlain, $cyrilicPlain),
838  sprintf('https://anotherdomain.com/%s/cyrilic-%s?option=com_content&page=cyrilic-%s', $cyrilicPlain, $cyrilicPlain, $cyrilicPlain),
839  ],
840  'cyrilic path with non-cyrilic capture group' => [
841  sprintf('#^/index-%s/\?option=com_content&page=(.*)#', $cyrilicPlain),
842  'https://anotherdomain.com/$1',
843  sprintf('https://example.com/index-%s/?option=com_content&page=cyrilic', $cyrilicPlain),
844  'https://anotherdomain.com/cyrilic?option=com_content&page=cyrilic',
845  ],
846  'cyrilic path with cyrilic capture group' => [
847  sprintf('#^/index-%s/\?option=com_content&page=(.*)#', $cyrilicPlain),
848  'https://anotherdomain.com/$1',
849  sprintf('https://example.com/index-%s/?option=com_content&page=cyrilic-%s', $cyrilicPlain, $cyrilicPlain),
850  sprintf('https://anotherdomain.com/cyrilic-%s?option=com_content&page=cyrilic-%s', $cyrilicPlain, $cyrilicPlain),
851  ],
852  'cyrilic path with cyrilic capture group with cyrilic prefix' => [
853  sprintf('#^/index-%s/\?option=com_content&page=%s(.*)#', $cyrilicPlain, $cyrilicPlain),
854  'https://anotherdomain.com/$1',
855  sprintf('https://example.com/index-%s/?option=com_content&page=%scyrilic-%s', $cyrilicPlain, $cyrilicPlain, $cyrilicPlain),
856  sprintf('https://anotherdomain.com/cyrilic-%s?option=com_content&page=%scyrilic-%s', $cyrilicPlain, $cyrilicPlain, $cyrilicPlain),
857  ],
858  ];
859  }
860 
866  string $redirectSourcePath,
867  string $redirectTarget,
868  string $requestUri,
869  string $expectedRedirectUri
870  ) {
871  $redirectTargetMatch = [
872  'uid' => 1,
873  'source_path' => $redirectSourcePath,
874  'target' => $redirectTarget,
875  'force_https' => '0',
876  'keep_query_parameters' => '1',
877  'is_regexp' => 1,
878  'respect_query_parameters' => 1,
879  ];
880  $linkDetails = [
881  'type' => ‪LinkService::TYPE_URL,
882  'url' => $redirectTarget,
883  ];
884  $this->linkServiceMock->method('resolve')->with($redirectTargetMatch['target'])->willReturn($linkDetails);
885  GeneralUtility::addInstance(TypoLinkCodecService::class, new TypoLinkCodecService(new ‪NoopEventDispatcher()));
886 
887  $source = new ‪Uri($requestUri);
888  $queryParams = [];
889  parse_str($source->getQuery(), $queryParams);
890  $request = new ‪ServerRequest($source);
891  $request = $request->withQueryParams($queryParams);
892  $request = $request->withAttribute('site', new ‪Site('dummy', 13, []));
893  $result = $this->redirectService->getTargetUrl($redirectTargetMatch, $request);
894 
895  $uri = new ‪Uri($expectedRedirectUri);
896  self::assertEquals($uri, $result);
897  }
898 }
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlReplaceRegExpCaptureGroup
‪getTargetUrlReplaceRegExpCaptureGroup()
Definition: RedirectServiceTest.php:711
‪TYPO3\CMS\Core\TypoScript\IncludeTree\SysTemplateRepository
Definition: SysTemplateRepository.php:39
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlWithQueryReplaceRegExpCaptureGroup
‪getTargetUrlWithQueryReplaceRegExpCaptureGroup(string $redirectSourcePath, string $redirectTarget, string $requestUri, string $expectedRedirectUri)
Definition: RedirectServiceTest.php:783
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\$redirectCacheServiceMock
‪MockObject &RedirectCacheService $redirectCacheServiceMock
Definition: RedirectServiceTest.php:50
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlWithQueryAndSlashReplaceRegExpCaptureGroup
‪getTargetUrlWithQueryAndSlashReplaceRegExpCaptureGroup(string $redirectSourcePath, string $redirectTarget, string $requestUri, string $expectedRedirectUri)
Definition: RedirectServiceTest.php:865
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlWithQueryAndSlashReplaceRegExpCaptureGroupDataProvider
‪static getTargetUrlWithQueryAndSlashReplaceRegExpCaptureGroupDataProvider()
Definition: RedirectServiceTest.php:818
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest
Definition: RedirectServiceTest.php:47
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\$linkServiceMock
‪MockObject &LinkService $linkServiceMock
Definition: RedirectServiceTest.php:51
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsNullIfNoRedirectsExist
‪matchRedirectReturnsNullIfNoRedirectsExist()
Definition: RedirectServiceTest.php:89
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlReturnsUrlForTypeUrl
‪getTargetUrlReturnsUrlForTypeUrl()
Definition: RedirectServiceTest.php:514
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsRedirectSpecificToDomainOnFlatMatchIfSpecificAndNonSpecificExist
‪matchRedirectReturnsRedirectSpecificToDomainOnFlatMatchIfSpecificAndNonSpecificExist()
Definition: RedirectServiceTest.php:366
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlRespectsAdditionalParametersFromTypolink
‪getTargetUrlRespectsAdditionalParametersFromTypolink()
Definition: RedirectServiceTest.php:650
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsRedirectOnRespectQueryParametersMatchWithSlash
‪matchRedirectReturnsRedirectOnRespectQueryParametersMatchWithSlash()
Definition: RedirectServiceTest.php:202
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\$redirectRepository
‪MockObject &RedirectRepository $redirectRepository
Definition: RedirectServiceTest.php:56
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsOnlyActiveRedirects
‪matchRedirectReturnsOnlyActiveRedirects()
Definition: RedirectServiceTest.php:455
‪TYPO3\CMS\Redirects\Service\RedirectService
Definition: RedirectService.php:53
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsRedirectOnRespectQueryParametersMatch
‪matchRedirectReturnsRedirectOnRespectQueryParametersMatch()
Definition: RedirectServiceTest.php:165
‪TYPO3\CMS\Frontend\Controller\ErrorController
Definition: ErrorController.php:38
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Redirects\Tests\Unit\Service
Definition: RedirectServiceTest.php:18
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsRedirectOnFlatMatch
‪matchRedirectReturnsRedirectOnFlatMatch(string $path='')
Definition: RedirectServiceTest.php:105
‪TYPO3\CMS\Redirects\Service\RedirectService\getTargetUrl
‪getTargetUrl(array $matchedRedirect, ServerRequestInterface $request)
Definition: RedirectService.php:255
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlReturnsNullIfUrlCouldNotBeResolved
‪getTargetUrlReturnsNullIfUrlCouldNotBeResolved()
Definition: RedirectServiceTest.php:501
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:30
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:42
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\setUp
‪setUp()
Definition: RedirectServiceTest.php:58
‪TYPO3\CMS\Redirects\Service\RedirectCacheService
Definition: RedirectCacheService.php:34
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsMatchingRedirectWithMatchingQueryParametersOverMatchingPath
‪matchRedirectReturnsMatchingRedirectWithMatchingQueryParametersOverMatchingPath()
Definition: RedirectServiceTest.php:313
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\$resetSingletonInstances
‪bool $resetSingletonInstances
Definition: RedirectServiceTest.php:48
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\$redirectService
‪RedirectService $redirectService
Definition: RedirectServiceTest.php:53
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:38
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:26
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlWithQueryReplaceRegExpCaptureGroupDataProvider
‪static getTargetUrlWithQueryReplaceRegExpCaptureGroupDataProvider()
Definition: RedirectServiceTest.php:736
‪TYPO3\CMS\Core\Http\ServerRequest
Definition: ServerRequest.php:39
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsRedirectOnFullRespectQueryParametersMatch
‪matchRedirectReturnsRedirectOnFullRespectQueryParametersMatch()
Definition: RedirectServiceTest.php:239
‪TYPO3\CMS\Redirects\Repository\RedirectRepository
Definition: RedirectRepository.php:31
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlReturnsUrlForTypeFile
‪getTargetUrlReturnsUrlForTypeFile()
Definition: RedirectServiceTest.php:540
‪TYPO3\CMS\Core\EventDispatcher\NoopEventDispatcher
Definition: NoopEventDispatcher.php:29
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlAddsExistingQueryParams
‪getTargetUrlAddsExistingQueryParams()
Definition: RedirectServiceTest.php:623
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsNullOnPartialRespectQueryParametersMatch
‪matchRedirectReturnsNullOnPartialRespectQueryParametersMatch()
Definition: RedirectServiceTest.php:276
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Log\Logger
Definition: Logger.php:28
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsRedirectOnRegexMatch
‪matchRedirectReturnsRedirectOnRegexMatch()
Definition: RedirectServiceTest.php:418
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlReturnsUrlForTypeFolder
‪getTargetUrlReturnsUrlForTypeFolder()
Definition: RedirectServiceTest.php:568
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication
Definition: FrontendUserAuthentication.php:33
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Resource\Exception\InvalidPathException
Definition: InvalidPathException.php:23
‪TYPO3\CMS\Core\Domain\Access\RecordAccessVoter
Definition: RecordAccessVoter.php:29
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\$siteFinder
‪MockObject &SiteFinder $siteFinder
Definition: RedirectServiceTest.php:55
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\matchRedirectReturnsRedirectOnFlatMatchDataProvider
‪static matchRedirectReturnsRedirectOnFlatMatchDataProvider()
Definition: RedirectServiceTest.php:138
‪TYPO3\CMS\Redirects\Tests\Unit\Service\RedirectServiceTest\getTargetUrlRespectsForceHttps
‪getTargetUrlRespectsForceHttps()
Definition: RedirectServiceTest.php:597
‪TYPO3\CMS\Frontend\Page\PageInformationFactory
Definition: PageInformationFactory.php:62