diff --git a/.gitignore b/.gitignore index e90ff9790..99557ab3b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.bak /.buildpath /.cache /.idea/ diff --git a/Classes/Common/Helper.php b/Classes/Common/Helper.php index 8ca41ea5a..105ce2257 100644 --- a/Classes/Common/Helper.php +++ b/Classes/Common/Helper.php @@ -440,7 +440,7 @@ public static function getIndexNameFromUid(int $uid, string $table, int $pid = - if ( !$uid // NOTE: Only use tables that don't have too many entries! - || !in_array($table, ['tx_dlf_collections', 'tx_dlf_libraries', 'tx_dlf_metadata', 'tx_dlf_structures', 'tx_dlf_solrcores']) + || !in_array($table, ['tx_dlf_collections', 'tx_dlf_libraries', 'tx_dlf_metadata', 'tx_dlf_metadatasubentries','tx_dlf_structures', 'tx_dlf_solrcores']) ) { self::log('Invalid UID "' . $uid . '" or table "' . $table . '"', LOG_SEVERITY_ERROR); return ''; @@ -846,7 +846,7 @@ public static function translate(string $indexName, string $table, string $pid): // Check if we already got a translation. if (empty($labels[$table][$pid][$languageContentId][$indexName])) { // Check if this table is allowed for translation. - if (in_array($table, ['tx_dlf_collections', 'tx_dlf_libraries', 'tx_dlf_metadata', 'tx_dlf_structures'])) { + if (in_array($table, ['tx_dlf_collections', 'tx_dlf_libraries', 'tx_dlf_metadata', 'tx_dlf_metadatasubentries', 'tx_dlf_structures'])) { $additionalWhere = $queryBuilder->expr()->in($table . '.sys_language_uid', [-1, 0]); if ($languageContentId > 0) { $additionalWhere = $queryBuilder->expr()->andX( diff --git a/Classes/Common/Indexer.php b/Classes/Common/Indexer.php index dc6b194cd..78db6e3e1 100644 --- a/Classes/Common/Indexer.php +++ b/Classes/Common/Indexer.php @@ -516,6 +516,7 @@ private static function processMetadata($document, $metadata, &$solrDoc): array { $autocomplete = []; foreach ($metadata as $indexName => $data) { + // TODO: Include also subentries if available. if ( !empty($data) && substr($indexName, -8) !== '_sorting' @@ -551,6 +552,7 @@ private static function processMetadata($document, $metadata, &$solrDoc): array */ private static function addFaceting($doc, &$solrDoc): void { + // TODO: Include also subentries if available. foreach ($doc->metadataArray[$doc->toplevelId] as $indexName => $data) { if ( !empty($data) diff --git a/Classes/Common/MetsDocument.php b/Classes/Common/MetsDocument.php index a26b4e837..f1ae0971a 100644 --- a/Classes/Common/MetsDocument.php +++ b/Classes/Common/MetsDocument.php @@ -520,7 +520,6 @@ private function processMetadataSections(string $id, int $cPid, array $metadata) if (!$this->extractAndProcessMetadata($dmdId, $mdSectionType, $metadata, $cPid, $hasMetadataSection)) { continue; } - $hasMetadataSection[$mdSectionType] = true; } @@ -533,6 +532,66 @@ private function processMetadataSections(string $id, int $cPid, array $metadata) } } + /** + * @param array $allSubentries + * @param string $parentIndex + * @param \DOMNode $parentNode + * @return array|false + */ + private function getSubentries($allSubentries, string $parentIndex, \DOMNode $parentNode) + { + $domXPath = new \DOMXPath($parentNode->ownerDocument); + $this->registerNamespaces($domXPath); + $theseSubentries = []; + foreach ($allSubentries as $subentry) { + if ($subentry['parent_index_name'] == $parentIndex) { + $values = $domXPath->evaluate($subentry['xpath'], $parentNode); + if (!empty($subentry['xpath']) && ($values)) { + $theseSubentries = array_merge($theseSubentries, $this->getSubentryValue($values, $subentry)); + } + // Set default value if applicable. + if ( + empty($theseSubentries[$subentry['index_name']][0]) + && strlen($subentry['default_value']) > 0 + ) { + $theseSubentries[$subentry['index_name']] = [$subentry['default_value']]; + } + } + } + if (empty($theseSubentries)) { + return false; + } + return $theseSubentries; + } + + /** + * @param $values + * @param $subentry + * @return array + */ + private function getSubentryValue($values, $subentry) + { + $theseSubentries = []; + if ( + ($values instanceof \DOMNodeList + && $values->length > 0) || is_string($values) + ) { + if (is_string($values)) { + // if concat is used evaluate returns a string + $theseSubentries[$subentry['index_name']][] = trim($values); + } else { + foreach ($values as $value) { + if (!empty(trim((string) $value->nodeValue))) { + $theseSubentries[$subentry['index_name']][] = trim((string) $value->nodeValue); + } + } + } + } elseif (!($values instanceof \DOMNodeList)) { + $theseSubentries[$subentry['index_name']] = [trim((string) $values->nodeValue)]; + } + return $theseSubentries; + } + /** * Get logical unit type. * @@ -605,8 +664,13 @@ private function extractAndProcessMetadata(string $dmdId, string $mdSectionType, */ private function processAdditionalMetadata(array $additionalMetadata, \DOMXPath $domXPath, \DOMElement $domNode, array &$metadata): void { + $subentries = []; + if (isset($additionalMetadata['subentries'])) { + $subentries = $additionalMetadata['subentries']; + unset($additionalMetadata['subentries']); + } foreach ($additionalMetadata as $resArray) { - $this->setMetadataFieldValues($resArray, $domXPath, $domNode, $metadata); + $this->setMetadataFieldValues($resArray, $domXPath, $domNode, $metadata, $subentries); $this->setDefaultMetadataValue($resArray, $metadata); $this->setSortableMetadataValue($resArray, $domXPath, $domNode, $metadata); } @@ -621,17 +685,23 @@ private function processAdditionalMetadata(array $additionalMetadata, \DOMXPath * @param \DOMXPath $domXPath * @param \DOMElement $domNode * @param array $metadata + * @param array $subentryResults * * @return void */ - private function setMetadataFieldValues(array $resArray, \DOMXPath $domXPath, \DOMElement $domNode, array &$metadata): void + private function setMetadataFieldValues(array $resArray, \DOMXPath $domXPath, \DOMElement $domNode, array &$metadata, array $subentryResults): void { if ($resArray['format'] > 0 && !empty($resArray['xpath'])) { $values = $domXPath->evaluate($resArray['xpath'], $domNode); if ($values instanceof \DOMNodeList && $values->length > 0) { $metadata[$resArray['index_name']] = []; foreach ($values as $value) { - $metadata[$resArray['index_name']][] = trim((string) $value->nodeValue); + $subentries = $this->getSubentries($subentryResults, $resArray['index_name'], $value); + if ($subentries) { + $metadata[$resArray['index_name']][] = $subentries; + } else { + $metadata[$resArray['index_name']][] = trim((string) $value->nodeValue); + } } } elseif (!($values instanceof \DOMNodeList)) { $metadata[$resArray['index_name']] = [trim((string) $values)]; @@ -670,17 +740,25 @@ private function setDefaultMetadataValue(array $resArray, array &$metadata): voi */ private function setSortableMetadataValue(array $resArray, \DOMXPath $domXPath, \DOMElement $domNode, array &$metadata): void { - if (!empty($metadata[$resArray['index_name']]) && $resArray['is_sortable']) { + $indexName = $resArray['index_name']; + $currentMetadata = $metadata[$indexName][0]; + + if (!empty($metadata[$indexName]) && $resArray['is_sortable']) { if ($resArray['format'] > 0 && !empty($resArray['xpath_sorting'])) { $values = $domXPath->evaluate($resArray['xpath_sorting'], $domNode); if ($values instanceof \DOMNodeList && $values->length > 0) { - $metadata[$resArray['index_name'] . '_sorting'][0] = trim((string) $values->item(0)->nodeValue); + $metadata[$indexName . '_sorting'][0] = trim((string) $values->item(0)->nodeValue); } elseif (!($values instanceof \DOMNodeList)) { - $metadata[$resArray['index_name'] . '_sorting'][0] = trim((string) $values); + $metadata[$indexName . '_sorting'][0] = trim((string) $values); } } - if (empty($metadata[$resArray['index_name'] . '_sorting'][0])) { - $metadata[$resArray['index_name'] . '_sorting'][0] = $metadata[$resArray['index_name']][0]; + if (empty($metadata[$indexName . '_sorting'][0])) { + if (is_array($currentMetadata)) { + $sortingValue = implode(',', array_column($currentMetadata, 0)); + $metadata[$indexName . '_sorting'][0] = $sortingValue; + } else { + $metadata[$indexName . '_sorting'][0] = $currentMetadata; + } } } } @@ -768,6 +846,7 @@ private function getAdditionalMetadataFromDatabase(int $cPid, string $dmdId) ->getRestrictions() ->removeByType(HiddenRestriction::class); // Get all metadata with configured xpath and applicable format first. + // Exclude metadata with subentries, we will fetch them later. $resultWithFormat = $queryBuilder ->select( 'tx_dlf_metadata.index_name AS index_name', @@ -806,7 +885,7 @@ private function getAdditionalMetadataFromDatabase(int $cPid, string $dmdId) // Get all metadata without a format, but with a default value next. $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable('tx_dlf_metadata'); - // Get hidden records, too. + // Get hidden records, too. $queryBuilder ->getRestrictions() ->removeByType(HiddenRestriction::class); @@ -826,7 +905,52 @@ private function getAdditionalMetadataFromDatabase(int $cPid, string $dmdId) ) ->execute(); // Merge both result sets. - return array_merge($resultWithFormat->fetchAllAssociative(), $resultWithoutFormat->fetchAllAssociative()); + $allResults = array_merge($resultWithFormat->fetchAllAssociative(), $resultWithoutFormat->fetchAllAssociative()); + + // Get subentries separately. + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('tx_dlf_metadata'); + // Get hidden records, too. + $queryBuilder + ->getRestrictions() + ->removeByType(HiddenRestriction::class); + $subentries = $queryBuilder + ->select( + 'tx_dlf_subentries_joins.index_name AS index_name', + 'tx_dlf_metadata.index_name AS parent_index_name', + 'tx_dlf_subentries_joins.xpath AS xpath', + 'tx_dlf_subentries_joins.default_value AS default_value' + ) + ->from('tx_dlf_metadata') + ->innerJoin( + 'tx_dlf_metadata', + 'tx_dlf_metadataformat', + 'tx_dlf_metadataformat_joins', + $queryBuilder->expr()->eq( + 'tx_dlf_metadataformat_joins.parent_id', + 'tx_dlf_metadata.uid' + ) + ) + ->innerJoin( + 'tx_dlf_metadataformat_joins', + 'tx_dlf_metadatasubentries', + 'tx_dlf_subentries_joins', + $queryBuilder->expr()->eq( + 'tx_dlf_subentries_joins.parent_id', + 'tx_dlf_metadataformat_joins.uid' + ) + ) + ->where( + $queryBuilder->expr()->eq('tx_dlf_metadata.pid', (int) $cPid), + $queryBuilder->expr()->gt('tx_dlf_metadataformat_joins.subentries', 0), + $queryBuilder->expr()->eq('tx_dlf_subentries_joins.l18n_parent', 0), + $queryBuilder->expr()->eq('tx_dlf_subentries_joins.pid', (int) $cPid) + ) + ->orderBy('tx_dlf_subentries_joins.sorting') + ->execute(); + $subentriesResult = $subentries->fetchAll(); + + return array_merge($allResults, ['subentries' => $subentriesResult]); } /** diff --git a/Classes/Controller/MetadataController.php b/Classes/Controller/MetadataController.php index 7979d4011..d188acb22 100644 --- a/Classes/Controller/MetadataController.php +++ b/Classes/Controller/MetadataController.php @@ -171,6 +171,17 @@ protected function printMetadata(array $metadata): void foreach ($section as $name => $value) { // NOTE: Labels are to be escaped in Fluid template + $metadata[$i][$name] = is_array($value) + ? implode($this->settings['separator'], $value) + : $value; + + if ($metadata[$i][$name] === 'Array') { + $metadata[$i][$name] = []; + foreach ($value as $subKey => $subValue) { + $metadata[$i][$name][$subKey] = $subValue; + } + } + $this->parseMetadata($i, $name, $value, $metadata); if (is_array($metadata[$i][$name])) { @@ -372,6 +383,8 @@ private function parseMetadata(int $i, string $name, $value, array &$metadata) : foreach ($metadata[$i][$name] as &$langValue) { $langValue = Helper::getLanguageName($langValue); } + } elseif (!empty($value)) { + $metadata[$i][$name][0] = $metadata[$i][$name][0]; } } diff --git a/Classes/Domain/Model/MetadataFormat.php b/Classes/Domain/Model/MetadataFormat.php index 30157c429..ad40ec008 100644 --- a/Classes/Domain/Model/MetadataFormat.php +++ b/Classes/Domain/Model/MetadataFormat.php @@ -12,6 +12,8 @@ namespace Kitodo\Dlf\Domain\Model; +use TYPO3\CMS\Extbase\Annotation as Extbase; +use TYPO3\CMS\Extbase\Persistence\ObjectStorage; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; /** @@ -55,11 +57,36 @@ class MetadataFormat extends AbstractEntity protected $xpathSorting; /** + * Collection of ``tx_dlf_metadatasubentries`` specified with this metadata entry. + * + * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Kitodo\Dlf\Domain\Model\MetadataSubentry> + * @Extbase\ORM\Lazy + * @Extbase\ORM\Cascade("remove") + */ + protected $subentries; + + /** + * Whether or not the field is mandatory. Not used at the moment (originally planned to be used in METS validator). + * + * @var int * @access protected - * @var int Whether or not the field is mandatory. Not used at the moment (originally planned to be used in METS validator). */ protected $mandatory; + /** + * constructor + */ + public function __construct() + { + // Do not remove the next line: It would break the functionality + $this->initStorageObjects(); + } + + protected function initStorageObjects() + { + $this->subentries = new ObjectStorage(); + } + /** * @return int */ @@ -124,6 +151,40 @@ public function setXpathSorting(string $xpathSorting): void $this->xpathSorting = $xpathSorting; } + public function getSubentries() + { + return $this->subentries; + } + + public function setSubentries(ObjectStorage $subentries): void + { + $this->subentries = $subentries; + } + + /** + * Adds a Subentry + * + * @param \Kitodo\Dlf\Domain\Model\MetadataSubentry $subentry + * + * @return void + */ + public function addSubentry(MetadataSubentry $subentry) + { + $this->subentries->attach($subentry); + } + + /** + * Removes a Subentry + * + * @param \Kitodo\Dlf\Domain\Model\MetadataSubentry $subentryToRemove + * + * @return void + */ + public function removeSubentry(MetadataSubentry $subentryToRemove) + { + $this->subentries->detach($subentryToRemove); + } + /** * @return int */ diff --git a/Classes/Domain/Model/MetadataSubentry.php b/Classes/Domain/Model/MetadataSubentry.php new file mode 100644 index 000000000..030222ac5 --- /dev/null +++ b/Classes/Domain/Model/MetadataSubentry.php @@ -0,0 +1,179 @@ + + * + * This file is part of the Kitodo and TYPO3 projects. + * + * @license GNU General Public License version 3 or later. + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + */ + +namespace Kitodo\Dlf\Domain\Model; + +/** + * This specifies a way how a metadatum (``tx_dlf_metadata``) may be encoded in a specific data format (``tx_dlf_format``). + * + * For instance, the title of a document may be obtained from either the MODS + * title field, or from the TEIHDR caption. This is modeled as two ``tx_dlf_metadaformat`` + * that refer to the same ``tx_dlf_metadata`` but different ``tx_dlf_format``. + * + * This contains the xpath expressions on the model 'Metadata'. + * + * @package TYPO3 + * @subpackage dlf + * @access public + */ +class MetadataSubentry extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity +{ + /** + * @var \Kitodo\Dlf\Domain\Model\MetadataSubentry + */ + protected $l18nParent; + + /** + * @var int + */ + protected $sorting; + + /** + * @var string + */ + protected $label; + + /** + * @var string + */ + protected $indexName; + + /** + * XPath/JSONPath expression to extract the metadatum (relative to the data format root). + * TODO + * + * @var string + */ + protected $xpath; + + /** + * @var string + */ + protected $defaultValue; + + /** + * @var string + */ + protected $wrap; + + /** + * @return \Kitodo\Dlf\Domain\Model\MetadataSubentry + */ + public function getL18nParent(): MetadataSubentry + { + return $this->l18nParent; + } + + /** + * @param \Kitodo\Dlf\Domain\Model\MetadataSubentry $l18nParent + */ + public function setL18nParent(MetadataSubentry $l18nParent): void + { + $this->l18nParent = $l18nParent; + } + + /** + * @return int + */ + public function getSorting(): int + { + return $this->sorting; + } + + /** + * @param int $sorting + */ + public function setSorting(int $sorting): void + { + $this->sorting = $sorting; + } + + /** + * @return string + */ + public function getLabel(): string + { + return $this->label; + } + + /** + * @param string $label + */ + public function setLabel(string $label): void + { + $this->label = $label; + } + + /** + * @return string + */ + public function getIndexName(): string + { + return $this->indexName; + } + + /** + * @param string $indexName + */ + public function setIndexName(string $indexName): void + { + $this->indexName = $indexName; + } + + /** + * @return string + */ + public function getXpath(): string + { + return $this->xpath; + } + + /** + * @param string $xpath + */ + public function setXpath(string $xpath): void + { + $this->xpath = $xpath; + } + + /** + * @return string + */ + public function getDefaultValue(): string + { + return $this->defaultValue; + } + + /** + * @param string $defaultValue + */ + public function setDefaultValue(string $defaultValue): void + { + $this->defaultValue = $defaultValue; + } + + /** + * @return string + */ + public function getWrap(): string + { + return $this->wrap; + } + + /** + * @param string $wrap + */ + public function setWrap(string $wrap): void + { + $this->wrap = $wrap; + } +} diff --git a/Classes/Domain/Repository/MetadataSubentryRepository.php b/Classes/Domain/Repository/MetadataSubentryRepository.php new file mode 100644 index 000000000..e5c3d94e1 --- /dev/null +++ b/Classes/Domain/Repository/MetadataSubentryRepository.php @@ -0,0 +1,18 @@ + + * + * This file is part of the Kitodo and TYPO3 projects. + * + * @license GNU General Public License version 3 or later. + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + */ + +namespace Kitodo\Dlf\Domain\Repository; + +class MetadataSubentryRepository extends \TYPO3\CMS\Extbase\Persistence\Repository +{ + +} diff --git a/Classes/Hooks/DataHandler.php b/Classes/Hooks/DataHandler.php index cf2461210..c04a50050 100644 --- a/Classes/Hooks/DataHandler.php +++ b/Classes/Hooks/DataHandler.php @@ -87,6 +87,7 @@ public function processDatamap_postProcessFieldArray(string $status, string $tab } break; // Field post-processing for table "tx_dlf_metadata". + // TODO: Include also subentries if available. case 'tx_dlf_metadata': // Store field in index if it should appear in lists. if (!empty($fieldArray['is_listed'])) { diff --git a/Classes/ViewHelpers/IsArrayViewHelper.php b/Classes/ViewHelpers/IsArrayViewHelper.php new file mode 100644 index 000000000..450ea8604 --- /dev/null +++ b/Classes/ViewHelpers/IsArrayViewHelper.php @@ -0,0 +1,44 @@ + + * + * This file is part of the Kitodo and TYPO3 projects. + * + * @license GNU General Public License version 3 or later. + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + */ + +namespace Kitodo\Dlf\ViewHelpers; + +use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; +use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; + +/** + * Checks if the given subject is an array. + */ +class IsArrayViewHelper extends AbstractViewHelper +{ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('subject', 'string', 'The subject'); + } + + /** + * @return bool + */ + public static function renderStatic( + array $arguments, + \Closure $renderChildrenClosure, + RenderingContextInterface $renderingContext + ) { + $subject = $arguments['subject']; + if ($subject === null) { + $subject = $renderChildrenClosure(); + } + + return \is_array($subject); + } +} diff --git a/Configuration/Extbase/Persistence/Classes.php b/Configuration/Extbase/Persistence/Classes.php index 454c039a1..cb15374ff 100644 --- a/Configuration/Extbase/Persistence/Classes.php +++ b/Configuration/Extbase/Persistence/Classes.php @@ -29,6 +29,9 @@ \Kitodo\Dlf\Domain\Model\MetadataFormat::class => [ 'tableName' => 'tx_dlf_metadataformat', ], + \Kitodo\Dlf\Domain\Model\MetadataSubentry::class => [ + 'tableName' => 'tx_dlf_metadatasubentries', + ], \Kitodo\Dlf\Domain\Model\Printer::class => [ 'tableName' => 'tx_dlf_printer', ], diff --git a/Configuration/TCA/tx_dlf_metadataformat.php b/Configuration/TCA/tx_dlf_metadataformat.php index fc13b0f4d..46ff8f787 100644 --- a/Configuration/TCA/tx_dlf_metadataformat.php +++ b/Configuration/TCA/tx_dlf_metadataformat.php @@ -76,9 +76,32 @@ 'default' => 0, ], ], + 'subentries' => [ + 'exclude' => 1, + 'l10n_mode' => 'exclude', + 'label' => 'LLL:EXT:dlf/Resources/Private/Language/Labels.xml:tx_dlf_metadataformat.subentries', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tx_dlf_metadatasubentries', + 'foreign_field' => 'parent_id', + 'appearance' => [ + 'expandSingle' => 1, + 'levelLinksPosition' => 'bottom', + 'enabledControls' => [ + 'info' => 1, + 'new' => 1, + 'dragdrop' => 0, + 'sort' => 1, + 'hide' => 0, + 'delete' => 1, + 'localize' => 0, + ], + ], + ], + ], ], 'types' => [ - '0' => ['showitem' => '--div--;LLL:EXT:dlf/Resources/Private/Language/locallang_labels.xlf:tx_dlf_metadataformat.tab1,encoded,xpath,xpath_sorting,mandatory'], + '0' => ['showitem' => '--div--;LLL:EXT:dlf/Resources/Private/Language/locallang_labels.xlf:tx_dlf_metadataformat.tab1,encoded,xpath,xpath_sorting,mandatory,subentries'], ], 'palettes' => [ '1' => ['showitem' => ''], diff --git a/Configuration/TCA/tx_dlf_metadatasubentries.php b/Configuration/TCA/tx_dlf_metadatasubentries.php new file mode 100644 index 000000000..3d778b3d7 --- /dev/null +++ b/Configuration/TCA/tx_dlf_metadatasubentries.php @@ -0,0 +1,106 @@ + + * + * This file is part of the Kitodo and TYPO3 projects. + * + * @license GNU General Public License version 3 or later. + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + */ + +return [ + 'ctrl' => [ + 'title' => 'LLL:EXT:dlf/Resources/Private/Language/locallang_labels.xlf:tx_dlf_metadata', + 'label' => 'label', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'languageField' => 'sys_language_uid', + 'transOrigPointerField' => 'l18n_parent', + 'transOrigDiffSourceField' => 'l18n_diffsource', + 'sortby' => 'sorting', + 'delete' => 'deleted', + 'enablecolumns' => [ + 'disabled' => 'hidden', + ], + 'iconfile' => 'EXT:dlf/Resources/Public/Icons/txdlfmetadata.png', + 'rootLevel' => 0, + 'searchFields' => 'label,index_name', + ], + 'interface' => [ + ], + 'columns' => [ + 'label' => [ + 'exclude' => 1, + 'label' => 'LLL:EXT:dlf/Resources/Private/Language/locallang_labels.xlf:tx_dlf_metadata.label', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'max' => 255, + 'eval' => 'required,trim', + 'default' => '', + ], + ], + 'index_name' => [ + 'exclude' => 1, + 'l10n_mode' => 'exclude', + 'label' => 'LLL:EXT:dlf/Resources/Private/Language/locallang_labels.xlf:tx_dlf_metadata.index_name', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'max' => 255, + 'eval' => 'required,nospace,alphanum_x,uniqueInPid', + 'default' => '', + 'fieldInformation' => [ + 'editInProductionWarning' => [ + 'renderType' => 'editInProductionWarning', + ], + ], + ], + ], + 'xpath' => [ + 'exclude' => 1, + 'label' => 'LLL:EXT:dlf/Resources/Private/Language/locallang_labels.xlf:tx_dlf_metadataformat.xpath', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'max' => 1024, + 'eval' => 'required,trim', + 'default' => '', + ], + ], + 'default_value' => [ + 'exclude' => 1, + 'label' => 'LLL:EXT:dlf/Resources/Private/Language/locallang_labels.xlf:tx_dlf_metadata.default_value', + 'config' => [ + 'type' => 'input', + 'size' => 30, + 'max' => 255, + 'eval' => 'trim', + 'default' => '', + ], + ], + 'wrap' => [ + 'exclude' => 1, + 'label' => 'LLL:EXT:dlf/Resources/Private/Language/locallang_labels.xlf:tx_dlf_metadata.wrap', + 'config' => [ + 'behaviour' => [ + 'allowLanguageSynchronization' => true + ], + 'type' => 'text', + 'cols' => 48, + 'rows' => 20, + 'wrap' => 'off', + 'eval' => 'trim', + 'default' => "key.wrap = |:\nvalue.required = 1\nvalue.wrap = |\nall.wrap =
  • |
  • ", + 'fixedFont' => true, + 'enableTabulator' => true + ], + ], + ], + 'types' => [ + '0' => ['showitem' => '--div--;LLL:EXT:dlf/Resources/Private/Language/locallang_labels.xlf:tx_dlf_metadata.tab1,label,index_name,xpath,default_value,wrap'], + ], +]; diff --git a/Resources/Private/Partials/Metadata/Entries.html b/Resources/Private/Partials/Metadata/Entries.html index 0eff906e1..c4f7d4590 100644 --- a/Resources/Private/Partials/Metadata/Entries.html +++ b/Resources/Private/Partials/Metadata/Entries.html @@ -27,7 +27,33 @@ - {value} + + + +
      + + + + {subentry} + {subConfigObject.wrap -> kitodo:metadataWrapVariable(name: 'subMetadataWrap')} + + {subConfigObject.label} + + + {subvalue} + + + + + + +
    +
    +
    + + {value} + +
    diff --git a/ext_tables.sql b/ext_tables.sql index c2dbefa3d..f7ea4de2f 100644 --- a/ext_tables.sql +++ b/ext_tables.sql @@ -133,6 +133,7 @@ CREATE TABLE tx_dlf_metadataformat ( encoded int(11) DEFAULT '0' NOT NULL, xpath varchar(1024) DEFAULT '' NOT NULL, xpath_sorting varchar(1024) DEFAULT '' NOT NULL, + subentries int(11) DEFAULT '0' NOT NULL, mandatory smallint(6) DEFAULT '0' NOT NULL, PRIMARY KEY (uid), @@ -140,6 +141,33 @@ CREATE TABLE tx_dlf_metadataformat ( KEY parent_id (parent_id) ); +-- +-- Table structure for table 'tx_dlf_metadatasubentries' +-- +CREATE TABLE tx_dlf_metadatasubentries ( + uid int(11) NOT NULL auto_increment, + pid int(11) DEFAULT '0' NOT NULL, + parent_id int(11) DEFAULT '0' NOT NULL, + tstamp int(11) DEFAULT '0' NOT NULL, + crdate int(11) DEFAULT '0' NOT NULL, + cruser_id int(11) DEFAULT '0' NOT NULL, + deleted smallint(6) DEFAULT '0' NOT NULL, + sys_language_uid int(11) DEFAULT '0' NOT NULL, + l18n_parent int(11) DEFAULT '0' NOT NULL, + l18n_diffsource mediumblob NOT NULL, + label varchar(255) DEFAULT '' NOT NULL, + index_name varchar(255) DEFAULT '' NOT NULL, + xpath varchar(1024) DEFAULT '' NOT NULL, + default_value varchar(255) DEFAULT '' NOT NULL, + wrap text NOT NULL, + + PRIMARY KEY (uid), + KEY parent (pid), + KEY parent_id (parent_id), + KEY language (l18n_parent,sys_language_uid), + KEY index_name (index_name) +); + -- -- Table structure for table 'tx_dlf_formats' -- diff --git a/ext_typoscript_setup.txt b/ext_typoscript_setup.txt new file mode 100644 index 000000000..00db5b8ac --- /dev/null +++ b/ext_typoscript_setup.txt @@ -0,0 +1,78 @@ +# TODO: This whole file can get discarded when support for TYPO3 9.5 ends. + +config.tx_extbase { + persistence { + classes { + Kitodo\Dlf\Domain\Model\ActionLog { + mapping { + tableName = tx_dlf_actionlog + } + } + Kitodo\Dlf\Domain\Model\Basket { + mapping { + tableName = tx_dlf_basket + } + } + Kitodo\Dlf\Domain\Model\Collection { + mapping { + tableName = tx_dlf_collections + } + } + Kitodo\Dlf\Domain\Model\Document { + mapping { + tableName = tx_dlf_documents + } + } + Kitodo\Dlf\Domain\Model\Format { + mapping { + tableName = tx_dlf_formats + } + } + Kitodo\Dlf\Domain\Model\Library { + mapping { + tableName = tx_dlf_libraries + } + } + Kitodo\Dlf\Domain\Model\Mail { + mapping { + tableName = tx_dlf_mail + } + } + Kitodo\Dlf\Domain\Model\Metadata { + mapping { + tableName = tx_dlf_metadata + } + } + Kitodo\Dlf\Domain\Model\MetadataFormat { + mapping { + tableName = tx_dlf_metadataformat + } + } + Kitodo\Dlf\Domain\Model\MetadataSubentry { + mapping { + tableName = tx_dlf_metadatasubentries + } + } + Kitodo\Dlf\Domain\Model\Printer { + mapping { + tableName = tx_dlf_printer + } + } + Kitodo\Dlf\Domain\Model\SolrCore { + mapping { + tableName = tx_dlf_solrcores + } + } + Kitodo\Dlf\Domain\Model\Structure { + mapping { + tableName = tx_dlf_structures + } + } + Kitodo\Dlf\Domain\Model\Token { + mapping { + tableName = tx_dlf_tokens + } + } + } + } +}