[BUGFIX] Make redirect sources with Query matchable
[Packages/TYPO3.CMS.git] / typo3 / sysext / redirects / Classes / Service / RedirectCacheService.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Redirects\Service;
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\Cache\CacheManager;
19 use TYPO3\CMS\Core\Database\ConnectionPool;
20 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
21 use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
22 use TYPO3\CMS\Core\Utility\GeneralUtility;
23
24 /**
25 * Ensure to clear the cache entry when a sys_redirect record is modified, also the main pool
26 * for getting all redirects.
27 *
28 * @internal
29 */
30 class RedirectCacheService
31 {
32 /**
33 * @var \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
34 */
35 protected $cache;
36
37 /**
38 * Constructor setting up the cache
39 * @param CacheManager|null $cacheManager
40 * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
41 */
42 public function __construct(CacheManager $cacheManager = null)
43 {
44 $cacheManager = $cacheManager ?? GeneralUtility::makeInstance(CacheManager::class);
45 $this->cache = $cacheManager->getCache('cache_pages');
46 }
47
48 /**
49 * Fetches all redirects available to the system, grouped by domain and regexp/nonregexp
50 *
51 * @return array
52 */
53 public function getRedirects(): array
54 {
55 $redirects = $this->cache->get('redirects');
56 if (!is_array($redirects)) {
57 $redirects = $this->rebuild();
58 }
59 return $redirects;
60 }
61
62 /**
63 * Rebuilds the cache for all redirects, grouped by host as well as by regular expressions and respect_query_parameters.
64 * Does not include deleted redirects, but includes the ones with dynamic starttime/endtime.
65 */
66 public function rebuild(): array
67 {
68 $redirects = [];
69 $this->flush();
70 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_redirect');
71 $queryBuilder->getRestrictions()->removeAll()
72 ->add(GeneralUtility::makeInstance(HiddenRestriction::class))
73 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
74 $statement = $queryBuilder
75 ->select('*')
76 ->from('sys_redirect')
77 ->execute();
78 while ($row = $statement->fetch()) {
79 $host = $row['source_host'] ?: '*';
80 if ($row['is_regexp']) {
81 $redirects[$host]['regexp'][$row['source_path']][$row['uid']] = $row;
82 } elseif ($row['respect_query_parameters']) {
83 $redirects[$host]['respect_query_parameters'][$row['source_path']][$row['uid']] = $row;
84 } else {
85 $redirects[$host]['flat'][rtrim($row['source_path'], '/') . '/'][$row['uid']] = $row;
86 }
87 }
88 $this->cache->set('redirects', $redirects, ['redirects']);
89 return $redirects;
90 }
91
92 /**
93 * Flushes all redirects from the cache
94 */
95 protected function flush()
96 {
97 $this->cache->flushByTag('redirects');
98 }
99 }