‪TYPO3CMS  ‪main
SlugHelper.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 TYPO3\CMS\Backend\Utility\BackendUtility;
25 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
38 
43 {
47  protected ‪$tableName;
48 
52  protected ‪$fieldName;
53 
57  protected ‪$workspaceId;
58 
62  protected ‪$configuration = [];
63 
67  protected ‪$workspaceEnabled;
68 
76  protected ‪$prependSlashInSlug;
77 
86  public function ‪__construct(string ‪$tableName, string ‪$fieldName, array ‪$configuration, int ‪$workspaceId = 0)
87  {
88  $this->tableName = ‪$tableName;
89  $this->fieldName = ‪$fieldName;
90  $this->configuration = ‪$configuration;
91  $this->workspaceId = ‪$workspaceId;
92 
93  if ($this->tableName === 'pages' && $this->fieldName === 'slug') {
94  $this->prependSlashInSlug = true;
95  } else {
96  $this->prependSlashInSlug = $this->configuration['prependSlash'] ?? false;
97  }
98 
99  $this->workspaceEnabled = BackendUtility::isTableWorkspaceEnabled(‪$tableName);
100  }
101 
105  public function ‪sanitize(string $slug): string
106  {
107  // Convert to lowercase + remove tags
108  $slug = mb_strtolower($slug, 'utf-8');
109  $slug = strip_tags($slug);
110 
111  // Convert some special tokens (space, "_" and "-") to the space character
112  $fallbackCharacter = (string)($this->configuration['fallbackCharacter'] ?? '-');
113  $slug = (string)preg_replace('/[ \t\x{00A0}\-+_]+/u', $fallbackCharacter, $slug);
114 
115  if (!\Normalizer::isNormalized($slug)) {
116  $slug = \Normalizer::normalize($slug) ?: $slug;
117  }
118 
119  // Convert extended letters to ascii equivalents
120  // The specCharsToASCII() converts "€" to "EUR"
121  $slug = GeneralUtility::makeInstance(CharsetConverter::class)->specCharsToASCII('utf-8', $slug);
122 
123  // Get rid of all invalid characters, but allow slashes
124  $slug = (string)preg_replace('/[^\p{L}\p{M}0-9\/' . preg_quote($fallbackCharacter) . ']/u', '', $slug);
125 
126  // Convert multiple fallback characters to a single one
127  if ($fallbackCharacter !== '') {
128  $slug = (string)preg_replace('/' . preg_quote($fallbackCharacter) . '{2,}/', $fallbackCharacter, $slug);
129  }
130 
131  // Ensure slug is lower cased after all replacement was done
132  $slug = mb_strtolower($slug, 'utf-8');
133  // Extract slug, thus it does not have wrapping fallback and slash characters
134  $extractedSlug = $this->‪extract($slug);
135  // Remove trailing and beginning slashes, except if the trailing slash was added, then we'll re-add it
136  $appendTrailingSlash = $extractedSlug !== '' && substr($slug, -1) === '/';
137  $slug = $extractedSlug . ($appendTrailingSlash ? '/' : '');
138  if ($this->prependSlashInSlug && ($slug[0] ?? '') !== '/') {
139  $slug = '/' . $slug;
140  }
141  return $slug;
142  }
143 
148  public function ‪extract(string $slug): string
149  {
150  // Convert some special tokens (space, "_" and "-") to the space character
151  $fallbackCharacter = $this->configuration['fallbackCharacter'] ?? '-';
152  return trim($slug, $fallbackCharacter . '/');
153  }
154 
160  public function ‪generate(array $recordData, int $pid): string
161  {
162  if ($this->tableName === 'pages' && ($pid === 0 || !empty($recordData['is_siteroot']))) {
163  return '/';
164  }
165  $prefix = '';
166  if ($this->tableName === 'pages' && ($this->configuration['generatorOptions']['prefixParentPageSlug'] ?? false)) {
167  $languageFieldName = ‪$GLOBALS['TCA'][‪$this->tableName]['ctrl']['languageField'] ?? null;
168  $languageId = (int)($recordData[$languageFieldName] ?? 0);
169  $parentPageRecord = $this->‪resolveParentPageRecord($pid, $languageId);
170  if (is_array($parentPageRecord)) {
171  // If the parent page has a slug, use that instead of "re-generating" the slug from the parents' page title
172  if (!empty($parentPageRecord['slug'])) {
173  $rootLineItemSlug = $parentPageRecord['slug'];
174  } else {
175  $rootLineItemSlug = $this->‪generate($parentPageRecord, (int)$parentPageRecord['pid']);
176  }
177  $rootLineItemSlug = trim($rootLineItemSlug, '/');
178  if (!empty($rootLineItemSlug)) {
179  $prefix = $rootLineItemSlug;
180  }
181  }
182  }
183 
184  $fieldSeparator = $this->configuration['generatorOptions']['fieldSeparator'] ?? '/';
185  $slugParts = [];
186 
187  $replaceConfiguration = $this->configuration['generatorOptions']['replacements'] ?? [];
188  foreach ($this->configuration['generatorOptions']['fields'] ?? [] as $fieldNameParts) {
189  if (is_string($fieldNameParts)) {
190  $fieldNameParts = ‪GeneralUtility::trimExplode(',', $fieldNameParts);
191  }
192  foreach ($fieldNameParts as ‪$fieldName) {
193  if (!empty($recordData[‪$fieldName])) {
194  $pieceOfSlug = (string)$recordData[‪$fieldName];
195  $pieceOfSlug = str_replace(
196  array_keys($replaceConfiguration),
197  array_values($replaceConfiguration),
198  $pieceOfSlug
199  );
200  $slugParts[] = $pieceOfSlug;
201  break;
202  }
203  }
204  }
205  $slug = implode($fieldSeparator, $slugParts);
206  $slug = $this->‪sanitize($slug);
207  // No valid data found
208  if ($slug === '' || $slug === '/') {
209  $slug = 'default-' . md5((string)json_encode($recordData));
210  }
211  if ($this->prependSlashInSlug && ($slug[0] ?? '') !== '/') {
212  $slug = '/' . $slug;
213  }
214  if (!empty($prefix)) {
215  $slug = $prefix . $slug;
216  }
217 
218  // Hook for alternative ways of filling/modifying the slug data
219  foreach ($this->configuration['generatorOptions']['postModifiers'] ?? [] as $funcName) {
220  $hookParameters = [
221  'slug' => $slug,
222  'workspaceId' => ‪$this->workspaceId,
223  'configuration' => ‪$this->configuration,
224  'record' => $recordData,
225  'pid' => $pid,
226  'prefix' => $prefix,
227  'tableName' => ‪$this->tableName,
228  'fieldName' => ‪$this->fieldName,
229  ];
230  $slug = GeneralUtility::callUserFunction($funcName, $hookParameters, $this);
231  }
232  return $this->‪sanitize($slug);
233  }
234 
238  public function ‪isUniqueInPid(string $slug, ‪RecordState $state): bool
239  {
240  $pageId = (int)$state->‪resolveNodeIdentifier();
241  $recordId = $state->‪getSubject()->getIdentifier();
242  $languageId = $state->‪getContext()->getLanguageId();
243 
244  $queryBuilder = $this->‪createPreparedQueryBuilder();
245  $this->‪applySlugConstraint($queryBuilder, $slug);
246  $this->‪applyPageIdConstraint($queryBuilder, $pageId);
247  $this->‪applyRecordConstraint($queryBuilder, $recordId);
248  $this->‪applyLanguageConstraint($queryBuilder, $languageId);
249  $this->‪applyWorkspaceConstraint($queryBuilder, $state);
250  $statement = $queryBuilder->executeQuery();
251 
252  $records = $this->‪resolveVersionOverlays(
253  $statement->fetchAllAssociative()
254  );
255  return count($records) === 0;
256  }
257 
263  public function ‪isUniqueInSite(string $slug, ‪RecordState $state): bool
264  {
265  $pageId = $state->‪resolveNodeAggregateIdentifier();
266  $recordId = $state->‪getSubject()->getIdentifier();
267  $languageId = $state->‪getContext()->getLanguageId();
268 
270  // If this is a new page, we use the parent page to resolve the site
271  $pageId = $state->‪getNode()->getIdentifier();
272  }
273  $pageId = (int)$pageId;
274 
275  $queryBuilder = $this->‪createPreparedQueryBuilder();
276  $this->‪applySlugConstraint($queryBuilder, $slug);
277  $this->‪applyRecordConstraint($queryBuilder, $recordId);
278  $this->‪applyLanguageConstraint($queryBuilder, $languageId);
279  $this->‪applyWorkspaceConstraint($queryBuilder, $state);
280  $statement = $queryBuilder->executeQuery();
281 
282  $records = $this->‪resolveVersionOverlays(
283  $statement->fetchAllAssociative()
284  );
285  if (count($records) === 0) {
286  return true;
287  }
288 
289  // The installation contains at least ONE other record with the same slug
290  // Now find out if it is the same root page ID
291  $this->‪flushRootLineCaches();
292  $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
293  try {
294  $siteOfCurrentRecord = $siteFinder->getSiteByPageId($pageId);
295  } catch (‪SiteNotFoundException $e) {
296  // Not within a site, so nothing to do
297  // TODO: Rather than silently ignoring this misconfiguration,
298  // a warning should be thrown here, or maybe even let the
299  // exception bubble up and catch it in places that uses this API
300  return true;
301  }
302  foreach ($records as ‪$record) {
303  try {
304  $recordState = ‪RecordStateFactory::forName($this->tableName)->fromArray(‪$record);
305  $siteOfExistingRecord = $siteFinder->getSiteByPageId(
306  (int)$recordState->resolveNodeAggregateIdentifier()
307  );
308  } catch (‪SiteNotFoundException $exception) {
309  // In case not site is found, the record is not
310  // organized in any site
311  continue;
312  }
313  if ($siteOfExistingRecord->getRootPageId() === $siteOfCurrentRecord->getRootPageId()) {
314  return false;
315  }
316  }
317 
318  // Otherwise, everything is still fine
319  return true;
320  }
321 
327  public function ‪isUniqueInTable(string $slug, ‪RecordState $state): bool
328  {
329  $recordId = $state->‪getSubject()->getIdentifier();
330  $languageId = $state->‪getContext()->getLanguageId();
331 
332  $queryBuilder = $this->‪createPreparedQueryBuilder();
333  $this->‪applySlugConstraint($queryBuilder, $slug);
334  $this->‪applyRecordConstraint($queryBuilder, $recordId);
335  $this->‪applyLanguageConstraint($queryBuilder, $languageId);
336  $this->‪applyWorkspaceConstraint($queryBuilder, $state);
337  $statement = $queryBuilder->executeQuery();
338 
339  $records = $this->‪resolveVersionOverlays(
340  $statement->fetchAllAssociative()
341  );
342 
343  return count($records) === 0;
344  }
345 
350  protected function ‪flushRootLineCaches(): void
351  {
352  $cacheManager = GeneralUtility::makeInstance(CacheManager::class);
353  $cacheManager->getCache('runtime')->flushByTag(‪RootlineUtility::RUNTIME_CACHE_TAG);
354  $cacheManager->getCache('rootline')->flush();
355  }
356 
364  protected function ‪buildSlug(string $slug, RecordState $state, callable $isUnique): string
365  {
366  $slug = $this->‪sanitize($slug);
367  $rawValue = $this->‪extract($slug);
368  $newValue = $slug;
369  $counter = 0;
370  while (
371  !$isUnique($newValue, $state)
372  && ++$counter <= 100
373  ) {
374  $newValue = $this->‪sanitize($rawValue . '-' . $counter);
375  }
376  if ($counter === 100) {
377  $uniqueId = ‪StringUtility::getUniqueId();
378  $newValue = $this->‪sanitize($rawValue . '-' . md5($uniqueId));
379  }
380  return $newValue;
381  }
382 
389  public function ‪buildSlugForUniqueInSite(string $slug, RecordState $state): string
390  {
391  return $this->‪buildSlug($slug, $state, [$this, 'isUniqueInSite']);
392  }
393 
399  public function ‪buildSlugForUniqueInPid(string $slug, ‪RecordState $state): string
400  {
401  return $this->‪buildSlug($slug, $state, [$this, 'isUniqueInPid']);
402  }
403 
410  public function ‪buildSlugForUniqueInTable(string $slug, ‪RecordState $state): string
411  {
412  return $this->‪buildSlug($slug, $state, [$this, 'isUniqueInTable']);
413  }
414 
415  protected function ‪createPreparedQueryBuilder(): QueryBuilder
416  {
417  $fieldNames = ['uid', 'pid', ‪$this->fieldName];
418  if ($this->workspaceEnabled) {
419  $fieldNames[] = 't3ver_state';
420  $fieldNames[] = 't3ver_oid';
421  }
422  $languageFieldName = ‪$GLOBALS['TCA'][‪$this->tableName]['ctrl']['languageField'] ?? null;
423  if (is_string($languageFieldName)) {
424  $fieldNames[] = $languageFieldName;
425  }
426  $languageParentFieldName = ‪$GLOBALS['TCA'][‪$this->tableName]['ctrl']['transOrigPointerField'] ?? null;
427  if (is_string($languageParentFieldName)) {
428  $fieldNames[] = $languageParentFieldName;
429  }
430 
431  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->tableName);
432  $queryBuilder->getRestrictions()
433  ->removeAll()
434  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
435  $queryBuilder
436  ->select(...$fieldNames)
437  ->from($this->tableName);
438  return $queryBuilder;
439  }
440 
441  protected function ‪applyWorkspaceConstraint(QueryBuilder $queryBuilder, ‪RecordState $state)
442  {
443  if (!$this->workspaceEnabled) {
444  return;
445  }
446 
447  $queryBuilder->getRestrictions()->add(
448  GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->workspaceId)
449  );
450 
451  // Exclude the online record of a versioned record
452  if ($state->‪getVersionLink()) {
453  $queryBuilder->andWhere(
454  $queryBuilder->expr()->neq('uid', $state->‪getVersionLink()->‪getSubject()->getIdentifier())
455  );
456  }
457  }
458 
464  protected function ‪applyLanguageConstraint(QueryBuilder $queryBuilder, int $languageId)
465  {
466  $languageFieldName = ‪$GLOBALS['TCA'][‪$this->tableName]['ctrl']['languageField'] ?? null;
467  if (!is_string($languageFieldName)) {
468  return;
469  }
470  if ($languageId === -1) {
471  // if language is -1 "all languages" we need to check against all languages, thus not adding
472  // any kind of language constraints.
473  return;
474  }
475 
476  // Only check records of the given language or -1 (all languages)
477  $queryBuilder->andWhere(
478  $queryBuilder->expr()->or(
479  $queryBuilder->expr()->eq(
480  $languageFieldName,
481  $queryBuilder->createNamedParameter($languageId, ‪Connection::PARAM_INT)
482  ),
483  $queryBuilder->expr()->eq(
484  $languageFieldName,
485  $queryBuilder->createNamedParameter(-1, ‪Connection::PARAM_INT)
486  )
487  )
488  );
489  }
490 
491  protected function ‪applySlugConstraint(QueryBuilder $queryBuilder, string $slug)
492  {
493  $queryBuilder->where(
494  $queryBuilder->expr()->eq(
495  $this->fieldName,
496  $queryBuilder->createNamedParameter($slug)
497  )
498  );
499  }
500 
501  protected function ‪applyPageIdConstraint(QueryBuilder $queryBuilder, int $pageId)
502  {
503  if ($pageId < 0) {
504  throw new \RuntimeException(
505  sprintf(
506  'Page id must be positive "%d"',
507  $pageId
508  ),
509  1534962573
510  );
511  }
512 
513  $queryBuilder->andWhere(
514  $queryBuilder->expr()->eq(
515  'pid',
516  $queryBuilder->createNamedParameter($pageId, ‪Connection::PARAM_INT)
517  )
518  );
519  }
520 
524  protected function ‪applyRecordConstraint(QueryBuilder $queryBuilder, $recordId)
525  {
526  // Exclude the current record if it is an existing record
528  return;
529  }
530 
531  $queryBuilder->andWhere(
532  $queryBuilder->expr()->neq('uid', $queryBuilder->createNamedParameter($recordId, ‪Connection::PARAM_INT))
533  );
534  if ($this->workspaceId > 0 && $this->workspaceEnabled) {
535  $liveId = BackendUtility::getLiveVersionIdOfRecord($this->tableName, (int)$recordId) ?? $recordId;
536  $queryBuilder->andWhere(
537  $queryBuilder->expr()->neq('uid', $queryBuilder->createNamedParameter($liveId, ‪Connection::PARAM_INT))
538  );
539  }
540  }
541 
542  protected function ‪resolveVersionOverlays(array $records): array
543  {
544  if (!$this->workspaceEnabled) {
545  return $records;
546  }
547 
548  return array_filter(
549  array_map(
550  function (array ‪$record): ?array {
551  BackendUtility::workspaceOL(
552  $this->tableName,
553  ‪$record,
554  $this->workspaceId,
555  true
556  );
557  if (VersionState::tryFrom(‪$record['t3ver_state'] ?? 0) ===
558  VersionState::DELETE_PLACEHOLDER) {
559  return null;
560  }
561  return ‪$record;
562  },
563  $records
564  )
565  );
566  }
567 
571  protected function ‪resolveParentPageRecord(int $pid, int $languageId): ?array
572  {
573  $rootLine = BackendUtility::BEgetRootLine($pid, '', true, ['nav_title']);
574  $excludeDokTypes = [
577  ];
578  do {
579  $parentPageRecord = array_shift($rootLine);
580  // exclude spacers, recyclers and folders
581  } while (!empty($rootLine) && in_array((int)$parentPageRecord['doktype'], $excludeDokTypes, true));
582  if ($languageId > 0) {
583  $languageIds = [$languageId];
584  $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
585 
586  try {
587  $site = $siteFinder->getSiteByPageId($pid);
588  $siteLanguage = $site->getLanguageById($languageId);
589  $languageIds = array_merge($languageIds, $siteLanguage->getFallbackLanguageIds());
590  } catch (SiteNotFoundException | \InvalidArgumentException $e) {
591  // no site or requested language available - move on
592  }
593 
594  foreach ($languageIds as $languageId) {
595  $localizedParentPageRecord = BackendUtility::getRecordLocalization('pages', $parentPageRecord['uid'], $languageId);
596  if (!empty($localizedParentPageRecord)) {
597  $parentPageRecord = reset($localizedParentPageRecord);
598  break;
599  }
600  }
601  }
602  return $parentPageRecord;
603  }
604 }
‪TYPO3\CMS\Core\DataHandling\SlugHelper\applyRecordConstraint
‪applyRecordConstraint(QueryBuilder $queryBuilder, $recordId)
Definition: SlugHelper.php:518
‪TYPO3\CMS\Core\DataHandling\SlugHelper\isUniqueInSite
‪isUniqueInSite(string $slug, RecordState $state)
Definition: SlugHelper.php:257
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Core\Utility\RootlineUtility\RUNTIME_CACHE_TAG
‪const RUNTIME_CACHE_TAG
Definition: RootlineUtility.php:42
‪TYPO3\CMS\Core\DataHandling\Model\RecordState\getVersionLink
‪EntityPointerLink getVersionLink()
Definition: RecordState.php:99
‪TYPO3\CMS\Core\DataHandling\SlugHelper\buildSlugForUniqueInTable
‪buildSlugForUniqueInTable(string $slug, RecordState $state)
Definition: SlugHelper.php:404
‪TYPO3\CMS\Core\DataHandling\SlugHelper\$workspaceEnabled
‪bool $workspaceEnabled
Definition: SlugHelper.php:62
‪TYPO3\CMS\Core\Versioning\VersionState
‪VersionState
Definition: VersionState.php:22
‪TYPO3\CMS\Core\DataHandling\Model\RecordState\getNode
‪getNode()
Definition: RecordState.php:65
‪TYPO3\CMS\Core\DataHandling
Definition: DataHandler.php:16
‪TYPO3\CMS\Core\Utility\RootlineUtility
Definition: RootlineUtility.php:40
‪TYPO3\CMS\Core\DataHandling\Model\RecordState\getSubject
‪getSubject()
Definition: RecordState.php:70
‪TYPO3\CMS\Core\DataHandling\SlugHelper\applyLanguageConstraint
‪applyLanguageConstraint(QueryBuilder $queryBuilder, int $languageId)
Definition: SlugHelper.php:458
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:25
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Core\Charset\CharsetConverter
Definition: CharsetConverter.php:54
‪TYPO3\CMS\Core\DataHandling\SlugHelper\isUniqueInTable
‪isUniqueInTable(string $slug, RecordState $state)
Definition: SlugHelper.php:321
‪TYPO3\CMS\Core\DataHandling\SlugHelper\generate
‪generate(array $recordData, int $pid)
Definition: SlugHelper.php:154
‪TYPO3\CMS\Core\DataHandling\SlugHelper\$workspaceId
‪int $workspaceId
Definition: SlugHelper.php:54
‪TYPO3\CMS\Core\DataHandling\Model\RecordStateFactory
Definition: RecordStateFactory.php:26
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:69
‪TYPO3\CMS\Core\DataHandling\SlugHelper\$fieldName
‪string $fieldName
Definition: SlugHelper.php:50
‪TYPO3\CMS\Core\DataHandling\SlugHelper\buildSlugForUniqueInPid
‪buildSlugForUniqueInPid(string $slug, RecordState $state)
Definition: SlugHelper.php:393
‪TYPO3\CMS\Core\DataHandling\SlugHelper\applySlugConstraint
‪applySlugConstraint(QueryBuilder $queryBuilder, string $slug)
Definition: SlugHelper.php:485
‪TYPO3\CMS\Core\DataHandling\SlugHelper
Definition: SlugHelper.php:43
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SPACER
‪const DOKTYPE_SPACER
Definition: PageRepository.php:103
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Core\DataHandling\SlugHelper\createPreparedQueryBuilder
‪createPreparedQueryBuilder()
Definition: SlugHelper.php:409
‪TYPO3\CMS\Core\DataHandling\SlugHelper\$tableName
‪string $tableName
Definition: SlugHelper.php:46
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SYSFOLDER
‪const DOKTYPE_SYSFOLDER
Definition: PageRepository.php:104
‪TYPO3\CMS\Core\DataHandling\SlugHelper\resolveVersionOverlays
‪resolveVersionOverlays(array $records)
Definition: SlugHelper.php:536
‪TYPO3\CMS\Core\DataHandling\SlugHelper\isUniqueInPid
‪isUniqueInPid(string $slug, RecordState $state)
Definition: SlugHelper.php:232
‪TYPO3\CMS\Core\DataHandling\SlugHelper\extract
‪extract(string $slug)
Definition: SlugHelper.php:142
‪TYPO3\CMS\Core\DataHandling\Model\RecordState\resolveNodeIdentifier
‪resolveNodeIdentifier()
Definition: RecordState.php:134
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Core\DataHandling\Model\RecordState
Definition: RecordState.php:32
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\DataHandling\SlugHelper\buildSlugForUniqueInSite
‪buildSlugForUniqueInSite(string $slug, RecordState $state)
Definition: SlugHelper.php:383
‪TYPO3\CMS\Core\DataHandling\SlugHelper\$prependSlashInSlug
‪bool $prependSlashInSlug
Definition: SlugHelper.php:70
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Core\DataHandling\Model\RecordState\getContext
‪getContext()
Definition: RecordState.php:60
‪TYPO3\CMS\Core\DataHandling\Model\RecordState\resolveNodeAggregateIdentifier
‪resolveNodeAggregateIdentifier()
Definition: RecordState.php:157
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Core\DataHandling\SlugHelper\$configuration
‪array $configuration
Definition: SlugHelper.php:58
‪TYPO3\CMS\Core\DataHandling\SlugHelper\sanitize
‪sanitize(string $slug)
Definition: SlugHelper.php:99
‪TYPO3\CMS\Core\DataHandling\SlugHelper\applyWorkspaceConstraint
‪applyWorkspaceConstraint(QueryBuilder $queryBuilder, RecordState $state)
Definition: SlugHelper.php:435
‪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\Core\Utility\StringUtility
Definition: StringUtility.php:24
‪TYPO3\CMS\Core\DataHandling\SlugHelper\resolveParentPageRecord
‪resolveParentPageRecord(int $pid, int $languageId)
Definition: SlugHelper.php:565
‪TYPO3\CMS\Core\DataHandling\SlugHelper\__construct
‪__construct(string $tableName, string $fieldName, array $configuration, int $workspaceId=0)
Definition: SlugHelper.php:80
‪TYPO3\CMS\Core\DataHandling\Model\RecordStateFactory\forName
‪static forName(string $name)
Definition: RecordStateFactory.php:29
‪TYPO3\CMS\Core\DataHandling\SlugHelper\applyPageIdConstraint
‪applyPageIdConstraint(QueryBuilder $queryBuilder, int $pageId)
Definition: SlugHelper.php:495
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode(string $delim, string $string, bool $removeEmptyValues=false, int $limit=0)
Definition: GeneralUtility.php:822
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static getUniqueId(string $prefix='')
Definition: StringUtility.php:57
‪TYPO3\CMS\Core\DataHandling\SlugHelper\buildSlug
‪buildSlug(string $slug, RecordState $state, callable $isUnique)
Definition: SlugHelper.php:358
‪TYPO3\CMS\Core\DataHandling\SlugHelper\flushRootLineCaches
‪flushRootLineCaches()
Definition: SlugHelper.php:344
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39