‪TYPO3CMS  ‪main
SlugService.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\EventDispatcher\EventDispatcherInterface;
21 use Psr\Log\LoggerAwareInterface;
22 use Psr\Log\LoggerAwareTrait;
23 use TYPO3\CMS\Backend\Utility\BackendUtility;
29 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
47 
51 class ‪SlugService implements LoggerAwareInterface
52 {
53  use LoggerAwareTrait;
54 
58  final public const ‪CORRELATION_ID_IDENTIFIER = '5d8e6e70';
59 
62  protected bool ‪$autoUpdateSlugs = false;
63  protected bool ‪$autoCreateRedirects = false;
64  protected int ‪$redirectTTL = 0;
65  protected int ‪$httpStatusCode = 307;
66 
67  public function ‪__construct(
68  private readonly ‪Context $context,
69  private readonly ‪PageRepository $pageRepository,
70  private readonly ‪LinkService $linkService,
71  private readonly ‪RedirectCacheService $redirectCacheService,
72  private readonly ‪SlugRedirectChangeItemFactory $slugRedirectChangeItemFactory,
73  private readonly EventDispatcherInterface $eventDispatcher,
74  private readonly ‪ConnectionPool $connectionPool,
75  ) {}
76 
77  public function ‪rebuildSlugsForSlugChange(int $pageId, ‪SlugRedirectChangeItem $changeItem, ‪CorrelationId $correlationId): void
78  {
79  $this->‪initializeSettings($changeItem->‪getSite());
80  if ($this->autoUpdateSlugs || $this->autoCreateRedirects) {
81  $sourceHosts = [];
82  $this->‪createCorrelationIds($pageId, $correlationId);
83  if ($this->autoCreateRedirects) {
84  $sourceHosts = $this->‪createRedirects(
85  $changeItem,
86  $changeItem->‪getDefaultLanguagePageId(),
87  (int)$changeItem->‪getChanged()['sys_language_uid']
88  );
89  }
90  if ($this->autoUpdateSlugs) {
91  $sourceHosts += $this->‪checkSubPages($changeItem->‪getChanged(), $changeItem);
92  }
93  $this->‪sendNotification();
94  // rebuild caches only for matched source hosts
95  if ($sourceHosts !== []) {
96  foreach (array_unique($sourceHosts) as $sourceHost) {
97  $this->redirectCacheService->rebuildForHost($sourceHost);
98  }
99  }
100  }
101  }
102 
103  protected function ‪initializeSettings(‪Site $site): void
104  {
105  $settings = $site->‪getSettings();
106  $this->autoUpdateSlugs = (bool)$settings->get('redirects.autoUpdateSlugs', true);
107  $this->autoCreateRedirects = (bool)$settings->get('redirects.autoCreateRedirects', true);
108  if (!$this->context->getPropertyFromAspect('workspace', 'isLive')) {
109  $this->autoCreateRedirects = false;
110  }
111  $this->redirectTTL = (int)$settings->get('redirects.redirectTTL', 0);
112  $this->httpStatusCode = (int)$settings->get('redirects.httpStatusCode', 307);
113  }
114 
115  protected function ‪createCorrelationIds(int $pageId, ‪CorrelationId $correlationId): void
116  {
117  if ($correlationId->‪getSubject() === null) {
118  $subject = md5('pages:' . $pageId);
119  $correlationId = $correlationId->‪withSubject($subject);
120  }
121 
122  $this->correlationIdRedirectCreation = $correlationId->‪withAspects(self::CORRELATION_ID_IDENTIFIER, 'redirect');
123  $this->correlationIdSlugUpdate = $correlationId->‪withAspects(self::CORRELATION_ID_IDENTIFIER, 'slug');
124  }
125 
129  protected function ‪createRedirects(‪SlugRedirectChangeItem $changeItem, int $pageId, int $languageId): array
130  {
131  $sourceHosts = [];
132  $storagePid = $changeItem->‪getSite()->getRootPageId();
133  foreach ($changeItem->‪getSourcesCollection()->all() as $source) {
135  $date = $this->context->getAspect('date');
136  $endtime = $date->getDateTime()->modify('+' . $this->redirectTTL . ' days');
137  $targetLinkParameters = array_replace(['_language' => $languageId], $source->getTargetLinkParameters());
138  $targetLink = $this->linkService->asString([
139  'type' => 'page',
140  'pageuid' => $pageId,
141  'parameters' => ‪HttpUtility::buildQueryString($targetLinkParameters),
142  ]);
143  ‪$record = array_replace(
144  $this->getTableDefaultValues('sys_redirect'),
145  [
146  'pid' => $storagePid,
147  'updatedon' => $date->get('timestamp'),
148  'createdon' => $date->get('timestamp'),
149  'deleted' => 0,
150  'disabled' => 0,
151  'starttime' => 0,
152  'endtime' => $this->redirectTTL > 0 ? $endtime->getTimestamp() : 0,
153  'source_host' => $source->getHost(),
154  'source_path' => $source->getPath(),
155  'is_regexp' => 0,
156  'force_https' => 0,
157  'respect_query_parameters' => 0,
158  'target' => $targetLink,
159  'target_statuscode' => $this->httpStatusCode,
160  'hitcount' => 0,
161  'lasthiton' => 0,
162  'disable_hitcount' => 0,
163  'creation_type' => 0,
164  ]
165  );
166 
167  ‪$record = $this->eventDispatcher->dispatch(
169  slugRedirectChangeItem: $changeItem,
170  source: $source,
171  redirectRecord: ‪$record,
172  )
173  )->getRedirectRecord();
174  // @todo Use dataHandler to create records
175  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
176  ->getConnectionForTable('sys_redirect');
177  $connection->insert('sys_redirect', ‪$record);
178  $id = (int)$connection->lastInsertId();
179  ‪$record['uid'] = $id;
180  $this->‪getRecordHistoryStore()->addRecord('sys_redirect', $id, ‪$record, $this->correlationIdRedirectCreation);
181  $this->eventDispatcher->dispatch(
183  slugRedirectChangeItem: $changeItem,
184  source: $source,
185  redirectRecord: ‪$record,
186  )
187  );
188  if (!in_array($source->getHost(), $sourceHosts)) {
189  $sourceHosts[] = $source->getHost();
190  }
191  }
192  return $sourceHosts;
193  }
194 
198  protected function ‪checkSubPages(array $currentPageRecord, ‪SlugRedirectChangeItem $parentChangeItem): array
199  {
200  $sourceHosts = [];
201  $languageUid = (int)$currentPageRecord['sys_language_uid'];
202  // resolveSubPages needs the page id of the default language
203  $pageId = $languageUid === 0 ? (int)$currentPageRecord['uid'] : (int)$currentPageRecord['l10n_parent'];
204  $subPageRecords = $this->‪resolveSubPages($pageId, $languageUid);
205  foreach ($subPageRecords as $subPageRecord) {
206  $changeItem = $this->slugRedirectChangeItemFactory->create(
207  pageId: (int)$subPageRecord['uid'],
208  original: $subPageRecord
209  );
210  if ($changeItem === null) {
211  continue;
212  }
213  $updatedPageRecord = $this->‪updateSlug($subPageRecord, $parentChangeItem);
214  if ($updatedPageRecord !== null && $this->autoCreateRedirects) {
215  $subPageId = (int)$subPageRecord['sys_language_uid'] === 0 ? (int)$subPageRecord['uid'] : (int)$subPageRecord['l10n_parent'];
216  $changeItem = $changeItem->withChanged($updatedPageRecord);
217  $sourceHosts += array_values($this->‪createRedirects($changeItem, $subPageId, $languageUid));
218  }
219  }
220  return $sourceHosts;
221  }
222 
223  protected function ‪resolveSubPages(int $id, int $languageUid): array
224  {
225  // First resolve all sub-pages in default language
226  $queryBuilder = $this->‪getQueryBuilderForPages();
227  $subPages = $queryBuilder
228  ->select('*')
229  ->from('pages')
230  ->where(
231  $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($id, ‪Connection::PARAM_INT)),
232  $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT))
233  )
234  ->orderBy('uid', 'ASC')
235  ->executeQuery()
236  ->fetchAllAssociative();
237 
238  // if the language is not the default language, resolve the language related records.
239  if ($languageUid > 0) {
240  $queryBuilder = $this->‪getQueryBuilderForPages();
241  $subPages = $queryBuilder
242  ->select('*')
243  ->from('pages')
244  ->where(
245  $queryBuilder->expr()->in('l10n_parent', $queryBuilder->createNamedParameter(array_column($subPages, 'uid'), ‪Connection::PARAM_INT_ARRAY)),
246  $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($languageUid, ‪Connection::PARAM_INT))
247  )
248  ->orderBy('uid', 'ASC')
249  ->executeQuery()
250  ->fetchAllAssociative();
251  }
252  $results = [];
253  if (!empty($subPages)) {
254  $subPages = $this->pageRepository->getPagesOverlay($subPages, $languageUid);
255  foreach ($subPages as $subPage) {
256  $results[] = $subPage;
257  // resolveSubPages needs the page id of the default language
258  $pageId = $languageUid === 0 ? (int)$subPage['uid'] : (int)$subPage['l10n_parent'];
259  foreach ($this->‪resolveSubPages($pageId, $languageUid) as $page) {
260  $results[] = $page;
261  }
262  }
263  }
264  return $results;
265  }
266 
271  protected function ‪updateSlug(array $subPageRecord, ‪SlugRedirectChangeItem $changeItem): ?array
272  {
273  if ($changeItem->‪getChanged() === null
274  || !str_starts_with($subPageRecord['slug'], $changeItem->‪getOriginal()['slug'])
275  ) {
276  return null;
277  }
278  $oldSlugOfParentPage = $changeItem->‪getOriginal()['slug'];
279  $newSlugOfParentPage = $changeItem->‪getChanged()['slug'];
280  $newSlug = rtrim($newSlugOfParentPage, '/') . '/'
281  . substr($subPageRecord['slug'], strlen(rtrim($oldSlugOfParentPage, '/') . '/'));
282  $state = ‪RecordStateFactory::forName('pages')
283  ->fromArray($subPageRecord, $subPageRecord['pid'], $subPageRecord['uid']);
284  $fieldConfig = ‪$GLOBALS['TCA']['pages']['columns']['slug']['config'] ?? [];
285  $slugHelper = GeneralUtility::makeInstance(SlugHelper::class, 'pages', 'slug', $fieldConfig);
286 
287  if (!$slugHelper->isUniqueInSite($newSlug, $state)) {
288  $newSlug = $slugHelper->buildSlugForUniqueInSite($newSlug, $state);
289  }
290 
291  $this->‪persistNewSlug((int)$subPageRecord['uid'], $newSlug);
292  return BackendUtility::getRecord('pages', (int)$subPageRecord['uid']);
293  }
294 
295  protected function ‪persistNewSlug(int ‪$uid, string $newSlug): void
296  {
297  $this->‪disableHook();
298  $data = [];
299  $data['pages'][‪$uid]['slug'] = $newSlug;
300  $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
301  $dataHandler->start($data, []);
302  $dataHandler->setCorrelationId($this->correlationIdSlugUpdate);
303  $dataHandler->process_datamap();
304  $this->‪enabledHook();
305  }
306 
307  protected function ‪sendNotification(): void
308  {
309  $data = [
310  'componentName' => 'redirects',
311  'eventName' => 'slugChanged',
312  'correlations' => [
313  'correlationIdSlugUpdate' => (string)$this->correlationIdSlugUpdate,
314  'correlationIdRedirectCreation' => (string)‪$this->correlationIdRedirectCreation,
315  ],
316  'autoUpdateSlugs' => (bool)$this->autoUpdateSlugs,
317  'autoCreateRedirects' => (bool)‪$this->autoCreateRedirects,
318  ];
319  BackendUtility::setUpdateSignal('redirects:slugChanged', $data);
320  }
321 
323  {
324  $backendUser = $this->‪getBackendUser();
325  return GeneralUtility::makeInstance(
326  RecordHistoryStore::class,
328  (int)$backendUser->user['uid'],
329  (int)$backendUser->getOriginalUserIdWhenInSwitchUserMode(),
330  $this->context->getPropertyFromAspect('date', 'timestamp'),
331  $backendUser->workspace
332  );
333  }
334 
335  protected function ‪getQueryBuilderForPages(): QueryBuilder
336  {
337  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
338  ->getQueryBuilderForTable('pages');
340  $queryBuilder
341  ->getRestrictions()
342  ->removeAll()
343  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
344  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->context->getPropertyFromAspect('workspace', 'id')));
345  return $queryBuilder;
346  }
347 
348  protected function ‪enabledHook(): void
349  {
350  ‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass']['redirects'] =
351  DataHandlerSlugUpdateHook::class;
352  }
353 
354  protected function ‪disableHook(): void
355  {
356  unset(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass']['redirects']);
357  }
358 
360  {
361  return ‪$GLOBALS['BE_USER'];
362  }
363 
371  private function getTableDefaultValues(string $tableName): array
372  {
373  ‪$defaults = [];
374  foreach (‪$GLOBALS['TCA'][$tableName]['columns'] ?? [] as $columnName => $columnConfig) {
375  if (!array_key_exists('default', $columnConfig['config'] ?? [])) {
376  continue;
377  }
378  ‪$defaults[$columnName] = $columnConfig['config']['default'];
379  }
380  $connection = $this->connectionPool->getConnectionForTable($tableName);
381  ‪$table = $connection->getSchemaInformation()->introspectTable($tableName);
382  foreach (‪$table->getColumns() as $column) {
383  $columnName = $column->getName();
384  if ($columnName === 'uid' || $column->getAutoincrement() === true) {
385  // Autoincrement fields and therefore the default TYPO3 `uid` column
386  // should be not provided in a data array to ensure the behaviour
387  // kicks correctly in.
388  continue;
389  }
390  if (array_key_exists($columnName, ‪$defaults)) {
391  // Already having TCA default value, which weigths higher.
392  continue;
393  }
394  $columnDefaultValue = $column->getDefault();
395  if ($columnDefaultValue === null && $column->getNotnull() === false) {
396  // No need to set null as default value for a nullable column.
397  continue;
398  }
399  ‪$defaults[$columnName] = $columnDefaultValue;
400  }
401  return ‪$defaults;
402  }
403 }
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:94
‪TYPO3\CMS\Redirects\Service\SlugService\CORRELATION_ID_IDENTIFIER
‪final const CORRELATION_ID_IDENTIFIER
Definition: SlugService.php:58
‪TYPO3\CMS\Redirects\Service\SlugService\updateSlug
‪updateSlug(array $subPageRecord, SlugRedirectChangeItem $changeItem)
Definition: SlugService.php:271
‪TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem
Definition: SlugRedirectChangeItem.php:30
‪TYPO3\CMS\Core\DataHandling\History\RecordHistoryStore\USER_BACKEND
‪const USER_BACKEND
Definition: RecordHistoryStore.php:39
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Redirects\Service\SlugService\getRecordHistoryStore
‪getRecordHistoryStore()
Definition: SlugService.php:322
‪TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem\getSourcesCollection
‪getSourcesCollection()
Definition: SlugRedirectChangeItem.php:71
‪TYPO3\CMS\Redirects\Hooks\DataHandlerSlugUpdateHook
Definition: DataHandlerSlugUpdateHook.php:30
‪TYPO3\CMS\Redirects\Service\SlugService\$autoUpdateSlugs
‪bool $autoUpdateSlugs
Definition: SlugService.php:62
‪TYPO3\CMS\Redirects\Service\SlugService\$redirectTTL
‪int $redirectTTL
Definition: SlugService.php:64
‪TYPO3\CMS\Core\DataHandling\Model\CorrelationId\getSubject
‪getSubject()
Definition: CorrelationId.php:116
‪TYPO3\CMS\Redirects\Service\SlugService\createRedirects
‪string[] createRedirects(SlugRedirectChangeItem $changeItem, int $pageId, int $languageId)
Definition: SlugService.php:129
‪TYPO3\CMS\Redirects\Event\AfterAutoCreateRedirectHasBeenPersistedEvent
Definition: AfterAutoCreateRedirectHasBeenPersistedEvent.php:32
‪TYPO3\CMS\Redirects\Service\SlugService\sendNotification
‪sendNotification()
Definition: SlugService.php:307
‪TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem\getChanged
‪getChanged()
Definition: SlugRedirectChangeItem.php:56
‪TYPO3\CMS\Redirects\Service\SlugService\resolveSubPages
‪resolveSubPages(int $id, int $languageUid)
Definition: SlugService.php:223
‪TYPO3\CMS\Core\DataHandling\Model\CorrelationId\withAspects
‪withAspects(string ... $aspects)
Definition: CorrelationId.php:101
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Redirects\Event\ModifyAutoCreateRedirectRecordBeforePersistingEvent
Definition: ModifyAutoCreateRedirectRecordBeforePersistingEvent.php:32
‪TYPO3\CMS\Redirects\Service\SlugService\initializeSettings
‪initializeSettings(Site $site)
Definition: SlugService.php:103
‪TYPO3\CMS\Core\DataHandling\Model\RecordStateFactory
Definition: RecordStateFactory.php:26
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:42
‪TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem\getOriginal
‪getOriginal()
Definition: SlugRedirectChangeItem.php:51
‪TYPO3\CMS\Redirects\Service\SlugService\$table
‪$table
Definition: SlugService.php:381
‪TYPO3\CMS\Core\DataHandling\History\RecordHistoryStore
Definition: RecordHistoryStore.php:31
‪TYPO3\CMS\Redirects\Service\RedirectCacheService
Definition: RedirectCacheService.php:34
‪TYPO3\CMS\Redirects\Service\SlugService\getBackendUser
‪getBackendUser()
Definition: SlugService.php:359
‪TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem\getDefaultLanguagePageId
‪getDefaultLanguagePageId()
Definition: SlugRedirectChangeItem.php:41
‪TYPO3\CMS\Redirects\Service\SlugService\rebuildSlugsForSlugChange
‪rebuildSlugsForSlugChange(int $pageId, SlugRedirectChangeItem $changeItem, CorrelationId $correlationId)
Definition: SlugService.php:77
‪TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItem\getSite
‪getSite()
Definition: SlugRedirectChangeItem.php:61
‪TYPO3\CMS\Core\DataHandling\Model\CorrelationId
Definition: CorrelationId.php:29
‪TYPO3\CMS\Redirects\RedirectUpdate\SlugRedirectChangeItemFactory
Definition: SlugRedirectChangeItemFactory.php:31
‪TYPO3\CMS\Core\DataHandling\Model\CorrelationId\withSubject
‪withSubject(string $subject)
Definition: CorrelationId.php:91
‪TYPO3\CMS\Core\DataHandling\SlugHelper
Definition: SlugHelper.php:43
‪TYPO3\CMS\Redirects\Service\SlugService\$correlationIdSlugUpdate
‪CorrelationId string $correlationIdSlugUpdate
Definition: SlugService.php:61
‪TYPO3\CMS\Core\Utility\HttpUtility\buildQueryString
‪static string buildQueryString(array $parameters, string $prependCharacter='', bool $skipEmptyParameters=false)
Definition: HttpUtility.php:124
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Redirects\Service\SlugService\$httpStatusCode
‪int $httpStatusCode
Definition: SlugService.php:65
‪TYPO3\CMS\Redirects\Service\SlugService\$defaults
‪foreach($table->getColumns() as $column) return $defaults
Definition: SlugService.php:382
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Redirects\Service\SlugService\getQueryBuilderForPages
‪getQueryBuilderForPages()
Definition: SlugService.php:335
‪TYPO3\CMS\Redirects\Service
Definition: IntegrityService.php:18
‪TYPO3\CMS\Redirects\Service\SlugService\$autoCreateRedirects
‪bool $autoCreateRedirects
Definition: SlugService.php:63
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪TYPO3\CMS\Redirects\Service\SlugService\persistNewSlug
‪persistNewSlug(int $uid, string $newSlug)
Definition: SlugService.php:295
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Redirects\Service\SlugService\$correlationIdRedirectCreation
‪CorrelationId string $correlationIdRedirectCreation
Definition: SlugService.php:60
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:24
‪TYPO3\CMS\Redirects\Service\SlugService\createCorrelationIds
‪createCorrelationIds(int $pageId, CorrelationId $correlationId)
Definition: SlugService.php:115
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:69
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Redirects\Service\SlugService
Definition: SlugService.php:52
‪TYPO3\CMS\Core\Site\Entity\Site\getSettings
‪getSettings()
Definition: Site.php:299
‪TYPO3\CMS\Redirects\Service\SlugService\checkSubPages
‪string[] checkSubPages(array $currentPageRecord, SlugRedirectChangeItem $parentChangeItem)
Definition: SlugService.php:198
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT_ARRAY
‪const PARAM_INT_ARRAY
Definition: Connection.php:72
‪TYPO3\CMS\Core\Context\DateTimeAspect
Definition: DateTimeAspect.php:35
‪TYPO3\CMS\Redirects\Service\SlugService\disableHook
‪disableHook()
Definition: SlugService.php:354
‪TYPO3\CMS\Core\DataHandling\Model\RecordStateFactory\forName
‪static forName(string $name)
Definition: RecordStateFactory.php:29
‪TYPO3\CMS\Redirects\Service\SlugService\enabledHook
‪enabledHook()
Definition: SlugService.php:348
‪TYPO3\CMS\Redirects\Service\SlugService\__construct
‪__construct(private readonly Context $context, private readonly PageRepository $pageRepository, private readonly LinkService $linkService, private readonly RedirectCacheService $redirectCacheService, private readonly SlugRedirectChangeItemFactory $slugRedirectChangeItemFactory, private readonly EventDispatcherInterface $eventDispatcher, private readonly ConnectionPool $connectionPool,)
Definition: SlugService.php:67
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39