diff --git a/Classes/Common/MetsDocument.php b/Classes/Common/MetsDocument.php index cc6c7a30e..461dbda8f 100644 --- a/Classes/Common/MetsDocument.php +++ b/Classes/Common/MetsDocument.php @@ -333,15 +333,18 @@ protected function getLogicalStructureInfo(\SimpleXMLElement $structure, $recurs $details['orderlabel'] = (isset($attributes['ORDERLABEL']) ? $attributes['ORDERLABEL'] : ''); $details['contentIds'] = (isset($attributes['CONTENTIDS']) ? $attributes['CONTENTIDS'] : ''); $details['volume'] = ''; - // Set volume information only if no label is set and this is the toplevel structure element. + // Set volume and year information only if no label is set and this is the toplevel structure element. if ( empty($details['label']) - && $details['id'] == $this->_getToplevelId() + && empty($details['orderlabel']) ) { $metadata = $this->getMetadata($details['id']); if (!empty($metadata['volume'][0])) { $details['volume'] = $metadata['volume'][0]; } + if (!empty($metadata['year'][0])) { + $details['year'] = $metadata['year'][0]; + } } $details['pagination'] = ''; $details['type'] = $attributes['TYPE']; @@ -630,6 +633,7 @@ class_exists($class) if (empty($metadata['date'][0])) { $metadata['date'][0] = ''; } + // Files are not expected to reference a dmdSec if (isset($this->fileInfos[$id]) || isset($hasMetadataSection['dmdSec'])) { return $metadata; diff --git a/Classes/Controller/TableOfContentsController.php b/Classes/Controller/TableOfContentsController.php index e0a70df47..d90b5b8b2 100644 --- a/Classes/Controller/TableOfContentsController.php +++ b/Classes/Controller/TableOfContentsController.php @@ -36,6 +36,8 @@ class TableOfContentsController extends AbstractController /** * The main method of the plugin * + * @access public + * * @return void */ public function mainAction() @@ -55,10 +57,11 @@ public function mainAction() /** * This builds a menu array for HMENU * - * @access protected + * @access private + * * @return array HMENU array */ - protected function makeMenuArray() + private function makeMenuArray() { $this->requestData['double'] = MathUtility::forceIntegerInRange($this->requestData['double'], 0, 1, 0); $menuArray = []; @@ -67,21 +70,7 @@ protected function makeMenuArray() !empty($this->document->getDoc()->physicalStructure) || !MathUtility::canBeInterpretedAsInteger($this->requestData['id']) ) { - // Get all logical units the current page or track is a part of. - if ( - !empty($this->requestData['page']) - && !empty($this->document->getDoc()->physicalStructure) - ) { - $this->activeEntries = array_merge((array) $this->document->getDoc()->smLinks['p2l'][$this->document->getDoc()->physicalStructure[0]], - (array) $this->document->getDoc()->smLinks['p2l'][$this->document->getDoc()->physicalStructure[$this->requestData['page']]]); - if ( - !empty($this->requestData['double']) - && $this->requestData['page'] < $this->document->getDoc()->numPages - ) { - $this->activeEntries = array_merge($this->activeEntries, - (array) $this->document->getDoc()->smLinks['p2l'][$this->document->getDoc()->physicalStructure[$this->requestData['page'] + 1]]); - } - } + $this->getAllLogicalUnits(); // Go through table of contents and create all menu entries. foreach ($this->document->getDoc()->tableOfContents as $entry) { $menuArray[] = $this->getMenuEntry($entry, true); @@ -104,6 +93,7 @@ protected function makeMenuArray() 'label' => !empty($resArray['mets_label']) ? $resArray['mets_label'] : $resArray['title'], 'type' => $resArray['type'], 'volume' => $resArray['volume'], + 'year' => $resArray['year'], 'orderlabel' => $resArray['mets_orderlabel'], 'pagination' => '', 'targetUid' => $resArray['uid'] @@ -119,21 +109,22 @@ protected function makeMenuArray() /** * This builds an array for one menu entry * - * @access protected + * @access private * * @param array $entry : The entry's array from \Kitodo\Dlf\Common\Doc->getLogicalStructure * @param bool $recursive : Whether to include the child entries * * @return array HMENU array for menu entry */ - protected function getMenuEntry(array $entry, $recursive = false) + private function getMenuEntry(array $entry, $recursive = false) { $entry = $this->resolveMenuEntry($entry); $entryArray = []; // Set "title", "volume", "type" and "pagination" from $entry array. - $entryArray['title'] = !empty($entry['label']) ? $entry['label'] : $entry['orderlabel']; + $entryArray['title'] = $this->setTitle($entry); $entryArray['volume'] = $entry['volume']; + $entryArray['year'] = $entry['year']; $entryArray['orderlabel'] = $entry['orderlabel']; $entryArray['type'] = $this->getTranslatedType($entry['type']); $entryArray['pagination'] = htmlspecialchars($entry['pagination']); @@ -141,9 +132,6 @@ protected function getMenuEntry(array $entry, $recursive = false) $entryArray['doNotLinkIt'] = 1; $entryArray['ITEM_STATE'] = 'NO'; - if ($entry['type'] == 'volume') { - $entryArray['title'] = $this->getTranslatedType($entry['type']) . ' ' . $entry['volume']; - } // Build menu links based on the $entry['points'] array. if ( !empty($entry['points']) @@ -222,10 +210,12 @@ protected function getMenuEntry(array $entry, $recursive = false) * This is so that when linking from a child document back to its parent, * that link is via UID, so that subsequently the parent's TOC is built from database. * + * @access private + * * @param array $entry * @return array */ - protected function resolveMenuEntry($entry) + private function resolveMenuEntry($entry) { // If the menu entry points to the parent document, // resolve to the parent UID set on indexation. @@ -242,9 +232,35 @@ protected function resolveMenuEntry($entry) return $entry; } + /** + * Get all logical units the current page or track is a part of. + * + * @access private + * + * @return void + */ + private function getAllLogicalUnits() { + if ( + !empty($this->requestData['page']) + && !empty($this->document->getDoc()->physicalStructure) + ) { + $this->activeEntries = array_merge((array) $this->document->getDoc()->smLinks['p2l'][$this->document->getDoc()->physicalStructure[0]], + (array) $this->document->getDoc()->smLinks['p2l'][$this->document->getDoc()->physicalStructure[$this->requestData['page']]]); + if ( + !empty($this->requestData['double']) + && $this->requestData['page'] < $this->document->getDoc()->numPages + ) { + $this->activeEntries = array_merge($this->activeEntries, + (array) $this->document->getDoc()->smLinks['p2l'][$this->document->getDoc()->physicalStructure[$this->requestData['page'] + 1]]); + } + } + } + /** * Get translated type of entry. * + * @access private + * * @param string $type * * @return string @@ -272,9 +288,40 @@ private function getTranslatedType($type) { private function isMultiElement($type) { return $type === 'multivolume_work' || $type === 'multipart_manuscript'; } + /** + * Set title from entry. + * + * @access private + * + * @param array $entry + * + * @return string + */ + private function setTitle($entry) { + if (empty($entry['label']) && empty($entry['orderlabel'])) { + foreach ($this->settings['titleReplacements'] as $titleReplacement) { + if ($entry['type'] == $titleReplacement['type']) { + $fields = explode(",", $titleReplacement['fields']); + $title = ''; + foreach ($fields as $field) { + if ($field == 'type') { + $title .= $this->getTranslatedType($entry['type']) . ' '; + } else { + $title .= $entry[$field] . ' '; + } + } + + return trim($title); + } + } + } + return $entry['label'] ?: $entry['orderlabel']; + } /** - * Sort menu by orderlabel - currently implemented for newspaper. + * Sort menu by orderlabel. + * + * @access private * * @param array &$menu * @@ -282,20 +329,28 @@ private function isMultiElement($type) { */ private function sortMenu(&$menu) { if ($menu[0]['type'] == $this->getTranslatedType("newspaper")) { - $this->sortMenuForNewspapers($menu); + $this->sortSubMenu($menu); + } + if ($menu[0]['type'] == $this->getTranslatedType("year")) { + $this->sortSubMenu($menu); } } /** - * Sort menu years of the newspaper by orderlabel. - * + * Sort sub menu e.g years of the newspaper by orderlabel. + * + * @access private + * * @param array &$menu * * @return void */ - private function sortMenuForNewspapers(&$menu) { - usort($menu[0]['_SUB_MENU'], function ($firstYear, $secondYear) { - return $firstYear['orderlabel'] <=> $secondYear['orderlabel']; + private function sortSubMenu(&$menu) { + usort($menu[0]['_SUB_MENU'], function ($firstElement, $secondElement) { + if (!empty($firstElement['orderlabel'])) { + return $firstElement['orderlabel'] <=> $secondElement['orderlabel']; + } + return $firstElement['year'] <=> $secondElement['year']; }); } } diff --git a/Classes/Domain/Repository/DocumentRepository.php b/Classes/Domain/Repository/DocumentRepository.php index 0315504d6..181ddb4d6 100644 --- a/Classes/Domain/Repository/DocumentRepository.php +++ b/Classes/Domain/Repository/DocumentRepository.php @@ -365,6 +365,7 @@ public function getTableOfContentsFromDb($uid, $pid, $settings) 'tx_dlf_documents.uid AS uid', 'tx_dlf_documents.title AS title', 'tx_dlf_documents.volume AS volume', + 'tx_dlf_documents.year AS year', 'tx_dlf_documents.mets_label AS mets_label', 'tx_dlf_documents.mets_orderlabel AS mets_orderlabel', 'tx_dlf_structures_join.index_name AS type' diff --git a/Configuration/TypoScript/setup.typoscript b/Configuration/TypoScript/setup.typoscript index eb3167b1c..aec7c16eb 100644 --- a/Configuration/TypoScript/setup.typoscript +++ b/Configuration/TypoScript/setup.typoscript @@ -104,3 +104,18 @@ plugin.tx_dlf_search { } } } + +plugin.tx_dlf_tableofcontents { + settings { + titleReplacements { + 0 { + type = issue + fields = type,year + } + 1 { + type = volume + fields = type,volume + } + } + } +} diff --git a/Documentation/Plugins/Index.rst b/Documentation/Plugins/Index.rst index 90031af5d..068e6cfcb 100644 --- a/Documentation/Plugins/Index.rst +++ b/Documentation/Plugins/Index.rst @@ -867,6 +867,8 @@ Table Of Contents Data type :Default: Default + :Description: + Description - :Property: excludeOther_ @@ -894,6 +896,24 @@ Table Of Contents :ref:`t3tsref:data-type-page-id` :Default: + - :Property: + titleReplacement + :Data Type: + :ref:`t3tsref:data-type-list` + :Default: + :Description: + List containing types for which title should be replaced + when the label is empty. The defined fields are used for + replacement. Example data: + 0 { + type = issue + fields = type,year + } + 1 { + type = volume + fields = type,volume + } + Toolbox -------