‪TYPO3CMS  10.4
IntegrityService.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 
26 
31 {
35  private ‪$redirectService;
36 
40  private ‪$siteFinder;
41 
43  {
44  $this->siteFinder = ‪$siteFinder ?? GeneralUtility::makeInstance(SiteFinder::class);
45  $this->redirectService = ‪$redirectService ?? GeneralUtility::makeInstance(
46  RedirectService::class,
47  GeneralUtility::makeInstance(RedirectCacheService::class),
48  GeneralUtility::makeInstance(LinkService::class),
49  $this->siteFinder
50  );
51  }
52 
59  public function ‪findConflictingRedirects(?string $siteIdentifier = null): \Generator
60  {
61  foreach ($this->‪getSites($siteIdentifier) as $site) {
62  // Collect page urls for all pages and languages for $site.
63  $urls = $this->‪getAllPageUrlsForSite($site);
64  foreach ($urls as $url) {
65  $uri = new ‪Uri($url);
66  $matchingRedirect = $this->‪getMatchingRedirectByUri($uri);
67  if ($matchingRedirect !== null) {
68  // @todo Returning information should be improved in future to give more useful information in
69  // command output and report output, for example redirect uid, page/language details, which would
70  // make the life easier for using the command and finding the conflicts.
71  yield [
72  'uri' => (string)$uri,
73  'redirect' => [
74  'source_host' => $matchingRedirect['source_host'],
75  'source_path' => $matchingRedirect['source_path'],
76  ],
77  ];
78  }
79  }
80  }
81  }
82 
83  private function ‪getMatchingRedirectByUri(‪Uri $uri): ?array
84  {
85  $port = $uri->‪getPort();
86  $domain = $uri->‪getHost() . ($port ? ':' . $port : '');
87  return $this->redirectService->matchRedirect($domain, $uri->‪getPath());
88  }
89 
94  private function ‪getSites(?string $siteIdentifier): array
95  {
96  if ($siteIdentifier !== null) {
97  return [$this->siteFinder->getSiteByIdentifier($siteIdentifier)];
98  }
99 
100  return $this->siteFinder->getAllSites();
101  }
102 
109  private function ‪getAllPageUrlsForSite(Site $site): array
110  {
111  $pageUrls = [];
112 
113  // language bases - redirects would be nasty, but should be checked also. We do not need to add site base
114  // here, as there is always at least one default language.
115  foreach ($site->getLanguages() as $siteLanguage) {
116  $pageUrls[] = rtrim((string)$siteLanguage->getBase(), '/') . '/';
117  }
118 
119  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
120  ->getQueryBuilderForTable('pages')
121  ->select('slug', $this->‪getPagesLanguageFieldName())
122  ->from('pages');
123 
124  $queryBuilder->where(
125  $queryBuilder->expr()->orX(
126  $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($site->getRootPageId(), \PDO::PARAM_INT)),
127  $queryBuilder->expr()->eq($this->getPagesLanguageParentFieldName(), $queryBuilder->createNamedParameter($site->getRootPageId(), \PDO::PARAM_INT))
128  )
129  );
130  $result = $queryBuilder->execute();
131 
132  while ($row = $result->fetch()) {
133  // @todo Considering only page slug is not complete, as it does not match redirects with file extension,
134  // for ex. if PageTypeSuffix routeEnhancer are used and redirects are created based on that.
135  $slug = ltrim(($row['slug'] ?? ''), '/');
136  $lang = (int)($row[$this->‪getPagesLanguageFieldName()] ?? 0);
137  $siteLanguage = $site->getLanguageById($lang);
138 
139  // empty slug root pages has been already handled with language bases above, thus skip them here.
140  if (empty($slug)) {
141  continue;
142  }
143 
144  $pageUrls[] = rtrim((string)$siteLanguage->getBase(), '/') . '/' . $slug;
145  }
146 
147  $subPageUrls = $this->‪getSlugsOfSubPages($site->getRootPageId(), $site);
148  $pageUrls = array_merge($pageUrls, $subPageUrls);
149  return array_unique($pageUrls);
150  }
151 
156  private function ‪getSlugsOfSubPages(int $pageId, Site $site): array
157  {
158  $pageUrls = [[]];
159 
160  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
161  ->getQueryBuilderForTable('pages')
162  ->select('uid', 'slug', $this->‪getPagesLanguageFieldName())
163  ->from('pages');
164 
165  $queryBuilder->where(
166  $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT))
167  );
168  $result = $queryBuilder->execute();
169 
170  while ($row = $result->fetch()) {
171  // @todo Considering only page slug is not complete, as it does not matches redirects with file extension,
172  // for ex. if PageTypeSuffix routeEnhancer are used and redirects are created based on that.
173  $slug = ltrim($row['slug'] ?? '', '/');
174  $lang = (int)($row[$this->‪getPagesLanguageFieldName()] ?? 0);
175  $siteLanguage = $site->getLanguageById($lang);
176 
177  // empty slugs should to occur here, but to be sure we skip them here, as they were already handled.
178  if (empty($slug)) {
179  continue;
180  }
181 
182  $pageUrls[] = [rtrim((string)$siteLanguage->getBase(), '/') . '/' . $slug];
183 
184  // only traverse for pages of default language (as even translated pages contain pid of parent in default language)
185  if ($lang === 0) {
186  $pageUrls[] = $this->‪getSlugsOfSubPages((int)$row['uid'], $site);
187  }
188  }
189  return array_merge(...$pageUrls);
190  }
191 
192  private function ‪getPagesLanguageFieldName(): string
193  {
194  return ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'] ?? 'sys_language_uid';
195  }
196 
197  private function ‪getPagesLanguageParentFieldName(): string
198  {
199  return ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] ?? 'l10n_parent';
200  }
201 }
‪TYPO3\CMS\Core\Site\Entity\Site\getLanguageById
‪SiteLanguage getLanguageById(int $languageId)
Definition: Site.php:235
‪TYPO3\CMS\Redirects\Service\IntegrityService\getAllPageUrlsForSite
‪array getAllPageUrlsForSite(Site $site)
Definition: IntegrityService.php:107
‪TYPO3\CMS\Core\Site\Entity\Site\getLanguages
‪SiteLanguage[] getLanguages()
Definition: Site.php:207
‪TYPO3\CMS\Redirects\Service\IntegrityService\$redirectService
‪RedirectService $redirectService
Definition: IntegrityService.php:34
‪TYPO3\CMS\Core\Http\Uri\getPath
‪string getPath()
Definition: Uri.php:287
‪TYPO3\CMS\Redirects\Service\IntegrityService\getPagesLanguageFieldName
‪getPagesLanguageFieldName()
Definition: IntegrityService.php:190
‪TYPO3\CMS\Core\Http\Uri\getPort
‪int null getPort()
Definition: Uri.php:257
‪TYPO3\CMS\Redirects\Service\RedirectService
Definition: RedirectService.php:48
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:29
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:40
‪TYPO3\CMS\Redirects\Service\IntegrityService\getMatchingRedirectByUri
‪getMatchingRedirectByUri(Uri $uri)
Definition: IntegrityService.php:81
‪TYPO3\CMS\Redirects\Service\IntegrityService\getPagesLanguageParentFieldName
‪getPagesLanguageParentFieldName()
Definition: IntegrityService.php:195
‪TYPO3\CMS\Redirects\Service\IntegrityService\__construct
‪__construct(RedirectService $redirectService=null, SiteFinder $siteFinder=null)
Definition: IntegrityService.php:40
‪TYPO3\CMS\Redirects\Service
Definition: IntegrityService.php:18
‪TYPO3\CMS\Core\Site\Entity\Site\getRootPageId
‪int getRootPageId()
Definition: Site.php:197
‪TYPO3\CMS\Redirects\Service\IntegrityService\findConflictingRedirects
‪Generator findConflictingRedirects(?string $siteIdentifier=null)
Definition: IntegrityService.php:57
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Redirects\Service\IntegrityService\$siteFinder
‪SiteFinder $siteFinder
Definition: IntegrityService.php:38
‪TYPO3\CMS\Core\Http\Uri\getHost
‪string getHost()
Definition: Uri.php:237
‪TYPO3\CMS\Redirects\Service\IntegrityService\getSlugsOfSubPages
‪getSlugsOfSubPages(int $pageId, Site $site)
Definition: IntegrityService.php:154
‪TYPO3\CMS\Redirects\Service\IntegrityService
Definition: IntegrityService.php:31
‪TYPO3\CMS\Redirects\Service\IntegrityService\getSites
‪Site[] getSites(?string $siteIdentifier)
Definition: IntegrityService.php:92
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46