Skip to content

[BUG] $_GET['id'] global mutation in createFromPageId() breaks FlexForm section container AJAX calls #183

Description

@raf-ch

Environment

  • TYPO3: 12.4.44
  • content_defender: 3.5.3
  • DCE (t3/dce): 3.3.0
  • PHP: 8.2

Description

When adding an element to a DCE FlexForm repeater (section container) via the AJAX endpoint /record/flex/containeradd, a 500 error is thrown:

InvalidArgumentException #1437991120: uid is already set to 1 and does not start with NEW for a "new" command
in DatabaseUniqueUidNewRow.php line 45

This worked correctly with TYPO3 12.4.32 and breaks with TYPO3 12.4.44.

Root cause

In BackendLayoutConfiguration::createFromPageId(), there is a known hack (documented with a // TODO comment) that sets $_GET['id'] globally:

// TODO: Mitigate a problem in \TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher::determinePageId
// @see: https://github.com/IchHabRecht/content_defender/issues/91
if (($_POST['id'] ?? $_GET['id'] ?? null) === null) {
    $_GET['id'] = $pageId;
}

During the containeradd AJAX call, this method is called with pageId=0 (because effectivePid=0 at that point in the FormEngine compilation chain). This sets $_GET['id'] = 0 globally, which corrupts the FormEngine compilation and causes databaseRow['uid'] to resolve to 1 instead of the real record UID.

This then cascades into:

  • Wrong effectivePid (0 instead of real page pid)
  • Wrong parentPageRow (null)
  • Permission check fails for non-admin users (AccessDeniedRootNodeException)
  • uid is already set to 1 exception for new records

Proposed fix

Save and restore $_GET['id'] around the call, so it doesn't leak globally:

$previousGetId = $_GET['id'] ?? null;
if (($_POST['id'] ?? $_GET['id'] ?? null) === null) {
    $_GET['id'] = $pageId;
}
$backendLayoutView = GeneralUtility::makeInstance(BackendLayoutView::class);
$backendLayout = $backendLayoutView->getSelectedBackendLayout($pageId);
if (null === $backendLayout) {
    $backendLayout = [
        'config' => '',
    ];
}
// Restore $_GET['id'] to avoid corrupting other processes (e.g. FormFlexAjaxController)
if ($previousGetId === null) {
    unset($_GET['id']);
} else {
    $_GET['id'] = $previousGetId;
}
return new self($backendLayout);

This fix alone is unfortunately not sufficient with TYPO3 12.4.44 — additional patches to DatabaseEditRow and FormFlexAjaxController were also needed in our case. But fixing the global $_GET['id'] mutation is the correct first step.

Related issues

Workaround

Apply the patch above manually to Classes/BackendLayout/BackendLayoutConfiguration.php.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions