baseCacheIdentifier; $dataMap = $this->firstLevelCache->get($cacheIdentifier); if ($dataMap instanceof DataMap) { return $dataMap; } $dataMap = $this->secondLevelCache->get($cacheIdentifier); if ($dataMap instanceof DataMap) { $this->firstLevelCache->set($cacheIdentifier, $dataMap); return $dataMap; } $dataMap = $this->buildDataMapInternal($className); $this->firstLevelCache->set($cacheIdentifier, $dataMap); $this->secondLevelCache->set($cacheIdentifier, $dataMap); return $dataMap; } /** * Builds a data map by adding column maps for all the configured columns in the $TCA. * It also resolves the type of values the column is holding and the typo of relation the column * represents. * * @param string $className The class name you want to fetch the Data Map for * @throws InvalidClassException */ protected function buildDataMapInternal(string $className): DataMap { if (!class_exists($className)) { throw new InvalidClassException( 'Could not find class definition for name "' . $className . '". This could be caused by a mis-spelling of the class name in the class definition.', 1476045117 ); } $recordType = null; $subclasses = []; $tableName = $this->resolveTableName($className); $fieldNameToPropertyNameMapping = []; if ($this->classesConfiguration->hasClass($className)) { $classSettings = $this->classesConfiguration->getConfigurationFor($className); $subclasses = $this->classesConfiguration->getSubClasses($className); if (isset($classSettings['recordType']) && $classSettings['recordType'] !== '') { $recordType = (string)$classSettings['recordType']; } if (isset($classSettings['tableName']) && $classSettings['tableName'] !== '') { $tableName = $classSettings['tableName']; } foreach ($classSettings['properties'] ?? [] as $propertyName => $propertyDefinition) { $fieldNameToPropertyNameMapping[$propertyDefinition['fieldName']] = $propertyName; } } $schema = null; $languageCapability = null; $columnMaps = []; if ($this->tcaSchemaFactory->has($tableName)) { $schema = $this->tcaSchemaFactory->get($tableName); if ($schema->hasCapability(TcaSchemaCapability::Language)) { $languageCapability = $schema->getCapability(TcaSchemaCapability::Language); } foreach ($schema->getFields() as $columnName => $columnDefinition) { $propertyName = $fieldNameToPropertyNameMapping[$columnName] ?? GeneralUtility::underscoredToLowerCamelCase($columnName); $columnMaps[$propertyName] = $this->columnMapFactory->create($columnDefinition, $propertyName, $className); } } return new DataMap( className: $className, tableName: $tableName, recordType: $recordType, subclasses: $subclasses, columnMaps: $columnMaps, languageIdColumnName: $languageCapability?->getLanguageField()->getName(), translationOriginColumnName: $languageCapability?->getTranslationOriginPointerField()->getName(), translationOriginDiffSourceName: $languageCapability?->hasDiffSourceField() ? $languageCapability->getDiffSourceField()->getName() : null, modificationDateColumnName: $schema?->hasCapability(TcaSchemaCapability::UpdatedAt) ? (string)$schema->getCapability(TcaSchemaCapability::UpdatedAt) : null, creationDateColumnName: $schema?->hasCapability(TcaSchemaCapability::CreatedAt) ? (string)$schema->getCapability(TcaSchemaCapability::CreatedAt) : null, deletedFlagColumnName: $schema?->hasCapability(TcaSchemaCapability::SoftDelete) ? (string)$schema->getCapability(TcaSchemaCapability::SoftDelete) : null, disabledFlagColumnName: $schema?->hasCapability(TcaSchemaCapability::RestrictionDisabledField) ? (string)$schema->getCapability(TcaSchemaCapability::RestrictionDisabledField) : null, startTimeColumnName: $schema?->hasCapability(TcaSchemaCapability::RestrictionStartTime) ? (string)$schema->getCapability(TcaSchemaCapability::RestrictionStartTime) : null, endTimeColumnName: $schema?->hasCapability(TcaSchemaCapability::RestrictionEndTime) ? (string)$schema->getCapability(TcaSchemaCapability::RestrictionEndTime) : null, frontendUserGroupColumnName: $schema?->hasCapability(TcaSchemaCapability::RestrictionUserGroup) ? (string)$schema->getCapability(TcaSchemaCapability::RestrictionUserGroup) : null, // @todo Check how to resolve foreign table types properly - if possible at all in this scenario recordTypeColumnName: $schema?->supportsSubSchema() && !$schema->getSubSchemaTypeInformation()->isPointerToForeignFieldInForeignSchema() ? $schema->getSubSchemaTypeInformation()->getFieldName() : null, // @todo We should remove DataMap in order to use TcaSchema directly rootLevel: (bool)($schema?->getCapability(TcaSchemaCapability::RestrictionRootLevel)->getRootLevelType()), ); } /** * Resolve the table name for the given class name */ protected function resolveTableName(string $className): string { $className = ltrim($className, '\\'); $classNameParts = explode('\\', $className); // Skip vendor and product name for core classes if (str_starts_with($className, 'TYPO3\\CMS\\')) { $classPartsToSkip = 2; } else { $classPartsToSkip = 1; } return 'tx_' . strtolower(implode('_', array_slice($classNameParts, $classPartsToSkip))); } }