/** * Return fields to be indexed in Solr (an alternative to an XSL transformation) * * @return string[] */ public function toSolrArray() { // Add source prefix to IDs in link fields $fields = ['760', '762', '765', '767', '770', '772', '773', '774', '775', '776', '777', '780', '785', '786', '787']; foreach ($fields as $code) { if (isset($this->fields[$code])) { foreach ($this->fields[$code] as &$marcfield) { if (isset($marcfield['s'])) { foreach ($marcfield['s'] as &$marcsubfield) { if (key($marcsubfield) == 'w') { $marcsubfield['w'] = $this->idPrefix . '.' . $marcsubfield['w']; } } } } } } $data = parent::toSolrArray(); // building $data['building'] = []; if ($this->getDriverParam('holdingsInBuilding', true)) { foreach ($this->getFields('852') as $field) { $location = $this->getSubfield($field, 'b'); if ($location) { $data['building'][] = $location; } } } // long_lat $field = $this->getField('034'); if ($field) { $westOrig = $this->getSubfield($field, 'd'); $eastOrig = $this->getSubfield($field, 'e'); $northOrig = $this->getSubfield($field, 'f'); $southOrig = $this->getSubfield($field, 'g'); $west = MetadataUtils::coordinateToDecimal($westOrig); $east = MetadataUtils::coordinateToDecimal($eastOrig); $north = MetadataUtils::coordinateToDecimal($northOrig); $south = MetadataUtils::coordinateToDecimal($southOrig); if (!is_nan($west) && !is_nan($north)) { if (!is_nan($east)) { $longitude = ($west + $east) / 2; } else { $longitude = $west; } if (!is_nan($south)) { $latitude = ($north + $south) / 2; } else { $latitude = $north; } if ($longitude < -180 || $longitude > 180 || ($latitude < -90 || $latitude > 90)) { global $logger; $logger->log('MarcRecord', "Discarding invalid coordinates {$longitude},{$latitude} " . "decoded from w={$westOrig}, e={$eastOrig}, n={$northOrig}, " . "s={$southOrig}, record {$this->source}." . $this->getID(), Logger::WARNING); } else { $data['long_lat'] = "{$longitude},{$latitude}"; } } } // lccn $data['lccn'] = $this->getFieldSubfields('010', ['a' => 1]); $data['ctrlnum'] = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '035', ['a' => 1]]]); $data['fullrecord'] = $this->toISO2709(); if (!$data['fullrecord']) { // In case the record exceeds 99999 bytes... $data['fullrecord'] = $this->toXML(); } $data['allfields'] = $this->getAllFields(); // language $languages = $this->getLanguages(); foreach ($languages as $language) { if (preg_match('/^\\w{3}$/', $language) && $language != 'zxx' && $language != 'und') { $data['language'][] = $language; } } $data['format'] = $this->getFormat(); $data['author'] = $this->getFieldSubfields('100', ['a' => 1, 'b' => 1, 'c' => 1, 'd' => 1, 'e' => 1]); $data['author_fuller'] = $this->getFieldSubfields('100', ['q' => 1]); $data['author-letter'] = $this->getFieldSubfields('100', ['a' => 1]); $data['author2'] = $this->getFieldsSubfields([[MarcRecord::GET_ALT, '100', ['a' => 1, 'b' => 1, 'c' => 1, 'd' => 1]], [MarcRecord::GET_BOTH, '110', ['a' => 1, 'b' => 1]], [MarcRecord::GET_BOTH, '111', ['a' => 1, 'b' => 1]], [MarcRecord::GET_BOTH, '700', ['a' => 1, 'q' => 1, 'b' => 1, 'c' => 1, 'd' => 1, 'e' => 1]], [MarcRecord::GET_BOTH, '710', ['a' => 1, 'b' => 1]], [MarcRecord::GET_BOTH, '711', ['a' => 1, 'b' => 1]]]); $key = array_search($data['author'], $data['author2']); if ($key !== false) { unset($data['author2'][$key]); } $data['author2'] = array_filter(array_values($data['author2'])); $data['author2-role'] = $this->getFieldsSubfields([[MarcRecord::GET_BOTH, '700', ['e' => 1]], [MarcRecord::GET_BOTH, '710', ['e' => 1]]], true); $data['author_additional'] = $this->getFieldsSubfields([[MarcRecord::GET_BOTH, '505', ['r' => 1]]], true); $data['title'] = $this->getTitle(); $data['title_sub'] = $this->getFieldSubfields('245', ['b' => 1, 'n' => 1, 'p' => 1]); $data['title_short'] = $this->getFieldSubfields('245', ['a' => 1]); $data['title_full'] = $this->getFieldSubfields('245', ['a' => 1, 'b' => 1, 'c' => 1, 'f' => 1, 'g' => 1, 'h' => 1, 'k' => 1, 'n' => 1, 'p' => 1, 's' => 1]); $data['title_alt'] = array_values(array_unique($this->getFieldsSubfields([[MarcRecord::GET_ALT, '245', ['a' => 1, 'b' => 1]], [MarcRecord::GET_BOTH, '130', ['a' => 1, 'd' => 1, 'f' => 1, 'g' => 1, 'k' => 1, 'l' => 1, 'n' => 1, 'p' => 1, 's' => 1, 't' => 1]], [MarcRecord::GET_BOTH, '240', ['a' => 1]], [MarcRecord::GET_BOTH, '246', ['g' => 1]], [MarcRecord::GET_BOTH, '730', ['a' => 1, 'd' => 1, 'f' => 1, 'g' => 1, 'k' => 1, 'l' => 1, 'n' => 1, 'p' => 1, 's' => 1, 't' => 1]], [MarcRecord::GET_BOTH, '740', ['a' => 1]]]))); $data['title_old'] = $this->getFieldsSubfields([[MarcRecord::GET_BOTH, '780', ['a' => 1, 's' => 1, 't' => 1]]]); $data['title_new'] = $this->getFieldsSubfields([[MarcRecord::GET_BOTH, '785', ['a' => 1, 's' => 1, 't' => 1]]]); $data['title_sort'] = $this->getTitle(true); if (!$data['title_short']) { $data['title_short'] = $this->getFieldSubfields('240', ['a' => 1, 'n' => 1, 'p' => 1]); $data['title_full'] = $this->getFieldSubfields('240'); } $data['series'] = $this->getFieldsSubfields([[MarcRecord::GET_BOTH, '440', ['a' => 1]], [MarcRecord::GET_BOTH, '490', ['a' => 1]], [MarcRecord::GET_BOTH, '800', ['a' => 1, 'b' => 1, 'c' => 1, 'd' => 1, 'f' => 1, 'p' => 1, 'q' => 1, 't' => 1]], [MarcRecord::GET_BOTH, '830', ['a' => 1, 'p' => 1]]]); $data['publisher'] = $this->getFieldsSubfields([[MarcRecord::GET_BOTH, '260', ['b' => 1]]], false, true); if (!$data['publisher']) { $fields = $this->getFields('264'); foreach ($fields as $field) { if ($this->getIndicator($field, 2) == '1') { $data['publisher'] = metadataUtils::stripTrailingPunctuation($this->getSubfield($field, 'b')); break; } } } $publicationYear = $this->getPublicationYear(); if ($publicationYear) { $data['publishDateSort'] = $publicationYear; $data['publishDate'] = [$publicationYear]; } $data['physical'] = $this->getFieldsSubfields([[MarcRecord::GET_BOTH, '300', ['a' => 1, 'b' => 1, 'c' => 1, 'e' => 1, 'f' => 1, 'g' => 1]], [MarcRecord::GET_BOTH, '530', ['a' => 1, 'b' => 1, 'c' => 1, 'd' => 1]]]); $data['dateSpan'] = $this->getFieldsSubfields([[MarcRecord::GET_BOTH, '362', ['a' => 1]]]); $data['edition'] = $this->getFieldSubfields('250', ['a' => 1]); $data['contents'] = $this->getFieldsSubfields([[MarcRecord::GET_BOTH, '505', ['a' => 1]], [MarcRecord::GET_BOTH, '505', ['t' => 1]]]); $data['isbn'] = $this->getISBNs(); foreach ($this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '773', ['z' => 1]]]) as $isbn) { $isbn = str_replace('-', '', $isbn); if (!preg_match('{([0-9]{9,12}[0-9xX])}', $isbn, $matches)) { continue; } $isbn = $matches[1]; if (strlen($isbn) == 10) { $isbn = MetadataUtils::isbn10to13($isbn); } if ($isbn) { $data['isbn'][] = $isbn; } } $data['issn'] = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '022', ['a' => 1]], [MarcRecord::GET_NORMAL, '440', ['x' => 1]], [MarcRecord::GET_NORMAL, '490', ['x' => 1]], [MarcRecord::GET_NORMAL, '730', ['x' => 1]], [MarcRecord::GET_NORMAL, '773', ['x' => 1]], [MarcRecord::GET_NORMAL, '776', ['x' => 1]], [MarcRecord::GET_NORMAL, '780', ['x' => 1]], [MarcRecord::GET_NORMAL, '785', ['x' => 1]]]); foreach ($data['issn'] as &$value) { $value = str_replace('-', '', $value); } $data['callnumber-first'] = $this->getFirstFieldSubfields([[MarcRecord::GET_NORMAL, '099', ['a' => 1]], [MarcRecord::GET_NORMAL, '090', ['a' => 1]], [MarcRecord::GET_NORMAL, '050', ['a' => 1]]]); $values = $this->getFirstFieldSubfields([[MarcRecord::GET_NORMAL, '090', ['a' => 1]], [MarcRecord::GET_NORMAL, '050', ['a' => 1]]]); if ($values) { if (preg_match('/^([A-Z]+)/', strtoupper($values[0]), $matches)) { $data['callnumber-subject'] = $matches[1]; } $dotPos = strstr($values[0], '.'); if ($dotPos > 0) { $data['callnumber-label'] = strtoupper(substr($values[1], 0, $dotPos)); } else { $data['callnumber-label'] = strtoupper($values[0]); } } $data['callnumber-raw'] = array_map('strtoupper', $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '080', ['a' => 1, 'b' => 1]], [MarcRecord::GET_NORMAL, '084', ['a' => 1, 'b' => 1]], [MarcRecord::GET_NORMAL, '050', ['a' => 1, 'b' => 1]]])); foreach ($data['callnumber-raw'] as $callnumber) { $cn = new LcCallNumber($callnumber); if ($cn->isValid()) { $data['callnumber-sort'] = $cn->getSortKey(); } } if (empty($data['callnumber-sort']) && !empty($data['callnumber-raw'])) { $cn = new LcCallNumber($data['callnumber-raw'][0]); $data['callnumber-sort'] = $cn->getSortKey(); } $data['topic'] = $this->getTopics(); $data['genre'] = $this->getGenres(); $data['geographic'] = $this->getGeographicTopics(); $data['era'] = $this->getEras(); $data['topic_facet'] = $this->getTopicFacets(); $data['genre_facet'] = $this->getGenreFacets(); $data['geographic_facet'] = $this->getGeographicFacets(); $data['era_facet'] = $this->getEraFacets(); $data['url'] = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '856', ['u' => 1]]]); $data['illustrated'] = $this->getIllustrated(); // TODO: dewey fields and OCLC numbers return $data; }
/** * Return fields to be indexed in Solr (an alternative to an XSL transformation) * * @return string[] */ public function toSolrArray() { $data = parent::toSolrArray(); if (empty($data['author'])) { $data['author'] = $data['author_fuller'] = $data['author-letter'] = $this->getFieldSubfields('110', ['a' => 1]); } $key = array_search($data['author'], $data['author2']); if ($key !== false) { unset($data['author2'][$key]); } if (isset($data['publishDate'])) { $data['main_date_str'] = MetadataUtils::extractYear($data['publishDate'][0]); $data['main_date'] = $this->validateDate($data['main_date_str'] . '-01-01T00:00:00Z'); } if ($range = $this->getPublicationDateRange()) { $data['search_sdaterange_mv'][] = $data['publication_sdaterange'] = MetadataUtils::dateRangeToNumeric($range); $data['search_daterange_mv'][] = $data['publication_daterange'] = MetadataUtils::dateRangeToStr($range); } $data['publication_place_txt_mv'] = MetadataUtils::arrayTrim($this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '260', ['a' => 1]]]), ' []'); $data['subtitle_lng_str_mv'] = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '041', ['j' => 1]], [MarcRecord::GET_NORMAL, '979', ['j' => 1]]], false, true, true); $data['original_lng_str_mv'] = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '041', ['h' => 1]], [MarcRecord::GET_NORMAL, '979', ['i' => 1]]], false, true, true); // 979cd = component part authors // 900, 910, 911 = Finnish reference field foreach ($this->getFieldsSubfields([[MarcRecord::GET_BOTH, '979', ['c' => 1]], [MarcRecord::GET_BOTH, '979', ['d' => 1]], [MarcRecord::GET_BOTH, '900', ['a' => 1]], [MarcRecord::GET_BOTH, '910', ['a' => 1, 'b' => 1]], [MarcRecord::GET_BOTH, '911', ['a' => 1, 'e' => 1]]], false, true, true) as $field) { $data['author2'][] = $field; } $key = array_search($data['author'], $data['author2']); if ($key !== false) { unset($data['author2'][$key]); } $data['author2'] = array_filter(array_values($data['author2'])); $data['title_alt'] = array_values(array_unique($this->getFieldsSubfields([[MarcRecord::GET_ALT, '245', ['a' => 1, 'b' => 1]], [MarcRecord::GET_BOTH, '130', ['a' => 1, 'd' => 1, 'f' => 1, 'g' => 1, 'h' => 1, 'k' => 1, 'l' => 1, 'n' => 1, 'p' => 1, 'r' => 1, 's' => 1, 't' => 1]], [MarcRecord::GET_BOTH, '240', ['a' => 1, 'd' => 1, 'f' => 1, 'g' => 1, 'k' => 1, 'l' => 1, 'n' => 1, 'p' => 1, 'r' => 1, 's' => 1]], [MarcRecord::GET_BOTH, '243', ['a' => 1, 'd' => 1, 'f' => 1, 'g' => 1, 'h' => 1, 'k' => 1, 'l' => 1, 'm' => 1, 'n' => 1, 'o' => 1, 'p' => 1, 'r' => 1, 's' => 1]], [MarcRecord::GET_BOTH, '246', ['a' => 1, 'b' => 1, 'g' => 1]], [MarcRecord::GET_BOTH, '700', ['t' => 1, 'm' => 1, 'r' => 1, 'h' => 1, 'i' => 1, 'g' => 1, 'n' => 1, 'p' => 1, 's' => 1, 'l' => 1, 'o' => 1, 'k' => 1], ['t' => 1]], [MarcRecord::GET_BOTH, '730', ['a' => 1, 'd' => 1, 'f' => 1, 'g' => 1, 'h' => 1, 'i' => 1, 'k' => 1, 'l' => 1, 'm' => 1, 'n' => 1, 'o' => 1, 'p' => 1, 'r' => 1, 's' => 1, 't' => 1]], [MarcRecord::GET_BOTH, '740', ['a' => 1]], [MarcRecord::GET_BOTH, '979', ['b' => 1]], [MarcRecord::GET_BOTH, '979', ['e' => 1]], [MarcRecord::GET_BOTH, '940', ['a' => 1]]]))); // Location coordinates $field = $this->getField('034'); if ($field) { $westOrig = $this->getSubfield($field, 'd'); $eastOrig = $this->getSubfield($field, 'e'); $northOrig = $this->getSubfield($field, 'f'); $southOrig = $this->getSubfield($field, 'g'); $west = MetadataUtils::coordinateToDecimal($westOrig); $east = MetadataUtils::coordinateToDecimal($eastOrig); $north = MetadataUtils::coordinateToDecimal($northOrig); $south = MetadataUtils::coordinateToDecimal($southOrig); if (!is_nan($west) && !is_nan($north)) { if ($west < -180 || $west > 180 || ($north < -90 || $north > 90)) { global $logger; $logger->log('NdlMarcRecord', "Discarding invalid coordinates {$west},{$north} decoded from " . "w={$westOrig}, e={$eastOrig}, n={$northOrig}, s={$southOrig}, " . "record {$this->source}." . $this->getID(), Logger::WARNING); } else { if (!is_nan($east) && !is_nan($south)) { if ($east < -180 || $east > 180 || $south < -90 || $south > 90) { global $logger; $logger->log('NdlMarcRecord', "Discarding invalid coordinates {$east},{$south} " . "decoded from w={$westOrig}, e={$eastOrig}, " . "n={$northOrig}, s={$southOrig}, record " . "{$this->source}." . $this->getID(), Logger::WARNING); } else { // Try to cope with weird coordinate order if ($north > $south) { list($north, $south) = [$south, $north]; } if ($west > $east) { list($west, $east) = [$east, $west]; } $data['location_geo'] = "ENVELOPE({$west}, {$east}, {$south}, {$north})"; } } else { $data['location_geo'] = "POINT({$west} {$north})"; } } } } // Classifications foreach ($this->getFields('080') as $field080) { $classification = trim($this->getSubfield($field080, 'a')); $classification .= trim($this->getSubfield($field080, 'b')); if ($classification) { $aux = $this->getSubfields($field080, ['x' => 1]); if ($aux) { $classification .= " {$aux}"; } $data['classification_txt_mv'][] = "udk {$classification}"; } } $dlc = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '050', ['a' => 1, 'b' => 1]]]); foreach ($dlc as $classification) { $data['classification_txt_mv'][] = 'dlc ' . mb_strtolower(str_replace(' ', '', $classification), 'UTF-8'); } foreach ($this->getFields('084') as $field) { $source = $this->getSubfield($field, '2'); $classification = $this->getSubfields($field, ['a' => 1, 'b' => 1]); if ($source) { $data['classification_txt_mv'][] = "{$source} " . mb_strtolower(str_replace(' ', '', $classification), 'UTF-8'); } } if (isset($data['classification_txt_mv'])) { $data['allfields'] = array_merge($data['allfields'], $data['classification_txt_mv']); } // Keep classification_str_mv for backward-compatibility for now if (isset($data['classification_txt_mv'])) { $data['classification_str_mv'] = $data['classification_txt_mv']; } // Ebrary location $ebraryLocs = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '035', ['a' => 1]]]); foreach ($ebraryLocs as $field) { if (strncmp($field, 'ebr', 3) == 0 && is_numeric(substr($field, 3))) { if (!isset($data['building']) || !in_array('EbraryDynamic', $data['building'])) { $data['building'][] = 'EbraryDynamic'; } } } // Topics if (strncmp($this->source, 'metalib', 7) == 0) { $field653 = $this->getFieldsSubfields([[MarcRecord::GET_BOTH, '653', ['a' => 1]]]); $data['topic'] = array_merge($data['topic'], $field653); $data['topic_facet'] = array_merge($data['topic_facet'], $field653); } // Original Study Number $data['ctrlnum'] = array_merge($data['ctrlnum'], $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '036', ['a' => 1]]])); // Source $data['source_str_mv'] = $this->source; $data['datasource_str_mv'] = [$this->source]; // ISSN $data['issn'] = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '022', ['a' => 1]]]); foreach ($data['issn'] as &$value) { $value = str_replace('-', '', $value); } $data['other_issn_str_mv'] = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '440', ['x' => 1]], [MarcRecord::GET_NORMAL, '480', ['x' => 1]], [MarcRecord::GET_NORMAL, '730', ['x' => 1]], [MarcRecord::GET_NORMAL, '776', ['x' => 1]]]); foreach ($data['other_issn_str_mv'] as &$value) { $value = str_replace('-', '', $value); } $data['linking_issn_str_mv'] = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '022', ['l' => 1]]]); foreach ($data['linking_issn_str_mv'] as &$value) { $value = str_replace('-', '', $value); } // URLs $fields = $this->getFields('856'); foreach ($fields as $field) { $ind2 = $this->getIndicator($field, 2); $sub3 = $this->getSubfield($field, 3); if (($ind2 == '0' || $ind2 == '1') && !$sub3) { $url = trim($this->getSubfield($field, 'u')); if (!$url) { continue; } // Require at least one dot surrounded by valid characters or a // familiar scheme if (!preg_match('/[A-Za-z0-9]\\.[A-Za-z0-9]/', $url) && !preg_match('/^(http|ftp)s?:\\/\\//', $url)) { continue; } $data['online_boolean'] = true; $data['online_str_mv'] = $this->source; $linkText = $this->getSubfield($field, 'y'); if (!$linkText) { $linkText = $this->getSubfield($field, 'z'); } $link = ['url' => $this->getSubfield($field, 'u'), 'text' => $linkText, 'source' => $this->source]; $data['online_urls_str_mv'][] = json_encode($link); } } // Holdings $data['holdings_txtP_mv'] = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '852', ['a' => 1, 'b' => 1, 'h' => 1, 'z' => 1]]]); if (!empty($data['holdings_txtP_mv'])) { $updateFunc = function (&$val, $k, $source) { $val .= " {$source}"; }; array_walk($data['holdings_txtP_mv'], $updateFunc, $this->source); } // Access restrictions if ($restrictions = $this->getAccessRestrictions()) { $data['restricted_str'] = $restrictions; } // ISMN foreach ($this->getFields('024') as $field024) { if ($this->getIndicator($field024, 1) == '2') { $ismn = $this->getSubfield($field024, 'a'); $ismn = str_replace('-', '', $ismn); if (!preg_match('{([0-9]{13})}', $ismn, $matches)) { continue; } $data['ismn_isn_mv'] = $matches[1]; } } // Project ID in 960 (Fennica) if ($this->getDriverParam('projectIdIn960', false)) { $data['project_id_str_mv'] = $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '960', ['a' => 1]]]); } // Hierarchical Categories (MetaLib) foreach ($this->getFields('976') as $field976) { $category = $this->getSubfield($field976, 'a'); $category = trim(str_replace(['/', '\\'], '', $category), " -\t\n\r\v"); if (!$category) { continue; } $sub = $this->getSubfield($field976, 'b'); $sub = trim(str_replace(['/', '\\'], '', $sub), " -\t\n\r\v"); if ($sub) { $category .= "/{$sub}"; } $data['category_str_mv'][] = $category; } // Hierarchical categories (e.g. SFX) if ($this->getDriverParam('categoriesIn650', false)) { foreach ($this->getFields('650') as $field650) { $category = $this->getSubfield($field650, 'a'); $category = trim(str_replace(['/', '\\'], '', $category)); if (!$category) { continue; } $sub = $this->getSubfield($field650, 'x'); $sub = trim(str_replace(['/', '\\'], '', $sub)); if ($sub) { $category .= "/{$sub}"; } $data['category_str_mv'][] = $category; } } // Call numbers $data['callnumber-first'] = strtoupper(str_replace(' ', '', $this->getFirstFieldSubfields([[MarcRecord::GET_NORMAL, '080', ['a' => 1, 'b' => 1]], [MarcRecord::GET_NORMAL, '084', ['a' => 1, 'b' => 1]], [MarcRecord::GET_NORMAL, '050', ['a' => 1, 'b' => 1]]]))); $data['callnumber-raw'] = array_map('strtoupper', $this->getFieldsSubfields([[MarcRecord::GET_NORMAL, '080', ['a' => 1, 'b' => 1]], [MarcRecord::GET_NORMAL, '084', ['a' => 1, 'b' => 1]], [MarcRecord::GET_NORMAL, '050', ['a' => 1, 'b' => 1]]])); $data['callnumber-sort'] = empty($data['callnumber-raw']) ? '' : $data['callnumber-raw'][0]; // Legacy callnumber fields. TODO: Remove when VuFind 1 is gone. $data['callnumber'] = strtoupper(str_replace(' ', '', $this->getFirstFieldSubfields([[MarcRecord::GET_NORMAL, '080', ['a' => 1, 'b' => 1]], [MarcRecord::GET_NORMAL, '084', ['a' => 1, 'b' => 1]], [MarcRecord::GET_NORMAL, '050', ['a' => 1, 'b' => 1]]]))); $data['callnumber-a'] = $this->getFirstFieldSubfields([[MarcRecord::GET_NORMAL, '080', ['a' => 1]], [MarcRecord::GET_NORMAL, '084', ['a' => 1]], [MarcRecord::GET_NORMAL, '050', ['a' => 1]]]); $data['callnumber-first-code'] = substr($data['callnumber-a'], 0, 1); return $data; }