addInlineFirstPid($result); foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) { if (!$this->isInlineField($fieldConfig)) { continue; } $childTableName = $fieldConfig['config']['foreign_table'] ?? ''; if (!in_array($childTableName, ['site_errorhandling', 'site_route', 'site_base_variant'], true)) { throw new \RuntimeException('Inline relation to other tables not implemented', 1522494737); } $result['processedTca']['columns'][$fieldName]['children'] = []; $result = $this->resolveSiteRelatedChildren($result, $fieldName); if (!empty($result['processedTca']['columns'][$fieldName]['config']['selectorOrUniqueConfiguration'])) { throw new \RuntimeException('selectorOrUniqueConfiguration not implemented in sites module', 1624313533); } } return $result; } /** * Is column of type "inline" */ protected function isInlineField(array $fieldConfig): bool { return !empty($fieldConfig['config']['type']) && $fieldConfig['config']['type'] === 'inline'; } /** * 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. * * @param array $result Incoming result * @return array Modified result * @todo: Find out when and if this is different from 'effectivePid' */ protected function addInlineFirstPid(array $result): array { if ($result['inlineFirstPid'] === null) { $table = $result['tableName']; $row = $result['databaseRow']; // If the parent is a page, use the uid(!) of the (new?) page as pid for the child records: if ($table === 'pages') { $liveVersionId = BackendUtility::getLiveVersionIdOfRecord('pages', $row['uid']); $pid = $liveVersionId ?? $row['uid']; } elseif (($row['pid'] ?? 0) < 0) { $prevRec = BackendUtility::getRecord($table, (int)abs($row['pid'])); $pid = $prevRec['pid']; } else { $pid = $row['pid'] ?? 0; } if (MathUtility::canBeInterpretedAsInteger($pid)) { $pageRecord = BackendUtility::getRecord('pages', (int)$pid); $pageSchema = $result['tcaSchemata']->has('pages') ? $result['tcaSchemata']->get('pages') : null; if ($pageSchema !== null && $pageSchema->hasCapability(TcaSchemaCapability::Language) && ($pageRecord[$pageSchema->getCapability(TcaSchemaCapability::Language)->getTranslationOriginPointerField()->getName()] ?? 0) > 0) { $pid = (int)$pageRecord[$pageSchema->getCapability(TcaSchemaCapability::Language)->getTranslationOriginPointerField()->getName()]; } } elseif (!str_starts_with($pid, 'NEW')) { throw new \RuntimeException( 'inlineFirstPid should either be an integer or a "NEW..." string', 1521220141 ); } $result['inlineFirstPid'] = $pid; } return $result; } /** * Substitute the value in databaseRow of this inline field with an array * that contains the databaseRows of currently connected records and some meta information. * * @param array $result Result array * @param string $fieldName Current handle field name * @return array Modified item array */ protected function resolveSiteRelatedChildren(array $result, string $fieldName): array { $connectedUids = []; if ($result['command'] === 'edit') { $siteConfigurationForPageUid = (int)$result['databaseRow']['rootPageId'][0]; try { $site = $this->siteFinder->getSiteByRootPageId($siteConfigurationForPageUid); } catch (SiteNotFoundException $e) { $site = null; } $siteConfiguration = $site ? $site->getConfiguration() : []; if (is_array($siteConfiguration[$fieldName] ?? false)) { $connectedUids = array_keys($siteConfiguration[$fieldName]); } } $result['databaseRow'][$fieldName] = implode(',', $connectedUids); if ($result['inlineCompileExistingChildren']) { foreach ($connectedUids as $uid) { if (!str_starts_with((string)$uid, 'NEW')) { $compiledChild = $this->compileChild($result, $fieldName, (int)$uid); $result['processedTca']['columns'][$fieldName]['children'][] = $compiledChild; } } } return $result; } /** * Compile a full child record * * @param array $result Result array of parent * @param string $parentFieldName Name of parent field * @param int $childUid Uid of child to compile * @return array Full result array */ protected function compileChild(array $result, string $parentFieldName, int $childUid): array { $parentConfig = $result['processedTca']['columns'][$parentFieldName]['config']; $childTableName = $parentConfig['foreign_table']; $inlineTopMostParent = $this->inlineStackProcessor->getStructureLevelFromStructure($result['inlineStructure'], 0); $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class); $formDataCompilerInput = [ 'request' => $result['request'], 'command' => 'edit', 'tableName' => $childTableName, 'vanillaUid' => $childUid, // Give incoming returnUrl down to children so they generate a returnUrl back to // the originally opening record, also see "originalReturnUrl" in inline container // and FormInlineAjaxController 'returnUrl' => $result['returnUrl'], 'isInlineChild' => true, 'inlineStructure' => $result['inlineStructure'], 'inlineExpandCollapseStateArray' => $result['inlineExpandCollapseStateArray'], 'inlineFirstPid' => $result['inlineFirstPid'], 'inlineParentConfig' => $parentConfig, // values of the current parent element // it is always a string either an id or new... 'inlineParentUid' => $result['databaseRow']['uid'], 'inlineParentTableName' => $result['tableName'], 'inlineParentFieldName' => $parentFieldName, // values of the top most parent element set on first level and not overridden on following levels 'inlineTopMostParentUid' => $result['inlineTopMostParentUid'] ?: ($inlineTopMostParent['uid'] ?? null), 'inlineTopMostParentTableName' => $result['inlineTopMostParentTableName'] ?: ($inlineTopMostParent['table'] ?? ''), 'inlineTopMostParentFieldName' => $result['inlineTopMostParentFieldName'] ?: ($inlineTopMostParent['field'] ?? ''), // pass through schemata as they are immutable once they are set 'tcaSchemata' => $result['tcaSchemata'], // pass through fullTca as it is immutable once set 'fullTca' => $result['fullTca'], ]; if (($parentConfig['foreign_selector'] ?? false) && ($parentConfig['appearance']['useCombination'] ?? false)) { throw new \RuntimeException('useCombination not implemented in sites module', 1522493097); } return $formDataCompiler->compile($formDataCompilerInput, GeneralUtility::makeInstance(SiteConfigurationDataGroup::class)); } }