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