95 lines
3.7 KiB
PHP
95 lines
3.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* 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!
|
|
*/
|
|
|
|
namespace TYPO3\CMS\Core\Schema;
|
|
|
|
use TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidDataStructureException;
|
|
use TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidIdentifierException;
|
|
use TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidTcaSchemaException;
|
|
use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
|
|
|
|
/**
|
|
* Low-level API to parse TCA to find field types which should be processed, as they contain
|
|
* a relation.
|
|
*
|
|
* This also parses ALL flexforms available, that's why it juggles through all FlexForm
|
|
* fields and parses the FlexForms as well.
|
|
*
|
|
* Everything is stored in a simple "RelationMap" object with an internal array structure.
|
|
*
|
|
* @internal not part of TYPO3 API as it should not be exposed, although this is really cool and powerful.
|
|
*/
|
|
final readonly class RelationMapBuilder
|
|
{
|
|
public function __construct(
|
|
private FlexFormTools $flexFormTools
|
|
) {}
|
|
|
|
public function buildFromStructure(array $tca): RelationMap
|
|
{
|
|
$relationMap = new RelationMap();
|
|
foreach ($tca as $table => $tableConfig) {
|
|
// What fields can have a relational connection to other tables?
|
|
foreach ($tableConfig['columns'] ?? [] as $fieldName => $fieldConfig) {
|
|
$fieldConfig = $fieldConfig['config'] ?? null;
|
|
if (!in_array($fieldConfig['type'] ?? '', ['select', 'group', 'inline', 'file', 'category', 'flex'], true)) {
|
|
continue;
|
|
}
|
|
|
|
if ($fieldConfig['type'] === 'flex') {
|
|
$this->addRelationsForFlexFieldToRelationMap($table, $tableConfig, $fieldName, $relationMap);
|
|
} else {
|
|
$relationMap->add($table, $fieldName, $fieldConfig);
|
|
}
|
|
}
|
|
}
|
|
return $relationMap;
|
|
}
|
|
|
|
/**
|
|
* Adds relations for a flex field to the relation map.
|
|
* Note: Inside a section, it is not possible to add a field with a relation (type 'inline', 'file', 'folder', 'group', 'category').
|
|
* See TcaFlexProcess class for details.
|
|
*/
|
|
private function addRelationsForFlexFieldToRelationMap(string $tableName, array $tableConfig, string $fieldName, RelationMap $relationMap): void
|
|
{
|
|
foreach (array_merge(['default'], array_keys($tableConfig['types'] ?? [])) as $recordType) {
|
|
try {
|
|
$dataStructure = $this->flexFormTools->parseDataStructureByIdentifier(json_encode([
|
|
'type' => 'tca',
|
|
'tableName' => $tableName,
|
|
'fieldName' => $fieldName,
|
|
'dataStructureKey' => $recordType,
|
|
]), $tableConfig);
|
|
} catch (InvalidTcaSchemaException|InvalidIdentifierException|InvalidDataStructureException) {
|
|
// Skip default on error
|
|
continue;
|
|
}
|
|
|
|
if (!is_array($dataStructure['sheets'] ?? null)) {
|
|
continue;
|
|
}
|
|
foreach ($dataStructure['sheets'] as $sheetIdentifier => $sheet) {
|
|
foreach ($sheet['ROOT']['el'] as $flexFieldName => $flexFieldConfig) {
|
|
$fieldIdentifier = $sheetIdentifier . '/' . $flexFieldName;
|
|
$relationMap->add($tableName, $fieldName, $flexFieldConfig['config'] ?? [], $fieldIdentifier);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|