Commit 06c67dc4 authored by Oliver Hader's avatar Oliver Hader Committed by Benni Mack
Browse files

[BUGFIX] Ensure that slugs are always calculated in DataHandler

When NOT using FormEngine to create a new page (e.g. in the pagetree
or via the "Create multiple pages" wizard), so just using DataHandler
magic is uttermost critical that a slug is always created, to ensure
the "uniqueInSite" functionality, and to access a page, even though
the page was created after the upgrade wizard has run.

Resolves: #86050
Resolves: #85937
Releases: master
Change-Id: I9eff3385c369a04a6f5a33d0b840b6a2b698891c
Reviewed-on: https://review.typo3.org/58098


Tested-by: default avatarTYPO3com <no-reply@typo3.com>
Reviewed-by: Susanne Moog's avatarSusanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog's avatarSusanne Moog <susanne.moog@typo3.org>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent f250a9c9
......@@ -966,6 +966,7 @@ class DataHandler implements LoggerAwareInterface
$hookObjectsArr[] = $hookObject;
}
// Pre-process data-map and synchronize localization states
$this->datamap = GeneralUtility::makeInstance(SlugEnricher::class)->enrichDataMap($this->datamap);
$this->datamap = DataMapProcessor::instance($this->datamap, $this->BE_USER)->process();
// Organize tables so that the pages-table is always processed first. This is required if you want to make sure that content pointing to a new page will be created.
$orderOfTables = [];
......@@ -1931,6 +1932,7 @@ class DataHandler implements LoggerAwareInterface
* @param string $field Field name
* @param array $incomingFieldArray the fields being explicitly set by the outside (unlike $fieldArray) for the record
* @return array $res The result array. The processed value (if any!) is set in the "value" key.
* @see SlugEnricher, SlugHelper
*/
protected function checkValueForSlug(string $value, array $tcaFieldConf, string $table, $id, int $realPid, string $field, array $incomingFieldArray = []): array
{
......@@ -1938,7 +1940,7 @@ class DataHandler implements LoggerAwareInterface
$helper = GeneralUtility::makeInstance(SlugHelper::class, $table, $field, $tcaFieldConf, $workspaceId);
$fullRecord = array_replace_recursive($this->checkValue_currentRecord, $incomingFieldArray ?? []);
// Generate a value if there is none, otherwise ensure that all characters are cleaned up
if (empty($value)) {
if ($value === '') {
$value = $helper->generate($fullRecord, $realPid);
} else {
$value = $helper->sanitize($value);
......
<?php
namespace TYPO3\CMS\Core\DataHandling;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Utility\MathUtility;
/**
* New records that are capable of handling slugs (TCA type 'slug'), always
* require the field value to be set in order to run through the validation
* process to create a new slug. Fields having `null` as value are ignored
* and can be used to by-pass implicit slug initialization.
*
* @see DataHandler::fillInFieldArray(), DataHandler::checkValueForSlug()
*/
class SlugEnricher
{
/**
* @var array
*/
protected $slugFieldNamesPerTable = [];
/**
* @param array $dataMap
* @return array
*/
public function enrichDataMap(array $dataMap): array
{
foreach ($dataMap as $tableName => &$tableDataMap) {
$slugFieldNames = $this->resolveSlugFieldNames($tableName);
if (empty($slugFieldNames)) {
continue;
}
foreach ($tableDataMap as $identifier => &$fieldValues) {
if (MathUtility::canBeInterpretedAsInteger($identifier)) {
continue;
}
$fieldValues = $this->enrichUndefinedSlugFieldNames(
$slugFieldNames,
$fieldValues
);
}
}
return $dataMap;
}
/**
* @param array $slugFieldNames
* @param array $fieldValues
* @return array
*/
protected function enrichUndefinedSlugFieldNames(array $slugFieldNames, array $fieldValues): array
{
if (empty($slugFieldNames)) {
return [];
}
$undefinedSlugFieldNames = array_diff(
$slugFieldNames,
array_keys($fieldValues)
);
if (empty($undefinedSlugFieldNames)) {
return $fieldValues;
}
return array_merge(
$fieldValues,
array_fill_keys(
$undefinedSlugFieldNames,
''
)
);
}
/**
* @param string $tableName
* @return string[]
*/
protected function resolveSlugFieldNames(string $tableName): array
{
if (isset($this->slugFieldNamesPerTable[$tableName])) {
return $this->slugFieldNamesPerTable[$tableName];
}
return $this->slugFieldNamesPerTable[$tableName] = array_keys(
array_filter(
$GLOBALS['TCA'][$tableName]['columns'] ?? [],
function (array $settings) {
return ($settings['config']['type'] ?? null) === 'slug';
}
)
);
}
}
......@@ -340,6 +340,10 @@ class SlugHelper
$queryBuilder->expr()->in(
't3ver_wsid',
$queryBuilder->createNamedParameter($workspaceIds, Connection::PARAM_INT_ARRAY)
),
$queryBuilder->expr()->in(
't3ver_state',
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
)
);
}
......
......@@ -92,7 +92,7 @@ class PseudoSiteFinder
'domains' => $domainRecords,
'languages' => $allLanguages
]);
$this->pseudoSites[$rootPageId] = $site;
$this->pseudoSites[(int)$rootPageId] = $site;
}
// Now lets an empty Pseudo-Site for visiting things on pid=0
......@@ -135,7 +135,7 @@ class PseudoSiteFinder
->orderBy('sorting')
->execute();
while ($row = $statement->fetch()) {
$uid = $row['uid'];
$uid = (int)$row['uid'];
$languageRecords[$uid] = [
'languageId' => $uid,
'title' => $row['title'],
......
......@@ -153,7 +153,7 @@ class LegacyDomainResolver implements SingletonInterface
// walk the rootline downwards from the target page
// to the root page, until a domain record is found
foreach ($rootLine as $pageInRootline) {
$pidInRootline = $pageInRootline['uid'];
$pidInRootline = (int)$pageInRootline['uid'];
if (empty($this->groupedDomainsPerPage[$pidInRootline])) {
continue;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment