From 1193d4be57557ea852693cac00d9d5d5f9acb671 Mon Sep 17 00:00:00 2001 From: Demian Katz <demian.katz@villanova.edu> Date: Tue, 19 May 2020 08:39:37 -0400 Subject: [PATCH] Improve flexibility of getFormattedMarcDetails(). (#1622) --- config/vufind/NoILS.ini | 10 +- .../VuFind/RecordDriver/MarcAdvancedTrait.php | 105 +++++++++++------- .../VuFindTest/RecordDriver/SolrMarcTest.php | 4 + 3 files changed, 78 insertions(+), 41 deletions(-) diff --git a/config/vufind/NoILS.ini b/config/vufind/NoILS.ini index 6947c23537f..319c7fdc680 100644 --- a/config/vufind/NoILS.ini +++ b/config/vufind/NoILS.ini @@ -26,7 +26,10 @@ useStatus = none ; Used if useHoldings is set to "marc" ; syntax = type|data ; For direct mapping use "msg|Message to display" -; For Marc Mapping use "marc|subfield(s)" E.g. marc|khi +; For Marc Mapping use "marc|subfield(s)|overrideField" where subfield(s) lists +; the subfield(s) to extract, and overrideField is a MARC field (if you want to +; use something different than the field specified in the marcField setting) +; E.g. marc|khi or marc|a|245 marcField = 852 availability = "msg|false" use_unknown_message = "msg|true" @@ -43,7 +46,10 @@ number = "marc|8" ; Used if useStatus is set to "marc" ; syntax = type|data ; For direct mapping use "msg|Message to display" -; For Marc Mapping use "marc|subfield(s)" E.g. marc|khi +; For Marc Mapping use "marc|subfield(s)|overrideField" where subfield(s) lists +; the subfield(s) to extract, and overrideField is a MARC field (if you want to +; use something different than the field specified in the marcField setting) +; E.g. marc|khi or marc|a|245 marcField = 852 availability = "msg|false" use_unknown_message = "msg|true" diff --git a/module/VuFind/src/VuFind/RecordDriver/MarcAdvancedTrait.php b/module/VuFind/src/VuFind/RecordDriver/MarcAdvancedTrait.php index 0efebdddf1d..5791f389d8b 100644 --- a/module/VuFind/src/VuFind/RecordDriver/MarcAdvancedTrait.php +++ b/module/VuFind/src/VuFind/RecordDriver/MarcAdvancedTrait.php @@ -783,57 +783,84 @@ trait MarcAdvancedTrait return false; } + /** + * Support method for getFormattedMarcDetails() -- extract a single result + * + * @param object $currentField Result from File_MARC::getFields + * @param array $details Parsed instructions from getFormattedMarcDetails() + * + * @return string|bool + */ + protected function extractSingleMarcDetail($currentField, $details) + { + // Simplest case -- "msg" mode (just return a configured message): + if ($details['mode'] === 'msg') { + // Map 'true' and 'false' to boolean equivalents: + $msgMap = ['true' => true, 'false' => false]; + return $msgMap[$details['params']] ?? $details['params']; + } + + // Standard case -- "marc" mode (extract subfield data): + $result = $this->getSubfieldArray( + $currentField, + // Default to subfield a if nothing is specified: + str_split($details['params'] ?? 'a'), + true + ); + return count($result) > 0 ? (string)$result[0] : ''; + } + /** * Get Status/Holdings Information from the internally stored MARC Record * (support method used by the NoILS driver). * - * @param array $field The MARC Field to retrieve - * @param array $data A keyed array of data to retrieve from subfields + * @param string $defaultField The MARC Field to retrieve if $data commands do + * not request something more specific + * @param array $data The type of data to retrieve from the MARC field; + * an array of pipe-delimited commands where the first part determines the data + * retrieval mode, the second part provides further instructions, and the + * optional third part provides a field to override $defaultField; supported + * modes: "msg" (for a hard-coded message) and "marc" (for fetching subfield + * data) * * @return array */ - public function getFormattedMarcDetails($field, $data) - { - // Initialize return array - $matches = []; - $i = 0; + public function getFormattedMarcDetails($defaultField, $data) + { + // First, parse the instructions into a more useful format, so we know + // which fields we're going to have to look up. + $instructions = []; + foreach ($data as $key => $rawInstruction) { + $instructionParts = explode('|', $rawInstruction); + $instructions[$key] = [ + 'mode' => $instructionParts[0], + 'params' => $instructionParts[1] ?? null, + 'field' => $instructionParts[2] ?? $defaultField + ]; + } - // Try to look up the specified field, return empty array if it doesn't - // exist. - $fields = $this->getMarcRecord()->getFields($field); - if (!is_array($fields)) { - return $matches; + // Now fetch all of the MARC data that we need. + $getTagCallback = function ($instruction) { + return $instruction['field']; + }; + $fields = []; + foreach (array_unique(array_map($getTagCallback, $instructions)) as $field) { + $fields[$field] = $this->getMarcRecord()->getFields($field); } - // Extract all the requested subfields, if applicable. - foreach ($fields as $currentField) { - foreach ($data as $key => $info) { - $split = explode("|", $info); - if ($split[0] == "msg") { - if ($split[1] == "true") { - $result = true; - } elseif ($split[1] == "false") { - $result = false; - } else { - $result = $split[1]; - } - $matches[$i][$key] = $result; - } else { - // Default to subfield a if nothing is specified. - if (count($split) < 2) { - $subfields = ['a']; - } else { - $subfields = str_split($split[1]); - } - $result = $this->getSubfieldArray( - $currentField, $subfields, true - ); - $matches[$i][$key] = count($result) > 0 - ? (string)$result[0] : ''; + // Initialize return array + $matches = []; + + // Process the instructions on the requested data. + foreach ($instructions as $key => $details) { + foreach ($fields[$details['field']] as $i => $currentField) { + if (!isset($matches[$i])) { + $matches[$i] = ['id' => $this->getUniqueId()]; } + $matches[$i][$key] = $this->extractSingleMarcDetail( + $currentField, $details + ); } - $matches[$i]['id'] = $this->getUniqueID(); - $i++; } return $matches; } diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php index f46520d7cf6..d2acb344e36 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php @@ -135,9 +135,11 @@ class SolrMarcTest extends \VuFindTest\Unit\TestCase 'foo' => 'msg|true', 'bar' => 'msg|false', 'baz' => 'msg|xyzzy', + 'null' => 'msg', 'title' => 'marc|a', 'default' => 'marc', 'emptySubfield' => 'marc|c', + 'pub' => 'marc|abc|260', ]; $this->assertEquals( [ @@ -145,10 +147,12 @@ class SolrMarcTest extends \VuFindTest\Unit\TestCase 'id' => '000105196', 'foo' => true, 'bar' => false, + 'null' => null, 'baz' => 'xyzzy', 'title' => 'Bollettino della Unione matematica italiana.', 'default' => 'Bollettino della Unione matematica italiana.', 'emptySubfield' => '', + 'pub' => 'Bologna : Zanichelli, 1922-1975.', ] ], $record->getFormattedMarcDetails('245', $input) -- GitLab