From bb84452d02675cfa15afd3a0e13aca7ac7164607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=84=B3ichiel=20=E2=84=9Boos?= <michiel@michielroos.com> Date: Wed, 8 Nov 2017 21:09:43 +0100 Subject: [PATCH] [BUGFIX] Set correct PID for file references on new pages Allow inline parent UID to have a "NEW..." placeholder value. Resolves: #82931 Releases: master, 9.5, 8.7 Change-Id: I1714160d14d226a02663568947ed9525ad07d347 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/54598 Tested-by: Markus Klein <markus.klein@typo3.org> Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Steffen Frese <steffenf14@gmail.com> Tested-by: Sascha Rademacher <sascha.rademacher+typo3@gmail.com> Tested-by: Benni Mack <benni@typo3.org> Reviewed-by: Markus Klein <markus.klein@typo3.org> Reviewed-by: Steffen Frese <steffenf14@gmail.com> Reviewed-by: Sascha Rademacher <sascha.rademacher+typo3@gmail.com> Reviewed-by: Benni Mack <benni@typo3.org> --- .../Controller/FormInlineAjaxController.php | 14 +++++++++---- .../backend/Classes/Form/FormDataCompiler.php | 12 +++++++---- .../Form/FormDataProvider/SiteTcaInline.php | 20 +++++++++++++------ .../Form/FormDataProvider/TcaInline.php | 20 +++++++++++++------ .../Classes/Form/InlineStackProcessor.php | 2 +- 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/typo3/sysext/backend/Classes/Controller/FormInlineAjaxController.php b/typo3/sysext/backend/Classes/Controller/FormInlineAjaxController.php index 54959c00bf79..770b01d3c1f8 100644 --- a/typo3/sysext/backend/Classes/Controller/FormInlineAjaxController.php +++ b/typo3/sysext/backend/Classes/Controller/FormInlineAjaxController.php @@ -48,6 +48,12 @@ class FormInlineAjaxController extends AbstractFormEngineAjaxController $domObjectId = $ajaxArguments[0]; $inlineFirstPid = $this->getInlineFirstPidFromDomObjectId($domObjectId); + if (!MathUtility::canBeInterpretedAsInteger($inlineFirstPid) && strpos($inlineFirstPid, 'NEW') !== 0) { + throw new \RuntimeException( + 'inlineFirstPid should either be an integer or a "NEW..." string', + 1521220491 + ); + } $childChildUid = null; if (isset($ajaxArguments[1]) && MathUtility::canBeInterpretedAsInteger($ajaxArguments[1])) { $childChildUid = (int)$ajaxArguments[1]; @@ -70,7 +76,7 @@ class FormInlineAjaxController extends AbstractFormEngineAjaxController $childVanillaUid = -1 * abs((int)$child['uid']); } else { // Else inline first Pid is the storage pid of new inline records - $childVanillaUid = (int)$inlineFirstPid; + $childVanillaUid = $inlineFirstPid; } $childTableName = $parentConfig['foreign_table']; @@ -118,17 +124,17 @@ class FormInlineAjaxController extends AbstractFormEngineAjaxController $formDataCompilerInput = [ 'command' => 'new', 'tableName' => $childData['processedTca']['columns'][$parentConfig['foreign_selector']]['config']['foreign_table'], - 'vanillaUid' => (int)$inlineFirstPid, + 'vanillaUid' => $inlineFirstPid, 'isInlineChild' => true, 'isInlineAjaxOpeningContext' => true, 'inlineStructure' => $inlineStackProcessor->getStructure(), - 'inlineFirstPid' => (int)$inlineFirstPid, + 'inlineFirstPid' => $inlineFirstPid, ]; $childData['combinationChild'] = $formDataCompiler->compile($formDataCompilerInput); } } - $childData['inlineParentUid'] = (int)$parent['uid']; + $childData['inlineParentUid'] = $parent['uid']; $childData['renderType'] = 'inlineRecordContainer'; $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class); $childResult = $nodeFactory->create($childData)->render(); diff --git a/typo3/sysext/backend/Classes/Form/FormDataCompiler.php b/typo3/sysext/backend/Classes/Form/FormDataCompiler.php index 1fdd51a6a49f..7d4532dd893e 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataCompiler.php +++ b/typo3/sysext/backend/Classes/Form/FormDataCompiler.php @@ -14,6 +14,8 @@ namespace TYPO3\CMS\Backend\Form; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Utility\MathUtility; + /** * Create and return a defined array of data ready to be used by the * container / element render part of FormEngine @@ -82,8 +84,8 @@ class FormDataCompiler } } if ($dataKey === 'vanillaUid') { - if (!is_int($dataValue)) { - throw new \InvalidArgumentException('$vanillaUid is not an integer', 1437654247); + if (!MathUtility::canBeInterpretedAsInteger($dataValue) && strpos($dataValue, 'NEW') !== 0) { + throw new \InvalidArgumentException('$vanillaUid is not an integer or "NEW..." string ID', 1437654247); } if (isset($initialData['command']) && $initialData['command'] === 'edit' && $dataValue < 0) { throw new \InvalidArgumentException('Negative $vanillaUid is not supported with $command="edit', 1437654332); @@ -140,13 +142,14 @@ class FormDataCompiler 'command' => '', // Table name of the handled row 'tableName' => '', - // Forced integer of otherwise not changed uid of the record, meaning of value depends on context (new / edit) + // Not changed uid of the record, meaning of value depends on context (new / edit) // * If $command is "edit" // ** $vanillaUid is a positive integer > 0 pointing to the record in the table // * If $command is "new": // ** If $vanillaUid > 0, it is the uid of a page the record should be added at // ** If $vanillaUid < 0, it is the uid of a record in the same table after which the new record should be added // ** If $vanillaUid = 0, a new record is added on page 0 + // ** If $vanillaUid = "NEW..." Id of a parent page record if an inline child is added to a not yet persisted page 'vanillaUid' => 0, // Url to return to 'returnUrl' => null, @@ -238,7 +241,8 @@ class FormDataCompiler 'inlineExpandCollapseStateArray' => [], // The "entry" pid for inline records. Nested inline records can potentially hang around on different // pid's, but the entry pid is needed for AJAX calls, so that they would know where the action takes - // place on the page structure. + // place on the page structure. This is usually an int, but can be a "NEW..." string if an inline relation + // is added to a currently being created page. 'inlineFirstPid' => null, // The "config" section of an inline parent, prepared and sanitized by TcaInlineConfiguration provider 'inlineParentConfig' => [], diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/SiteTcaInline.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/SiteTcaInline.php index 1a808f6ddd5c..9b2af4a76469 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataProvider/SiteTcaInline.php +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/SiteTcaInline.php @@ -26,6 +26,7 @@ use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\MathUtility; /** * Special data provider for the sites configuration module. @@ -87,17 +88,24 @@ class SiteTcaInline extends AbstractDatabaseRecordProvider implements FormDataPr if ($table === 'pages') { $liveVersionId = BackendUtility::getLiveVersionIdOfRecord('pages', $row['uid']); $pid = $liveVersionId ?? $row['uid']; - } elseif ($row['pid'] < 0) { + } elseif (($row['pid'] ?? 0) < 0) { $prevRec = BackendUtility::getRecord($table, abs($row['pid'])); $pid = $prevRec['pid']; } else { - $pid = $row['pid']; + $pid = $row['pid'] ?? 0; } - $pageRecord = BackendUtility::getRecord('pages', $pid); - if ((int)$pageRecord[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']] > 0) { - $pid = (int)$pageRecord[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']]; + if (MathUtility::canBeInterpretedAsInteger($pid)) { + $pageRecord = BackendUtility::getRecord('pages', (int)$pid); + if ((int)$pageRecord[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']] > 0) { + $pid = (int)$pageRecord[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']]; + } + } elseif (strpos($pid, 'NEW') !== 0) { + throw new \RuntimeException( + 'inlineFirstPid should either be an integer or a "NEW..." string', + 1521220141 + ); } - $result['inlineFirstPid'] = (int)$pid; + $result['inlineFirstPid'] = $pid; } return $result; } diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php index 14a57ce70f60..ce96bee919a9 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php @@ -27,6 +27,7 @@ use TYPO3\CMS\Core\Localization\LanguageService; use TYPO3\CMS\Core\Messaging\FlashMessage; use TYPO3\CMS\Core\Messaging\FlashMessageService; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Core\Versioning\VersionState; /** @@ -100,17 +101,24 @@ class TcaInline extends AbstractDatabaseRecordProvider implements FormDataProvid if ($table === 'pages') { $liveVersionId = BackendUtility::getLiveVersionIdOfRecord('pages', $row['uid']); $pid = $liveVersionId ?? $row['uid']; - } elseif ($row['pid'] < 0) { + } elseif (($row['pid'] ?? 0) < 0) { $prevRec = BackendUtility::getRecord($table, abs($row['pid'])); $pid = $prevRec['pid']; } else { - $pid = $row['pid']; + $pid = $row['pid'] ?? 0; } - $pageRecord = BackendUtility::getRecord('pages', $pid); - if ((int)$pageRecord[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']] > 0) { - $pid = (int)$pageRecord[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']]; + if (MathUtility::canBeInterpretedAsInteger($pid)) { + $pageRecord = BackendUtility::getRecord('pages', (int)$pid); + if ((int)$pageRecord[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']] > 0) { + $pid = (int)$pageRecord[$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']]; + } + } elseif (strpos($pid, 'NEW') !== 0) { + throw new \RuntimeException( + 'inlineFirstPid should either be an integer or a "NEW..." string', + 1521220142 + ); } - $result['inlineFirstPid'] = (int)$pid; + $result['inlineFirstPid'] = $pid; } return $result; } diff --git a/typo3/sysext/backend/Classes/Form/InlineStackProcessor.php b/typo3/sysext/backend/Classes/Form/InlineStackProcessor.php index 315ae2f1d47e..2f2dbf8c7480 100644 --- a/typo3/sysext/backend/Classes/Form/InlineStackProcessor.php +++ b/typo3/sysext/backend/Classes/Form/InlineStackProcessor.php @@ -158,7 +158,7 @@ class InlineStackProcessor /** * DOM object-id for this inline level * - * @param int $inlineFirstPid Pid of top level inline element storage + * @param int|string $inlineFirstPid Pid of top level inline element storage or "NEW..." * @return string */ public function getCurrentStructureDomObjectIdPrefix($inlineFirstPid) -- GitLab