/** * Get holdings structure for holdings * * @param Integer $fieldName * @return Array[] */ protected function getStructuredHoldingsStructure($fieldName, $data = array()) { //$data = array(); $fields = $this->holdings ? $this->holdings->getFields($fieldName) : false; $mapping = array('B' => 'network', 'F' => 'institution_chb'); if (is_array($fields)) { foreach ($fields as $index => $field) { $item = $this->extractFieldData($field, $mapping); $networkCode = $item['network']; $institution = $item['institution_chb']; $groupCode = $this->getGroup($institution); // Prevent display of untranslated and ungrouped institutions $institutionLabel = $this->translator->translate($institution, 'institution'); if ($groupCode == 'unknown' || $institutionLabel === $institution) { if ($groupCode === 'unknown') { $this->swissbibLogger->logUngroupedInstitution($institution); } continue; } // Make sure group is present if (!isset($data[$groupCode])) { $data[$groupCode] = array('label' => $groupCode, 'networkCode' => $networkCode, 'institutions' => array()); } // Make sure institution is present if (!isset($data[$groupCode]['institutions'][$institution])) { $data[$groupCode]['institutions'][$institution] = array('label' => $institution, 'bibinfolink' => $this->getBibInfoLink($institution)); } } } return $data; }
function getNotes() { $additionalNotesFields = array('520' => 'Description', '500' => 'General Note', '504' => 'Bibliography', '511' => 'Participants/Performers', '518' => 'Date/Time and Place of Event', '310' => 'Current Publication Frequency', '321' => 'Former Publication Frequency', '351' => 'Organization & arrangement of materials', '362' => 'Dates of publication and/or sequential designation', '501' => '"With"', '502' => 'Dissertation', '506' => 'Restrictions on Access', '507' => 'Scale for Graphic Material', '508' => 'Creation/Production Credits', '510' => 'Citation/References', '513' => 'Type of Report an Period Covered', '515' => 'Numbering Peculiarities', '521' => 'Target Audience', '522' => 'Geographic Coverage', '525' => 'Supplement', '526' => 'Study Program Information', '530' => 'Additional Physical Form', '533' => 'Reproduction', '534' => 'Original Version', '536' => 'Funding Information', '538' => 'System Details', '545' => 'Biographical or Historical Data', '546' => 'Language', '547' => 'Former Title Complexity', '550' => 'Issuing Body', '555' => 'Cumulative Index/Finding Aids', '556' => 'Information About Documentation', '561' => 'Ownership and Custodial History', '563' => 'Binding Information', '580' => 'Linking Entry Complexity', '581' => 'Publications About Described Materials', '586' => 'Awards', '590' => 'Local note', '599' => 'Differentiable Local note'); $notes = array(); foreach ($additionalNotesFields as $tag => $label) { /** @var File_MARC_Data_Field[] $marcFields */ $marcFields = $this->marcRecord->getFields($tag); foreach ($marcFields as $marcField) { $noteText = array(); foreach ($marcField->getSubFields() as $subfield) { /** @var File_MARC_Subfield $subfield */ $noteText[] = $subfield->getData(); } $note = implode(',', $noteText); if (strlen($note) > 0) { $notes[] = array('label' => $label, 'note' => $note); } } } return $notes; }
/** * 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 * * @return array */ public function getFormattedMarcDetails($field, $data) { // Initialize return array $matches = []; $i = 0; // Try to look up the specified field, return empty array if it doesn't // exist. $fields = $this->marcRecord->getFields($field); if (!is_array($fields)) { return $matches; } // 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] : ''; } } $matches[$i]['id'] = $this->getUniqueID(); $i++; } return $matches; }
/** * Return an array of all values extracted from the specified field/subfield * combination. If multiple subfields are specified and $concat is true, they * will be concatenated together in the order listed -- each entry in the array * will correspond with a single MARC field. If $concat is false, the return * array will contain separate entries for separate subfields. * * @param string $field The MARC field number to read * @param array $subFields The MARC subfield codes to read * @param bool $concatenate Should we concatenate subfields? * @access private * @return array */ private function getFieldArray($field, $subFields = null, $concatenate = true) { if (!$this->marcRecord) { return array(); } // Default to subField a if nothing is specified. if (!is_array($subFields)) { $subFields = array('a'); } // Initialize return array $matches = array(); // Try to look up the specified field, return empty array if it doesn't exist. $fields = $this->marcRecord->getFields($field); if (!is_array($fields)) { return $matches; } // Extract all the requested subfields, if applicable. foreach ($fields as $currentField) { $next = $this->getSubfieldArray($currentField, $subFields, $concatenate); $matches = array_merge($matches, $next); } return $matches; }
/** * Decode a MARC holding record. * * @param File_MARC_Record $record Holding record to decode.. * * @return array Has two elements: the first is the list of * locations found in the record, the second are the * decoded holdings per se. * * @todo Check if is OK to print multiple times textual holdings * that had more than one $8. */ protected function decodeMarcHoldingRecord($record) { $locations = []; $holdings = []; // First pass: // - process locations // // - collect textual holdings indexed by linking number to be // able to easily check later what fields from enumeration // and chronology they override. $textuals = []; foreach ($record->getFields('852|866', true) as $field) { switch ($field->getTag()) { case '852': $locations[] = $this->processMarcHoldingLocation($field); break; case '866': $linking_fields = $field->getSubfields('8'); if ($linking_fields === false) { // Skip textual holdings fields with no linking continue 2; } foreach ($linking_fields as $linking_field) { $linking = explode('.', $linking_field->getData()); // Only the linking part is used in textual // holdings... $linking = $linking[0]; // and it should be an int. $textuals[(int) $linking] =& $field; } break; } } // Second pass: enumeration and chronology, biblio // Digits to use to build a combined index with linking number // and sequence number. // PS: Does this make this implementation year-3K safe? $link_digits = floor(strlen((string) PHP_INT_MAX) / 2); foreach (array_key_exists(0, $textuals) ? [] : $record->getFields('863') as $field) { $linking_field = $field->getSubfield('8'); if ($linking_field === false) { // Skip record if there is no linking number continue; } $linking = explode('.', $linking_field->getData()); if (1 < count($linking)) { $sequence = explode('\\', $linking[1]); // Lets ignore the link type, as we only care for \x $sequence = $sequence[0]; } else { $sequence = 0; } $linking = $linking[0]; if (array_key_exists((int) $linking, $textuals)) { // Skip coded holdings overridden by textual // holdings continue; } $decoded_holding = ''; foreach ($field->getSubfields() as $subfield) { if (strpos('68x', $subfield->getCode()) !== false) { continue; } $decoded_holding .= ' ' . $subfield->getData(); } $ndx = (int) ($linking . sprintf("%0{$link_digits}u", $sequence)); $holdings[$ndx] = trim($decoded_holding); } foreach ($textuals as $linking => $field) { $textual_holding = $field->getSubfield('a')->getData(); foreach ($field->getSubfields('z') as $note) { $textual_holding .= ' ' . $note->getData(); } $ndx = (int) ($linking . sprintf("%0{$link_digits}u", 0)); $holdings[$ndx] = trim($textual_holding); } return [$locations, $holdings]; }
/** * @param File_MARC_Record $marcRecord * @return bool */ function isRecordHoldable($marcRecord) { $pType = $this->getPType(); /** @var File_MARC_Data_Field[] $items */ $items = $marcRecord->getFields('989'); $holdable = false; $itemNumber = 0; foreach ($items as $item) { $itemNumber++; $subfield_j = $item->getSubfield('j'); if (is_object($subfield_j) && !$subfield_j->isEmpty()) { $iType = $subfield_j->getData(); } else { $iType = '0'; } $subfield_d = $item->getSubfield('d'); if (is_object($subfield_d) && !$subfield_d->isEmpty()) { $locationCode = $subfield_d->getData(); } else { $subfield_p = $item->getSubfield('p'); if (is_object($subfield_p) && !$subfield_p->isEmpty()) { $locationCode = $subfield_p->getData(); } else { $locationCode = '?????'; } } //$logger->log("$itemNumber) iType = $iType, locationCode = $locationCode", PEAR_LOG_DEBUG); //Check the determiner table to see if this matches $holdable = $this->isItemHoldableToPatron($locationCode, $iType, $pType); if ($holdable) { break; } } return $holdable; }
/** * Check all fields against the standard rules encoded in the class. * * @param File_MARC_Record $marc Record to check * * @return void */ protected function standardFieldChecks($marc) { $fieldsSeen = array(); foreach ($marc->getFields() as $current) { $tagNo = $current->getTag(); // if 880 field, inherit rules from tagno in subfield _6 if ($tagNo == 880) { if ($sub6 = $current->getSubfield(6)) { $tagNo = substr($sub6->getData(), 0, 3); $tagrules = isset($this->rules[$tagNo]) ? $this->rules[$tagNo] : null; // 880 is repeatable, but its linked field may not be if (isset($tagrules['repeatable']) && $tagrules['repeatable'] == 'NR' && isset($fieldsSeen['880.' . $tagNo])) { $this->warn("{$tagNo}: Field is not repeatable."); } $fieldsSeen['880.' . $tagNo] = isset($fieldsSeen['880.' . $tagNo]) ? $fieldsSeen['880.' . $tagNo] + 1 : 1; } else { $this->warn("880: No subfield 6."); $tagRules = null; } } else { // Default case -- not an 880 field: $tagrules = isset($this->rules[$tagNo]) ? $this->rules[$tagNo] : null; if (isset($tagrules['repeatable']) && $tagrules['repeatable'] == 'NR' && isset($fieldsSeen[$tagNo])) { $this->warn("{$tagNo}: Field is not repeatable."); } $fieldsSeen[$tagNo] = isset($fieldsSeen[$tagNo]) ? $fieldsSeen[$tagNo] + 1 : 1; } // Treat data fields differently from control fields: if (intval(ltrim($tagNo, '0')) >= 10) { if (!empty($tagrules)) { $this->checkIndicators($tagNo, $current, $tagrules); $this->checkSubfields($tagNo, $current, $tagrules); } } else { // Control field: if (strstr($current->toRaw(), chr(hexdec('1F')))) { $this->warn("{$tagNo}: Subfields are not allowed in fields lower than 010"); } } // Check to see if a checkxxx() function exists, and call it on the // field if it does $method = 'check' . $tagNo; if (method_exists($this, $method)) { $this->{$method}($current); } } }
/** * @param File_MARC_Record $marcRecord * @return bool */ function isRecordHoldable($marcRecord) { global $configArray; $pType = $this->getPType(); /** @var File_MARC_Data_Field[] $items */ $marcItemField = isset($configArray['Reindex']['itemTag']) ? $configArray['Reindex']['itemTag'] : '989'; $iTypeSubfield = isset($configArray['Reindex']['iTypeSubfield']) ? $configArray['Reindex']['iTypeSubfield'] : 'j'; $locationSubfield = isset($configArray['Reindex']['locationSubfield']) ? $configArray['Reindex']['locationSubfield'] : 'j'; $items = $marcRecord->getFields($marcItemField); $holdable = false; $itemNumber = 0; foreach ($items as $item) { $itemNumber++; $subfield_j = $item->getSubfield($iTypeSubfield); if (is_object($subfield_j) && !$subfield_j->isEmpty()) { $iType = $subfield_j->getData(); } else { $iType = '0'; } $subfield_d = $item->getSubfield($locationSubfield); if (is_object($subfield_d) && !$subfield_d->isEmpty()) { $locationCode = $subfield_d->getData(); } else { $locationCode = '?????'; } //$logger->log("$itemNumber) iType = $iType, locationCode = $locationCode", PEAR_LOG_DEBUG); //Check the determiner table to see if this matches $holdable = $this->isItemHoldableToPatron($locationCode, $iType, $pType); if ($holdable) { break; } } return $holdable; }