Exemple #1
0
 /**
  * Process parameters and display the page.
  *
  * @return void
  * @access public
  */
 public function launch()
 {
     global $interface;
     // Retrieve the record from the index
     if (!($record = $this->db->getRecord($_GET['id']))) {
         PEAR_Singleton::raiseError(new PEAR_Error('Record Does Not Exist'));
     }
     // Send basic information to the template.
     $interface->setPageTitle(isset($record['heading']) ? $record['heading'] : 'Heading unavailable.');
     $interface->assign('record', $record);
     // Load MARC data
     require_once ROOT_DIR . '/sys/MarcLoader.php';
     $marcRecord = MarcLoader::loadMarcRecordFromRecord($record);
     if (!$marcRecord) {
         PEAR_Singleton::raiseError(new PEAR_Error('Cannot Process MARC Record'));
     }
     $xml = trim($marcRecord->toXML());
     // Transform MARCXML
     $style = new DOMDocument();
     $style->load('services/Record/xsl/record-marc.xsl');
     $xsl = new XSLTProcessor();
     $xsl->importStyleSheet($style);
     $doc = new DOMDocument();
     if ($doc->loadXML($xml)) {
         $html = $xsl->transformToXML($doc);
         $interface->assign('details', $html);
     }
     // Assign the ID of the last search so the user can return to it.
     $interface->assign('lastsearch', isset($_SESSION['lastSearchURL']) ? $_SESSION['lastSearchURL'] : false);
     // Display Page
     $interface->setTemplate('record.tpl');
     $interface->display('layout.tpl');
 }
Exemple #2
0
 /**
  * @param EContentRecord $econtentRecord An eContent Record to load the Marc Record for
  * @return File_MARC_Record
  */
 public static function loadEContentMarcRecord($econtentRecord)
 {
     if ($econtentRecord->ilsId != false) {
         return MarcLoader::loadMarcRecordByILSId($econtentRecord->ilsId, 'econtentRecord');
     } else {
         return null;
     }
 }
 /**
  * @return File_MARC_Record
  */
 public function getMarcRecord()
 {
     if ($this->marcRecord == null) {
         $this->marcRecord = MarcLoader::loadMarcRecordByHooplaId($this->id);
         global $timer;
         $timer->logTime("Finished loading marc record for hoopla record {$this->id}");
     }
     return $this->marcRecord;
 }
 public function __construct($record)
 {
     // Call the parent's constructor...
     parent::__construct($record);
     // Also process the MARC record:
     require_once ROOT_DIR . '/sys/MarcLoader.php';
     $this->marcRecord = MarcLoader::loadMarcRecordFromRecord($record);
     if (!$this->marcRecord) {
         PEAR_Singleton::raiseError(new PEAR_Error('Cannot Process MARC Record for record ' . $record['id']));
     }
 }
Exemple #5
0
 function launch()
 {
     global $configArray;
     global $interface;
     //Grab the tracking data
     $recordId = $_REQUEST['id'];
     $ipAddress = $_SERVER['REMOTE_ADDR'];
     $field856Index = isset($_REQUEST['index']) ? $_REQUEST['index'] : null;
     // Setup Search Engine Connection
     $class = $configArray['Index']['engine'];
     $url = $configArray['Index']['url'];
     $this->db = new $class($url);
     // Process MARC Data
     require_once ROOT_DIR . '/sys/MarcLoader.php';
     $marcRecord = MarcLoader::loadMarcRecordByILSId($recordId);
     if ($marcRecord) {
         $this->marcRecord = $marcRecord;
     } else {
         PEAR_Singleton::raiseError(new PEAR_Error("Failed to load the MAC record for this title."));
     }
     /** @var File_MARC_Data_Field[] $linkFields */
     $linkFields = $marcRecord->getFields('856');
     if ($linkFields) {
         $cur856Index = 0;
         foreach ($linkFields as $marcField) {
             $cur856Index++;
             if ($cur856Index == $field856Index) {
                 //Get the link
                 if ($marcField->getSubfield('u')) {
                     $link = $marcField->getSubfield('u')->getData();
                     $externalLink = $link;
                 }
             }
         }
     }
     $linkParts = parse_url($externalLink);
     //Insert into the purchaseLinkTracking table
     require_once ROOT_DIR . '/sys/BotChecker.php';
     if (!BotChecker::isRequestFromBot()) {
         require_once ROOT_DIR . '/sys/ExternalLinkTracking.php';
         $externalLinkTracking = new ExternalLinkTracking();
         $externalLinkTracking->ipAddress = $ipAddress;
         $externalLinkTracking->recordId = $recordId;
         $externalLinkTracking->linkUrl = $externalLink;
         $externalLinkTracking->linkHost = $linkParts['host'];
         $result = $externalLinkTracking->insert();
     }
     //redirects them to the link they clicked
     if ($externalLink != "") {
         header("Location:" . $externalLink);
     } else {
         PEAR_Singleton::raiseError(new PEAR_Error("Failed to load link for this record."));
     }
 }
Exemple #6
0
 function downloadMarc()
 {
     $id = $_REQUEST['id'];
     $econtentRecord = new EContentRecord();
     $econtentRecord->id = $id;
     $econtentRecord->find(true);
     $marcData = MarcLoader::loadEContentMarcRecord($econtentRecord);
     header('Content-Description: File Transfer');
     header('Content-Type: application/octet-stream');
     header("Content-Disposition: attachment; filename={$econtentRecord->ilsId}.mrc");
     header('Content-Transfer-Encoding: binary');
     header('Expires: 0');
     header('Cache-Control: must-revalidate');
     header('Pragma: public');
     header('Content-Length: ' . strlen($marcData->toRaw()));
     ob_clean();
     flush();
     echo $marcData->toRaw();
 }
 static function loadDescription($eContentRecord)
 {
     global $interface;
     global $configArray;
     global $library;
     global $timer;
     $marc = MarcLoader::loadEContentMarcRecord($eContentRecord);
     $descriptionArray = array();
     //Load the description
     if (strlen($eContentRecord->description) > 0) {
         $descriptionArray['description'] = EcontentRecord_Description::trimDescription($eContentRecord->description);
     } else {
         //TODO: Check syndetics for eContent
         $descriptionArray['description'] = "Description Not Provided";
     }
     //Load publisher
     $descriptionArray['publisher'] = $eContentRecord->publisher;
     if ($descriptionArray) {
         return $descriptionArray;
     }
 }
 static function loadDescription($eContentRecord, $forSummary = false)
 {
     $descriptionArray = array();
     //Load the description
     if (strlen($eContentRecord->description) > 0) {
         $descriptionArray['description'] = EcontentRecord_Description::trimDescription($eContentRecord->description);
     } else {
         $marc = MarcLoader::loadEContentMarcRecord($eContentRecord);
         require_once ROOT_DIR . '/services/Record/Description.php';
         global $library;
         $allowExternalDescription = true;
         if (isset($library) && $library->preferSyndeticsSummary == 0) {
             $allowExternalDescription = false;
         }
         if ($forSummary) {
             $allowExternalDescription = false;
         }
         $descriptionArray = Record_Description::loadDescriptionFromMarc($marc, $allowExternalDescription);
     }
     //Load publisher
     $descriptionArray['publisher'] = $eContentRecord->publisher;
     return $descriptionArray;
 }
 private function getCoverFromMarc()
 {
     $this->log("Looking for picture as part of 856 tag.", PEAR_LOG_INFO);
     $this->initDatabaseConnection();
     //Process the marc record
     require_once ROOT_DIR . '/sys/MarcLoader.php';
     $marcRecord = MarcLoader::loadMarcRecordByILSId($this->id);
     if (!$marcRecord) {
         return false;
     }
     if ($this->configArray['Content']['loadCoversFrom856'] && $this->category && strtolower($this->category) == 'other') {
         //Get the 856 tags
         $marcFields = $marcRecord->getFields('856');
         if ($marcFields) {
             /** @var File_MARC_Data_Field $marcField */
             foreach ($marcFields as $marcField) {
                 if ($marcField->getSubfield('y')) {
                     $subfield_y = $marcField->getSubfield('y')->getData();
                     if (preg_match('/.*<img.*src=[\'"](.*?)[\'"].*>.*/i', $subfield_y, $matches)) {
                         if ($this->processImageURL($matches[1], true)) {
                             //We got a successful match
                             return true;
                         }
                     }
                 } else {
                     //no image link available on this link
                 }
             }
         }
     }
     //Check the 690 field to see if this is a seed catalog entry
     $marcFields = $marcRecord->getFields('690');
     if ($marcFields) {
         $this->log("Found 690 field", PEAR_LOG_INFO);
         foreach ($marcFields as $marcField) {
             if ($marcField->getSubfield('a')) {
                 $this->log("Found 690a subfield", PEAR_LOG_INFO);
                 $subfield_a = $marcField->getSubfield('a')->getData();
                 if (preg_match('/seed library.*/i', $subfield_a, $matches)) {
                     $this->log("Title is a seed library title", PEAR_LOG_INFO);
                     $themeName = $this->configArray['Site']['theme'];
                     $filename = "interface/themes/{$themeName}/images/seed_library_logo.jpg";
                     if ($this->processImageURL($filename, true)) {
                         return true;
                     }
                 }
             } else {
                 //no image link available on this link
             }
         }
     }
     return false;
 }
Exemple #10
0
 function launch()
 {
     global $interface;
     global $timer;
     global $configArray;
     global $user;
     //Enable and disable functionality based on library settings
     global $library;
     global $locationSingleton;
     // Setup Search Engine Connection
     $class = $configArray['Index']['engine'];
     $url = $configArray['Index']['url'];
     $this->db = new $class($url);
     if (isset($_REQUEST['searchId'])) {
         $_SESSION['searchId'] = $_REQUEST['searchId'];
         $interface->assign('searchId', $_SESSION['searchId']);
     } else {
         if (isset($_SESSION['searchId'])) {
             $interface->assign('searchId', $_SESSION['searchId']);
         }
     }
     $location = $locationSingleton->getActiveLocation();
     $showCopiesLineInHoldingsSummary = true;
     if ($library && $library->showCopiesLineInHoldingsSummary == 0) {
         $showCopiesLineInHoldingsSummary = false;
     }
     $interface->assign('showCopiesLineInHoldingsSummary', $showCopiesLineInHoldingsSummary);
     $timer->logTime('Configure UI for library and location');
     $interface->assign('overDriveVersion', isset($configArray['OverDrive']['interfaceVersion']) ? $configArray['OverDrive']['interfaceVersion'] : 1);
     $timer->logTime('Loaded Comments');
     $eContentRecord = new EContentRecord();
     $this->id = strip_tags($_REQUEST['id']);
     $eContentRecord->id = $this->id;
     if (!$eContentRecord->find(true)) {
         //TODO: display record not found error
     } else {
         $this->recordDriver = new EcontentRecordDriver();
         $this->recordDriver->setDataObject($eContentRecord);
         if ($configArray['Catalog']['ils'] == 'Millennium' || $configArray['Catalog']['ils'] == 'Sierra') {
             if (isset($eContentRecord->ilsId) && strlen($eContentRecord->ilsId) > 0) {
                 $interface->assign('classicId', substr($eContentRecord->ilsId, 1, strlen($eContentRecord->ilsId) - 2));
                 $interface->assign('classicUrl', $configArray['Catalog']['linking_url']);
             }
         }
         $this->isbn = $eContentRecord->getIsbn();
         if (is_array($this->isbn)) {
             if (count($this->isbn) > 0) {
                 $this->isbn = $this->isbn[0];
             } else {
                 $this->isbn = "";
             }
         }
         $this->issn = $eContentRecord->getPropertyArray('issn');
         if (is_array($this->issn)) {
             if (count($this->issn) > 0) {
                 $this->issn = $this->issn[0];
             } else {
                 $this->issn = "";
             }
         }
         $interface->assign('additionalAuthorsList', $eContentRecord->getPropertyArray('author2'));
         $interface->assign('lccnList', $eContentRecord->getPropertyArray('lccn'));
         $interface->assign('isbnList', $eContentRecord->getPropertyArray('isbn'));
         $interface->assign('isbn', $eContentRecord->getIsbn());
         $interface->assign('isbn10', $eContentRecord->getIsbn10());
         $interface->assign('issnList', $eContentRecord->getPropertyArray('issn'));
         $interface->assign('upcList', $eContentRecord->getPropertyArray('upc'));
         $interface->assign('seriesList', $eContentRecord->getPropertyArray('series'));
         $interface->assign('topicList', $eContentRecord->getPropertyArray('topic'));
         $interface->assign('genreList', $eContentRecord->getPropertyArray('genre'));
         $interface->assign('regionList', $eContentRecord->getPropertyArray('region'));
         $interface->assign('eraList', $eContentRecord->getPropertyArray('era'));
         $interface->assign('eContentRecord', $eContentRecord);
         $interface->assign('cleanDescription', strip_tags($eContentRecord->description, '<p><br><b><i><em><strong>'));
         $interface->assign('id', $eContentRecord->id);
         require_once ROOT_DIR . '/sys/eContent/EContentRating.php';
         $eContentRating = new EContentRating();
         $eContentRating->recordId = $eContentRecord->id;
         $interface->assign('ratingData', $eContentRating->getRatingData($user, false));
         //Determine the cover to use
         $bookCoverUrl = $configArray['Site']['coverUrl'] . "/bookcover.php?id={$eContentRecord->id}&amp;econtent=true&amp;issn={$eContentRecord->getIssn()}&amp;isn={$eContentRecord->getIsbn()}&amp;size=large&amp;upc={$eContentRecord->getUpc()}&amp;category=" . urlencode($eContentRecord->format_category()) . "&amp;format=" . urlencode($eContentRecord->getFirstFormat());
         $interface->assign('bookCoverUrl', $bookCoverUrl);
         if (isset($_REQUEST['detail'])) {
             $detail = strip_tags($_REQUEST['detail']);
             $interface->assign('defaultDetailsTab', $detail);
         }
         // Find Similar Records
         $similar = $this->db->getMoreLikeThis('econtentRecord' . $eContentRecord->id);
         $timer->logTime('Got More Like This');
         //Load the citations
         $this->loadCitation($eContentRecord);
         // Retrieve User Search History
         $interface->assign('lastsearch', isset($_SESSION['lastSearchURL']) ? $_SESSION['lastSearchURL'] : false);
         //Get Next/Previous Links
         $searchSource = isset($_REQUEST['searchSource']) ? $_REQUEST['searchSource'] : 'local';
         $searchObject = SearchObjectFactory::initSearchObject();
         $searchObject->init($searchSource);
         $searchObject->getNextPrevLinks();
         //Load notes if any
         $marcRecord = MarcLoader::loadEContentMarcRecord($eContentRecord);
         if ($marcRecord) {
             $tableOfContents = array();
             $marcFields505 = $marcRecord->getFields('505');
             if ($marcFields505) {
                 $tableOfContents = $this->processTableOfContentsFields($marcFields505);
             }
             $notes = array();
             /*$marcFields500 = $marcRecord->getFields('500');
             		$marcFields504 = $marcRecord->getFields('504');
             		$marcFields511 = $marcRecord->getFields('511');
             		$marcFields518 = $marcRecord->getFields('518');
             		$marcFields520 = $marcRecord->getFields('520');
             		if ($marcFields500 || $marcFields504 || $marcFields505 || $marcFields511 || $marcFields518 || $marcFields520){
             			$allFields = array_merge($marcFields500, $marcFields504, $marcFields511, $marcFields518, $marcFields520);
             			$notes = $this->processNoteFields($allFields);
             		}*/
             if (isset($library) && $library->showTableOfContentsTab == 0 || count($tableOfContents) == 0) {
                 $notes = array_merge($notes, $tableOfContents);
             } else {
                 $interface->assign('tableOfContents', $tableOfContents);
             }
             if (isset($library) && strlen($library->notesTabName) > 0) {
                 $interface->assign('notesTabName', $library->notesTabName);
             } else {
                 $interface->assign('notesTabName', 'Notes');
             }
             $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');
             foreach ($additionalNotesFields as $tag => $label) {
                 $marcFields = $marcRecord->getFields($tag);
                 foreach ($marcFields as $marcField) {
                     $noteText = array();
                     foreach ($marcField->getSubFields() as $subfield) {
                         $noteText[] = $subfield->getData();
                     }
                     $note = implode(',', $noteText);
                     if (strlen($note) > 0) {
                         $notes[] = "<dt>{$label}</dt><dd>" . $note . '</dd>';
                     }
                 }
             }
             if (count($notes) > 0) {
                 $interface->assign('notes', $notes);
             }
         }
         //Load subjects
         if ($marcRecord) {
             if (isset($configArray['Content']['subjectFieldsToShow'])) {
                 $subjectFieldsToShow = $configArray['Content']['subjectFieldsToShow'];
                 $subjectFields = explode(',', $subjectFieldsToShow);
                 $subjects = array();
                 $standardSubjects = array();
                 $bisacSubjects = array();
                 $oclcFastSubjects = array();
                 foreach ($subjectFields as $subjectField) {
                     /** @var File_MARC_Data_Field[] $marcFields */
                     $marcFields = $marcRecord->getFields($subjectField);
                     if ($marcFields) {
                         foreach ($marcFields as $marcField) {
                             $searchSubject = "";
                             $subject = array();
                             //Determine the type of the subject
                             $type = 'standard';
                             $subjectSource = $marcField->getSubfield('2');
                             if ($subjectSource != null) {
                                 if (preg_match('/bisac/i', $subjectSource->getData())) {
                                     $type = 'bisac';
                                 } elseif (preg_match('/fast/i', $subjectSource->getData())) {
                                     $type = 'fast';
                                 }
                             }
                             foreach ($marcField->getSubFields() as $subField) {
                                 /** @var File_MARC_Subfield $subField */
                                 if ($subField->getCode() != '2' && $subField->getCode() != '0') {
                                     $subFieldData = $subField->getData();
                                     if ($type == 'bisac' && $subField->getCode() == 'a') {
                                         $subFieldData = ucwords(strtolower($subFieldData));
                                     }
                                     $searchSubject .= " " . $subFieldData;
                                     $subject[] = array('search' => trim($searchSubject), 'title' => $subFieldData);
                                 }
                             }
                             if ($type == 'bisac') {
                                 $bisacSubjects[] = $subject;
                                 $subjects[] = $subject;
                             } elseif ($type == 'fast') {
                                 //Suppress fast subjects by default
                                 $oclcFastSubjects[] = $subject;
                             } else {
                                 $subjects[] = $subject;
                                 $standardSubjects[] = $subject;
                             }
                         }
                     }
                     $interface->assign('subjects', $subjects);
                     $interface->assign('standardSubjects', $standardSubjects);
                     $interface->assign('bisacSubjects', $bisacSubjects);
                     $interface->assign('oclcFastSubjects', $oclcFastSubjects);
                 }
             }
         } else {
             $rawSubjects = $eContentRecord->getPropertyArray('subject');
             $subjects = array();
             foreach ($rawSubjects as $subject) {
                 $explodedSubjects = explode(' -- ', $subject);
                 $searchSubject = "";
                 $subject = array();
                 foreach ($explodedSubjects as $tmpSubject) {
                     $searchSubject .= $tmpSubject . ' ';
                     $subject[] = array('search' => trim($searchSubject), 'title' => $tmpSubject);
                 }
                 $subjects[] = $subject;
             }
             $interface->assign('subjects', $subjects);
         }
         $this->loadReviews($eContentRecord);
         if (isset($_REQUEST['subsection'])) {
             $subsection = $_REQUEST['subsection'];
             if ($subsection == 'Description') {
                 $interface->assign('extendedMetadata', $this->recordDriver->getExtendedMetadata());
                 $interface->assign('subTemplate', 'view-description.tpl');
             } elseif ($subsection == 'Reviews') {
                 $interface->assign('subTemplate', 'view-reviews.tpl');
             }
         }
         //Build the actual view
         $interface->setTemplate('view.tpl');
         $interface->setPageTitle($eContentRecord->title);
         //Load Staff Details
         $interface->assign('staffDetails', $this->recordDriver->getStaffView($eContentRecord));
         // Display Page
         $interface->display('layout.tpl');
     }
 }
Exemple #11
0
 function getBasicItemInfo()
 {
     global $timer;
     global $configArray;
     $itemData = array();
     //Load basic information
     $this->id = $_GET['id'];
     $itemData['id'] = $this->id;
     // Setup Search Engine Connection
     $class = $configArray['Index']['engine'];
     $url = $configArray['Index']['url'];
     $this->db = new $class($url);
     if ($configArray['System']['debugSolr']) {
         $this->db->debug = true;
     }
     // Retrieve Full Marc Record
     if (!($record = $this->db->getRecord($this->id))) {
         PEAR_Singleton::raiseError(new PEAR_Error('Record Does Not Exist'));
     }
     $this->record = $record;
     $this->recordDriver = RecordDriverFactory::initRecordDriver($record);
     $timer->logTime('Initialized the Record Driver');
     // Process MARC Data
     if ($record['recordtype'] == 'econtentRecord') {
         require_once ROOT_DIR . '/sys/eContent/EContentRecord.php';
         $eContentRecord = new EContentRecord();
         $eContentRecord->id = substr($record['id'], strlen('econtentRecord'));
         if (!$eContentRecord->find(true)) {
             $itemData['error'] = 'Cannot load eContent Record for id ' . $record['id'];
         } else {
             $itemData['isbn'] = $eContentRecord->getIsbn();
             $itemData['issn'] = $eContentRecord->getissn();
             $itemData['upc'] = $eContentRecord->getUpc();
             $itemData['issn'] = '';
             $itemData['title'] = $record['title'];
             $itemData['author'] = $eContentRecord->author;
             $itemData['publisher'] = $eContentRecord->publisher;
             $itemData['allIsbn'] = $eContentRecord->getPropertyArray('isbn');
             $itemData['allUpc'] = $eContentRecord->getPropertyArray('upc');
             $itemData['allIssn'] = $eContentRecord->getPropertyArray('issn');
             $itemData['format'] = $eContentRecord->format();
             $itemData['formatCategory'] = $eContentRecord->format_category();
             $itemData['language'] = $eContentRecord->language;
             $itemData['cover'] = $configArray['Site']['coverUrl'] . "/bookcover.php?id={$itemData['id']}&isbn={$itemData['isbn']}&issn={$itemData['issn']}&upc={$itemData['upc']}&category={$itemData['formatCategory']}&format={$itemData['format'][0]}&size=medium";
             $itemData['description'] = $eContentRecord->description;
             require_once ROOT_DIR . '/sys/eContent/EContentRating.php';
             $eContentRating = new EContentRating();
             $eContentRating->recordId = $eContentRecord->id;
             global $user;
             $itemData['ratingData'] = $eContentRating->getRatingData($user, false);
         }
     } else {
         require_once ROOT_DIR . '/sys/MarcLoader.php';
         $marcRecord = MarcLoader::loadMarcRecordFromRecord($record);
         if ($marcRecord) {
             $this->marcRecord = $marcRecord;
         } else {
             $itemData['error'] = 'Cannot Process MARC Record';
         }
         $timer->logTime('Processed the marc record');
         // Get ISBN for cover and review use
         if ($isbnFields = $this->marcRecord->getFields('020')) {
             //Use the first good ISBN we find.
             /** @var File_MARC_Data_Field $isbnField */
             foreach ($isbnFields as $isbnField) {
                 if ($isbnSubfield = $isbnField->getSubfield('a')) {
                     $this->isbn = trim($isbnSubfield->getData());
                     if ($pos = strpos($this->isbn, ' ')) {
                         $this->isbn = substr($this->isbn, 0, $pos);
                     }
                     if (strlen($this->isbn) < 10) {
                         $this->isbn = str_pad($this->isbn, 10, "0", STR_PAD_LEFT);
                     }
                     $itemData['isbn'] = $this->isbn;
                     break;
                 }
             }
         }
         /** @var File_MARC_Data_Field $upcField */
         if ($upcField = $this->marcRecord->getField('024')) {
             if ($upcSubField = $upcField->getSubfield('a')) {
                 $this->upc = trim($upcSubField->getData());
                 $itemData['upc'] = $this->upc;
             }
         }
         /** @var File_MARC_Data_Field $issnField */
         if ($issnField = $this->marcRecord->getField('022')) {
             if ($issnSubfield = $issnField->getSubfield('a')) {
                 $this->issn = trim($issnSubfield->getData());
                 if ($pos = strpos($this->issn, ' ')) {
                     $this->issn = substr($this->issn, 0, $pos);
                 }
                 $itemData['issn'] = $this->issn;
             }
         }
         $timer->logTime('Got UPC, ISBN, and ISSN');
         //Generate basic information from the marc file to make display easier.
         $itemData['title'] = $record['title'];
         $itemData['author'] = isset($record['author']) ? $record['author'] : (isset($record['author2']) ? $record['author2'][0] : '');
         $itemData['publisher'] = $record['publisher'];
         $itemData['allIsbn'] = $record['isbn'];
         $itemData['allUpc'] = $record['upc'];
         $itemData['allIssn'] = $record['issn'];
         $itemData['issn'] = $record['issn'];
         $itemData['format'] = isset($record['format']) ? $record['format'][0] : '';
         $itemData['formatCategory'] = $record['format_category'][0];
         $itemData['language'] = $record['language'];
         $itemData['cover'] = $configArray['Site']['path'] . "/bookcover.php?id={$itemData['id']}&issn={$itemData['issn']}&isbn={$itemData['isbn']}&upc={$itemData['upc']}&category={$itemData['formatCategory']}&format={$itemData['format'][0]}";
         //Retrieve description from MARC file
         $description = '';
         /** @var File_MARC_Data_Field $descriptionField */
         if ($descriptionField = $this->marcRecord->getField('520')) {
             if ($descriptionSubfield = $descriptionField->getSubfield('a')) {
                 $description = trim($descriptionSubfield->getData());
             }
         }
         $itemData['description'] = $description;
         //setup 5 star ratings
         global $user;
         $resource = new Resource();
         $resource->record_id = $this->id;
         $resource->source = 'VuFind';
         $ratingData = $resource->getRatingData($user);
         $itemData['ratingData'] = $ratingData;
         $timer->logTime('Got 5 star data');
     }
     return $itemData;
 }
 /**
  * Load status (holdings) for a record and filter them based on the logged in user information.
  *
  * Format of return array is:
  * key = {section#}{location}-### where ### is the holding iteration
  *
  * value = array (
  *  id = The id of the bib
  *  number = The position of the holding within the original list of holdings
  *  section = A description of the section
  *  sectionId = a numeric id of the section for sorting
  *  type = holding
  *  status
  *  statusfull
  *  availability
  *  holdable
  *  nonHoldableReason
  *  reserve
  *  holdQueueLength
  *  duedate
  *  location
  *  libraryDisplayName
  *  locationLink
  *  callnumber
  *  link = array
  *  linkText
  *  isDownload
  * )
  *
  * Includes both physical titles as well as titles on order
  *
  * @param string            $id     the id of the record
  * @return array A list of holdings for the record
  */
 public function getStatus($id)
 {
     if (array_key_exists($id, MillenniumStatusLoader::$loadedStatus)) {
         return MillenniumStatusLoader::$loadedStatus[$id];
     }
     global $library;
     global $user;
     global $timer;
     global $logger;
     global $configArray;
     $pType = $this->driver->getPType();
     $scope = $this->driver->getMillenniumScope();
     if (!$configArray['Catalog']['offline']) {
         //Get information about holdings, order information, and issue information
         $millenniumInfo = $this->driver->getMillenniumRecordInfo($id);
         //Get the number of holds
         if ($millenniumInfo->framesetInfo) {
             if (preg_match('/(\\d+) hold(s?) on .*? of \\d+ (copies|copy)/', $millenniumInfo->framesetInfo, $matches)) {
                 $holdQueueLength = $matches[1];
             } else {
                 $holdQueueLength = 0;
             }
         }
         // Load Record Page
         $r = substr($millenniumInfo->holdingsInfo, stripos($millenniumInfo->holdingsInfo, 'bibItems'));
         $r = substr($r, strpos($r, ">") + 1);
         $r = substr($r, 0, stripos($r, "</table"));
         $rows = preg_split("/<tr([^>]*)>/", $r);
     } else {
         $rows = array();
         $millenniumInfo = null;
     }
     //Load item information from marc record
     $matchItemsWithMarcItems = $configArray['Catalog']['matchItemsWithMarcItems'];
     if ($matchItemsWithMarcItems) {
         // Load the full marc record so we can get the iType for each record.
         $marcRecord = MarcLoader::loadMarcRecordByILSId($id);
         $marcItemField = isset($configArray['Reindex']['itemTag']) ? $configArray['Reindex']['itemTag'] : '989';
         $itemFields = $marcRecord->getFields($marcItemField);
         $marcItemData = array();
         //TODO: Don't hardcode item subfields
         $statusSubfield = $configArray['Reindex']['statusSubfield'];
         $dueDateSubfield = $configArray['Reindex']['dueDateSubfield'];
         $locationSubfield = $configArray['Reindex']['locationSubfield'];
         $iTypeSubfield = $configArray['Reindex']['iTypeSubfield'];
         $callNumberPrestampSubfield = $configArray['Reindex']['callNumberPrestampSubfield'];
         $callNumberSubfield = $configArray['Reindex']['callNumberSubfield'];
         $callNumberCutterSubfield = $configArray['Reindex']['callNumberCutterSubfield'];
         $callNumberPoststampSubfield = $configArray['Reindex']['callNumberPoststampSubfield'];
         $volumeSubfield = $configArray['Reindex']['volumeSubfield'];
         $lastCheckinDateSubfield = $configArray['Reindex']['lastCheckinDateSubfield'];
         // added plb 3-24-2015
         foreach ($itemFields as $itemField) {
             /** @var $itemField File_MARC_Data_Field */
             $fullCallNumber = $itemField->getSubfield($callNumberPrestampSubfield) != null ? $itemField->getSubfield($callNumberPrestampSubfield)->getData() . ' ' : '';
             $fullCallNumber .= $itemField->getSubfield($callNumberSubfield) != null ? $itemField->getSubfield($callNumberSubfield)->getData() : '';
             $fullCallNumber .= $itemField->getSubfield($callNumberCutterSubfield) != null ? ' ' . $itemField->getSubfield($callNumberCutterSubfield)->getData() : '';
             $fullCallNumber .= $itemField->getSubfield($callNumberPoststampSubfield) != null ? ' ' . $itemField->getSubfield($callNumberPoststampSubfield)->getData() : '';
             $fullCallNumber .= $itemField->getSubfield($volumeSubfield) != null ? ' ' . $itemField->getSubfield($volumeSubfield)->getData() : '';
             $fullCallNumber = str_replace('  ', ' ', $fullCallNumber);
             $itemData['callnumber'] = $fullCallNumber;
             $itemData['location'] = $itemField->getSubfield($locationSubfield) != null ? trim($itemField->getSubfield($locationSubfield)->getData()) : '?????';
             $itemData['iType'] = $itemField->getSubfield($iTypeSubfield) != null ? $itemField->getSubfield($iTypeSubfield)->getData() : '-1';
             $itemData['matched'] = false;
             $itemData['status'] = $itemField->getSubfield($statusSubfield) != null ? $itemField->getSubfield($statusSubfield)->getData() : '-';
             $itemData['dueDate'] = $itemField->getSubfield($dueDateSubfield) != null ? trim($itemField->getSubfield($dueDateSubfield)->getData()) : null;
             $lastCheckinDate = $itemField->getSubfield($lastCheckinDateSubfield);
             // added plb 3-24-2015
             if ($lastCheckinDate) {
                 // convert to timestamp for ease of display in template
                 $lastCheckinDate = trim($lastCheckinDate->getData());
                 $lastCheckinDate = DateTime::createFromFormat('m-d-Y G:i', $lastCheckinDate);
                 if ($lastCheckinDate) {
                     $lastCheckinDate = $lastCheckinDate->getTimestamp();
                 }
             }
             $itemData['lastCheckinDate'] = $lastCheckinDate ? $lastCheckinDate : null;
             $marcItemData[] = $itemData;
         }
     } else {
         $marcItemData = array();
         $marcRecord = null;
     }
     if (!$configArray['Catalog']['offline']) {
         //Process each row in the callnumber table.
         $ret = $this->parseHoldingRows($id, $rows);
         if (count($ret) == 0) {
             //Also check the frameset for links
             if (preg_match('/<div class="bibDisplayUrls">.*?<table.*?>(.*?)<\\/table>.*?<\\/div>/si', $millenniumInfo->framesetInfo, $displayUrlInfo)) {
                 $linksTable = $displayUrlInfo[1];
                 preg_match_all('/<td.*?>.*?<a href="(.*?)".*?>(.*?)<\\/a>.*?<\\/td>/si', $linksTable, $linkData, PREG_SET_ORDER);
                 for ($i = 0; $i < count($linkData); $i++) {
                     $linkText = $linkData[$i][2];
                     if ($linkText != 'Latest Received') {
                         $newHolding = array('type' => 'holding', 'link' => array(), 'status' => 'Online', 'location' => 'Online');
                         $newHolding['link'][] = array('link' => $linkData[$i][1], 'linkText' => $linkText, 'isDownload' => true);
                         $ret[] = $newHolding;
                     }
                 }
             }
         }
         $timer->logTime('processed all holdings rows');
     } else {
         $ret = null;
     }
     global $locationSingleton;
     /** @var $locationSingleton Location */
     $physicalLocation = $locationSingleton->getPhysicalLocation();
     if ($physicalLocation != null) {
         $physicalBranch = $physicalLocation->holdingBranchLabel;
     } else {
         $physicalBranch = '';
     }
     $homeBranch = '';
     $homeBranchId = 0;
     $nearbyBranch1 = '';
     $nearbyBranch1Id = 0;
     $nearbyBranch2 = '';
     $nearbyBranch2Id = 0;
     //Set location information based on the user login.  This will override information based
     if (isset($user) && $user != false) {
         $homeBranchId = $user->homeLocationId;
         $nearbyBranch1Id = $user->myLocation1Id;
         $nearbyBranch2Id = $user->myLocation2Id;
     } else {
         //Check to see if the cookie for home location is set.
         if (isset($_COOKIE['home_location']) && is_numeric($_COOKIE['home_location'])) {
             $cookieLocation = new Location();
             $locationId = $_COOKIE['home_location'];
             $cookieLocation->whereAdd("locationId = '{$locationId}'");
             $cookieLocation->find();
             if ($cookieLocation->N == 1) {
                 $cookieLocation->fetch();
                 $homeBranchId = $cookieLocation->locationId;
                 $nearbyBranch1Id = $cookieLocation->nearbyLocation1;
                 $nearbyBranch2Id = $cookieLocation->nearbyLocation2;
             }
         }
     }
     //Load the holding label for the user's home location.
     $userLocation = new Location();
     $userLocation->whereAdd("locationId = '{$homeBranchId}'");
     $userLocation->find();
     if ($userLocation->N == 1) {
         $userLocation->fetch();
         $homeBranch = $userLocation->holdingBranchLabel;
     }
     //Load nearby branch 1
     $nearbyLocation1 = new Location();
     $nearbyLocation1->whereAdd("locationId = '{$nearbyBranch1Id}'");
     $nearbyLocation1->find();
     if ($nearbyLocation1->N == 1) {
         $nearbyLocation1->fetch();
         $nearbyBranch1 = $nearbyLocation1->holdingBranchLabel;
     }
     //Load nearby branch 2
     $nearbyLocation2 = new Location();
     $nearbyLocation2->whereAdd();
     $nearbyLocation2->whereAdd("locationId = '{$nearbyBranch2Id}'");
     $nearbyLocation2->find();
     if ($nearbyLocation2->N == 1) {
         $nearbyLocation2->fetch();
         $nearbyBranch2 = $nearbyLocation2->holdingBranchLabel;
     }
     $sorted_array = array();
     //Get a list of the display names for all locations based on holding label.
     $locationLabels = array();
     $location = new Location();
     $location->find();
     $libraryLocationLabels = array();
     $locationCodes = array();
     $suppressedLocationCodes = array();
     while ($location->fetch()) {
         if (strlen($location->holdingBranchLabel) > 0 && $location->holdingBranchLabel != '???') {
             if ($library && $library->libraryId == $location->libraryId) {
                 $cleanLabel = str_replace('/', '\\/', $location->holdingBranchLabel);
                 $libraryLocationLabels[] = str_replace('.', '\\.', $cleanLabel);
             }
             $locationLabels[$location->holdingBranchLabel] = $location->displayName;
             $locationCodes[$location->code] = $location->holdingBranchLabel;
             if ($location->suppressHoldings == 1) {
                 $suppressedLocationCodes[$location->code] = $location->code;
             }
         }
     }
     if (count($libraryLocationLabels) > 0) {
         $libraryLocationLabels = '/^(' . join('|', $libraryLocationLabels) . ').*/i';
     } else {
         $libraryLocationLabels = '';
     }
     //Get the current Ptype for later usage.
     $timer->logTime('setup for additional holdings processing.');
     //Now that we have the holdings, we need to filter and sort them according to scoping rules.
     if (!$configArray['Catalog']['offline']) {
         $i = 0;
         foreach ($ret as $holdingKey => $holding) {
             $holding['type'] = 'holding';
             //Process holdings without call numbers - Need to show items without call numbers
             //because they may have links, etc.  Also show if there is a status.  Since some
             //In process items may not have a call number yet.
             if ((!isset($holding['callnumber']) || strlen($holding['callnumber']) == 0) && (!isset($holding['link']) || count($holding['link']) == 0) && !isset($holding['status'])) {
                 continue;
             }
             //Determine if the holding is available or not.
             //First check the status
             if (preg_match('/^(' . $this->driver->availableStatiRegex . ')$/', $holding['status'])) {
                 $holding['availability'] = 1;
             } else {
                 $holding['availability'] = 0;
             }
             if (preg_match('/^(' . $this->driver->holdableStatiRegex . ')$/', $holding['status'])) {
                 $holding['holdable'] = 1;
             } else {
                 $holding['holdable'] = 0;
                 $holding['nonHoldableReason'] = "This item is not currently available for Patron Holds";
             }
             if (!isset($holding['libraryDisplayName'])) {
                 $holding['libraryDisplayName'] = $holding['location'];
             }
             //Get the location id for this holding
             $holding['locationCode'] = '?????';
             foreach ($locationCodes as $locationCode => $holdingLabel) {
                 if (strlen($locationCode) > 0 && preg_match("~{$holdingLabel}~i", $holding['location'])) {
                     $holding['locationCode'] = $locationCode;
                     break;
                 }
             }
             if ($holding['locationCode'] == '?????') {
                 $logger->log("Did not find location code for " . $holding['location'] . " record {$id}", PEAR_LOG_DEBUG);
             }
             if (array_key_exists($holding['locationCode'], $suppressedLocationCodes)) {
                 $logger->log("Location " . $holding['locationCode'] . " is suppressed", PEAR_LOG_DEBUG);
                 continue;
             }
             //Now that we have the location code, try to match with the marc record
             $holding['iType'] = 0;
             if ($matchItemsWithMarcItems) {
                 foreach ($marcItemData as $itemKey => $itemData) {
                     if ($itemData['matched'] === false) {
                         // ensure not checked already
                         $locationMatched = strpos($itemData['location'], $holding['locationCode']) === 0;
                         $itemCallNumber = isset($itemData['callnumber']) ? $itemData['callnumber'] : '';
                         $holdingCallNumber = isset($holding['callnumber']) ? $holding['callnumber'] : '';
                         if (strlen($itemCallNumber) == 0 || strlen($holding['callnumber']) == 0) {
                             $callNumberMatched = strlen($itemCallNumber) == strlen($holdingCallNumber);
                         } else {
                             $callNumberMatched = strpos($itemCallNumber, $holdingCallNumber) >= 0;
                         }
                         if ($locationMatched && $callNumberMatched) {
                             $holding['iType'] = $itemData['iType'];
                             $holding['lastCheckinDate'] = $itemData['lastCheckinDate'];
                             // if the marc record matches up, include the last checkin date in the holding info.
                             //Get the more specific location code
                             if (strlen($holding['locationCode']) < strlen($itemData['location'])) {
                                 $holding['locationCode'] = $itemData['location'];
                             }
                             $itemData['matched'] = true;
                             $marcItemData[$itemKey] = $itemData;
                             // add matched sub-array element back to original array being looped over.
                             break;
                         }
                     }
                 }
                 //Check to see if this item can be held by the current patron.  Only important when
                 //we know what pType is in use and we are showing all items.
                 if ($scope == $this->driver->getDefaultScope() && $pType >= 0) {
                     //Never remove the title if it is owned by the current library (could be in library use only)
                     if (isset($library) && strlen($library->ilsCode) > 0 && strpos($holding['locationCode'], $library->ilsCode) === 0) {
                         //$logger->log("Cannot remove holding because it belongs to the active library", PEAR_LOG_DEBUG);
                     } else {
                         if (!$this->driver->isItemHoldableToPatron($holding['locationCode'], $holding['iType'], $pType)) {
                             //$logger->log("Removing item $holdingKey because it is not usable by the current patronType $pType, iType is {$holding['iType']}, location is {$holding['locationCode']}", PEAR_LOG_DEBUG);
                             //echo("Removing item $holdingKey because it is not usable by the current patronType $pType, iType is {$holding['iType']}, location is {$holding['locationCode']}");
                             unset($ret[$holdingKey]);
                             continue;
                         }
                     }
                 } else {
                     if ($pType >= 0 && $holding['holdable'] == 1) {
                         //We won't want to remove titles based on holdability, but we do want to check if it is holdable
                         if (!$this->driver->isItemHoldableToPatron($holding['locationCode'], $holding['iType'], $pType)) {
                             $holding['holdable'] = 0;
                         }
                     }
                 }
             }
             //Set the hold queue length
             $holding['holdQueueLength'] = isset($holdQueueLength) ? $holdQueueLength : null;
             //Add the holding to the sorted array to determine
             $paddedNumber = str_pad($i, 3, '0', STR_PAD_LEFT);
             $sortString = $holding['location'] . '-' . $paddedNumber;
             //$sortString = $holding['location'] . $holding['callnumber']. $i;
             if (strlen($physicalBranch) > 0 && stripos($holding['location'], $physicalBranch) !== false) {
                 //If the user is in a branch, those holdings come first.
                 $holding['section'] = 'In this library';
                 $holding['sectionId'] = 1;
                 $sorted_array['1' . $sortString] = $holding;
             } else {
                 if (strlen($homeBranch) > 0 && stripos($holding['location'], $homeBranch) !== false) {
                     //Next come the user's home branch if the user is logged in or has the home_branch cookie set.
                     $holding['section'] = 'Your library';
                     $holding['sectionId'] = 2;
                     $sorted_array['2' . $sortString] = $holding;
                 } else {
                     if (strlen($nearbyBranch1) > 0 && stripos($holding['location'], $nearbyBranch1) !== false) {
                         //Next come nearby locations for the user
                         $holding['section'] = 'Nearby Libraries';
                         $holding['sectionId'] = 3;
                         $sorted_array['3' . $sortString] = $holding;
                     } else {
                         if (strlen($nearbyBranch2) > 0 && stripos($holding['location'], $nearbyBranch2) !== false) {
                             //Next come nearby locations for the user
                             $holding['section'] = 'Nearby Libraries';
                             $holding['sectionId'] = 4;
                             $sorted_array['4' . $sortString] = $holding;
                         } else {
                             if (strlen($libraryLocationLabels) > 0 && preg_match($libraryLocationLabels, $holding['location'])) {
                                 //Next come any locations within the same system we are in.
                                 $holding['section'] = $library->displayName;
                                 $holding['sectionId'] = 5;
                                 $sorted_array['5' . $sortString] = $holding;
                             } else {
                                 //Finally, all other holdings are shown sorted alphabetically.
                                 $holding['section'] = 'Other Locations';
                                 $holding['sectionId'] = 6;
                                 $sorted_array['6' . $sortString] = $holding;
                             }
                         }
                     }
                 }
             }
             $i++;
         }
     } else {
         $i = 0;
         //Offline circ, process each item in the marc record
         foreach ($marcItemData as $marcData) {
             $i++;
             $holding = array();
             $holding['type'] = 'holding';
             $holding['locationCode'] = $marcData['location'];
             $holding['callnumber'] = $marcData['callnumber'];
             $holding['statusfull'] = $this->translateStatusCode($marcData['status'], $marcData['dueDate']);
             $holding['lastCheckinDate'] = $marcData['lastCheckinDate'];
             //Try to translate the location code at least to location
             $location = new Location();
             $location->whereAdd("LOCATE(code, '{$marcData['location']}') = 1");
             if ($location->find(true)) {
                 $holding['location'] = $location->displayName;
             } else {
                 $holding['location'] = $marcData['location'];
             }
             if (array_key_exists($holding['locationCode'], $suppressedLocationCodes)) {
                 $logger->log("Location " . $holding['locationCode'] . " is suppressed", PEAR_LOG_DEBUG);
                 continue;
             }
             $holding['iType'] = $marcData['iType'];
             if ($marcData['status'] == '-' && $marcData['dueDate'] == null) {
                 $holding['availability'] = 1;
             } else {
                 $holding['availability'] = 0;
             }
             //Check to see if this item can be held by the current patron.  Only important when
             //we know what pType is in use and we are showing all items.
             if ($scope == $this->driver->getDefaultScope() && $pType > 0) {
                 //Never remove the title if it is owned by the current library (could be in library use only)
                 if (isset($library) && strlen($library->ilsCode) > 0 && strpos($holding['locationCode'], $library->ilsCode) === 0) {
                     //$logger->log("Cannot remove holding because it belongs to the active library", PEAR_LOG_DEBUG);
                 } else {
                     if (!$this->driver->isItemHoldableToPatron($holding['locationCode'], $holding['iType'], $pType)) {
                         //$logger->log("Removing item because it is not usable by the current patronType $pType, iType is {$holding['iType']}, location is {$holding['locationCode']}", PEAR_LOG_DEBUG);
                         //echo("Removing item $holdingKey because it is not usable by the current patronType $pType, iType is {$holding['iType']}, location is {$holding['locationCode']}");
                         continue;
                     }
                 }
             }
             $paddedNumber = str_pad($i, 3, '0', STR_PAD_LEFT);
             $sortString = $holding['location'] . '-' . $paddedNumber;
             if (strlen($physicalBranch) > 0 && stripos($holding['location'], $physicalBranch) !== false) {
                 //If the user is in a branch, those holdings come first.
                 $holding['section'] = 'In this library';
                 $holding['sectionId'] = 1;
                 $sorted_array['1' . $sortString] = $holding;
             } else {
                 if (strlen($homeBranch) > 0 && stripos($holding['location'], $homeBranch) !== false) {
                     //Next come the user's home branch if the user is logged in or has the home_branch cookie set.
                     $holding['section'] = 'Your library';
                     $holding['sectionId'] = 2;
                     $sorted_array['2' . $sortString] = $holding;
                 } else {
                     if (strlen($nearbyBranch1) > 0 && stripos($holding['location'], $nearbyBranch1) !== false) {
                         //Next come nearby locations for the user
                         $holding['section'] = 'Nearby Libraries';
                         $holding['sectionId'] = 3;
                         $sorted_array['3' . $sortString] = $holding;
                     } else {
                         if (strlen($nearbyBranch2) > 0 && stripos($holding['location'], $nearbyBranch2) !== false) {
                             //Next come nearby locations for the user
                             $holding['section'] = 'Nearby Libraries';
                             $holding['sectionId'] = 4;
                             $sorted_array['4' . $sortString] = $holding;
                         } else {
                             if (strlen($libraryLocationLabels) > 0 && preg_match($libraryLocationLabels, $holding['location'])) {
                                 //Next come any locations within the same system we are in.
                                 $holding['section'] = $library->displayName;
                                 $holding['sectionId'] = 5;
                                 $sorted_array['5' . $sortString] = $holding;
                             } else {
                                 //Finally, all other holdings are shown sorted alphabetically.
                                 $holding['section'] = 'Other Locations';
                                 $holding['sectionId'] = 6;
                                 $sorted_array['6' . $sortString] = $holding;
                             }
                         }
                     }
                 }
             }
         }
     }
     $timer->logTime('finished processing holdings');
     //Check to see if the title is holdable
     $holdable = $this->driver->isRecordHoldable($marcRecord);
     foreach ($sorted_array as $key => $holding) {
         //Do not override holdability based on status
         if (isset($holding['holdable']) && $holding['holdable'] == 1) {
             $holding['holdable'] = $holdable ? 1 : 0;
             $sorted_array[$key] = $holding;
         }
     }
     if (!$configArray['Catalog']['offline']) {
         //Load order records, these only show in the full page view, not the item display
         $orderMatches = array();
         if (preg_match_all('/<tr\\s+class="bibOrderEntry">.*?<td\\s*>(.*?)<\\/td>/s', $millenniumInfo->framesetInfo, $orderMatches)) {
             for ($i = 0; $i < count($orderMatches[1]); $i++) {
                 $location = trim($orderMatches[1][$i]);
                 $location = preg_replace('/\\sC\\d{3}\\w{0,2}[\\s\\.]/', '', $location);
                 //Remove courier code if any
                 $sorted_array['7' . $location . $i] = array('location' => $location, 'section' => 'On Order', 'sectionId' => 7, 'holdable' => 1);
             }
         }
         $timer->logTime('loaded order records');
     }
     ksort($sorted_array);
     //Check to see if we can remove the sections.
     //We can if all section keys are the same.
     $removeSection = true;
     $lastKeyIndex = '';
     foreach ($sorted_array as $key => $holding) {
         $currentKey = substr($key, 0, 1);
         if ($lastKeyIndex == '') {
             $lastKeyIndex = $currentKey;
         } else {
             if ($lastKeyIndex != $currentKey) {
                 $removeSection = false;
                 break;
             }
         }
     }
     foreach ($sorted_array as $key => $holding) {
         if ($removeSection == true) {
             $holding['section'] = '';
             $sorted_array[$key] = $holding;
         }
     }
     if (!$configArray['Catalog']['offline']) {
         $issueSummaries = $this->driver->getIssueSummaries($millenniumInfo);
     } else {
         $issueSummaries = null;
     }
     $timer->logTime('loaded issue summaries');
     if (!is_null($issueSummaries)) {
         krsort($sorted_array);
         //Group holdings under the issue issue summary that is related.
         foreach ($sorted_array as $key => $holding) {
             //Have issue summary = false
             $haveIssueSummary = false;
             $issueSummaryKey = null;
             foreach ($issueSummaries as $issueKey => $issueSummary) {
                 if ($issueSummary['location'] == $holding['location']) {
                     $haveIssueSummary = true;
                     $issueSummaryKey = $issueKey;
                     break;
                 }
             }
             if ($haveIssueSummary) {
                 $issueSummaries[$issueSummaryKey]['holdings'][strtolower($key)] = $holding;
             } else {
                 //Need to automatically add a summary so we don't lose data
                 $issueSummaries[$holding['location']] = array('location' => $holding['location'], 'type' => 'issue', 'holdings' => array(strtolower($key) => $holding));
             }
         }
         foreach ($issueSummaries as $key => $issueSummary) {
             if (isset($issueSummary['holdings']) && is_array($issueSummary['holdings'])) {
                 krsort($issueSummary['holdings']);
                 $issueSummaries[$key] = $issueSummary;
             }
         }
         ksort($issueSummaries);
         $status = $issueSummaries;
     } else {
         $status = $sorted_array;
     }
     MillenniumStatusLoader::$loadedStatus[$id] = $status;
     return $status;
 }
Exemple #13
0
 function __construct($subAction = false, $record_id = null)
 {
     global $interface;
     global $configArray;
     global $library;
     global $timer;
     global $logger;
     $interface->assign('page_body_style', 'sidebar_left');
     $interface->assign('libraryThingUrl', $configArray['LibraryThing']['url']);
     //Determine whether or not materials request functionality should be enabled
     $interface->assign('enableMaterialsRequest', MaterialsRequest::enableMaterialsRequest());
     //Load basic information needed in subclasses
     if ($record_id == null || !isset($record_id)) {
         $this->id = $_GET['id'];
     } else {
         $this->id = $record_id;
     }
     //Check to see if the record exists within the resources table
     $resource = new Resource();
     $resource->record_id = $this->id;
     $resource->source = 'VuFind';
     $resource->deleted = 0;
     if (!$resource->find()) {
         //Check to see if the record has been converted to an eContent record
         require_once ROOT_DIR . '/sys/eContent/EContentRecord.php';
         $econtentRecord = new EContentRecord();
         $econtentRecord->ilsId = $this->id;
         $econtentRecord->status = 'active';
         if ($econtentRecord->find(true)) {
             header("Location: /EcontentRecord/{$econtentRecord->id}/Home");
             die;
         }
         $logger->log("Did not find a record for id {$this->id} in resources table.", PEAR_LOG_DEBUG);
         $interface->setTemplate('invalidRecord.tpl');
         $interface->display('layout.tpl');
         die;
     }
     if ($configArray['Catalog']['ils'] == 'Millennium') {
         $interface->assign('classicId', substr($this->id, 1, strlen($this->id) - 2));
         $interface->assign('classicUrl', $configArray['Catalog']['linking_url']);
     }
     // Setup Search Engine Connection
     $class = $configArray['Index']['engine'];
     $url = $configArray['Index']['url'];
     $this->db = new $class($url);
     $this->db->disableScoping();
     // Retrieve Full Marc Record
     if (!($record = $this->db->getRecord($this->id))) {
         $logger->log("Did not find a record for id {$this->id} in solr.", PEAR_LOG_DEBUG);
         $interface->setTemplate('invalidRecord.tpl');
         $interface->display('layout.tpl');
         die;
     }
     $this->db->enableScoping();
     $this->record = $record;
     $interface->assign('record', $record);
     $this->recordDriver = RecordDriverFactory::initRecordDriver($record);
     $timer->logTime('Initialized the Record Driver');
     $interface->assign('coreMetadata', $this->recordDriver->getCoreMetadata());
     // Process MARC Data
     require_once ROOT_DIR . '/sys/MarcLoader.php';
     $marcRecord = MarcLoader::loadMarcRecordFromRecord($record);
     if ($marcRecord) {
         $this->marcRecord = $marcRecord;
         $interface->assign('marc', $marcRecord);
     } else {
         $interface->assign('error', 'Cannot Process MARC Record');
     }
     $timer->logTime('Processed the marc record');
     //Load information for display in the template rather than processing specific fields in the template
     $marcField = $marcRecord->getField('245');
     $recordTitle = $this->getSubfieldData($marcField, 'a');
     $interface->assign('recordTitle', $recordTitle);
     $recordTitleSubtitle = trim($this->concatenateSubfieldData($marcField, array('a', 'b', 'h', 'n', 'p')));
     $recordTitleSubtitle = preg_replace('~\\s+[\\/:]$~', '', $recordTitleSubtitle);
     $interface->assign('recordTitleSubtitle', $recordTitleSubtitle);
     $recordTitleWithAuth = trim($this->concatenateSubfieldData($marcField, array('a', 'b', 'h', 'n', 'p', 'c')));
     $interface->assign('recordTitleWithAuth', $recordTitleWithAuth);
     $marcField = $marcRecord->getField('100');
     if ($marcField) {
         $mainAuthor = $this->concatenateSubfieldData($marcField, array('a', 'b', 'c', 'd'));
         $interface->assign('mainAuthor', $mainAuthor);
     }
     $marcField = $marcRecord->getField('110');
     if ($marcField) {
         $corporateAuthor = $this->getSubfieldData($marcField, 'a');
         $interface->assign('corporateAuthor', $corporateAuthor);
     }
     $marcFields = $marcRecord->getFields('700');
     if ($marcFields) {
         $contributors = array();
         foreach ($marcFields as $marcField) {
             $contributors[] = $this->concatenateSubfieldData($marcField, array('a', 'b', 'c', 'd'));
         }
         $interface->assign('contributors', $contributors);
     }
     $published = $this->recordDriver->getPublicationDetails();
     $interface->assign('published', $published);
     $marcFields = $marcRecord->getFields('250');
     if ($marcFields) {
         $editionsThis = array();
         foreach ($marcFields as $marcField) {
             $editionsThis[] = $this->getSubfieldData($marcField, 'a');
         }
         $interface->assign('editionsThis', $editionsThis);
     }
     $marcFields = $marcRecord->getFields('300');
     if ($marcFields) {
         $physicalDescriptions = array();
         foreach ($marcFields as $marcField) {
             $description = $this->concatenateSubfieldData($marcField, array('a', 'b', 'c', 'e', 'f', 'g'));
             if ($description != 'p. cm.') {
                 $description = preg_replace("/[\\/|;:]\$/", '', $description);
                 $description = preg_replace("/p\\./", 'pages', $description);
                 $physicalDescriptions[] = $description;
             }
         }
         $interface->assign('physicalDescriptions', $physicalDescriptions);
     }
     // Get ISBN for cover and review use
     $mainIsbnSet = false;
     /** @var File_MARC_Data_Field[] $isbnFields */
     if ($isbnFields = $this->marcRecord->getFields('020')) {
         $isbns = array();
         //Use the first good ISBN we find.
         foreach ($isbnFields as $isbnField) {
             /** @var File_MARC_Subfield $isbnSubfieldA */
             if ($isbnSubfieldA = $isbnField->getSubfield('a')) {
                 $tmpIsbn = trim($isbnSubfieldA->getData());
                 if (strlen($tmpIsbn) > 0) {
                     $isbns[] = $isbnSubfieldA->getData();
                     $pos = strpos($tmpIsbn, ' ');
                     if ($pos > 0) {
                         $tmpIsbn = substr($tmpIsbn, 0, $pos);
                     }
                     $tmpIsbn = trim($tmpIsbn);
                     if (strlen($tmpIsbn) > 0) {
                         if (strlen($tmpIsbn) < 10) {
                             $tmpIsbn = str_pad($tmpIsbn, 10, "0", STR_PAD_LEFT);
                         }
                         if (!$mainIsbnSet) {
                             $this->isbn = $tmpIsbn;
                             $interface->assign('isbn', $tmpIsbn);
                             $mainIsbnSet = true;
                         }
                     }
                 }
             }
         }
         if (isset($this->isbn)) {
             if (strlen($this->isbn) == 13) {
                 require_once ROOT_DIR . '/Drivers/marmot_inc/ISBNConverter.php';
                 $this->isbn10 = ISBNConverter::convertISBN13to10($this->isbn);
             } else {
                 $this->isbn10 = $this->isbn;
             }
             $interface->assign('isbn10', $this->isbn10);
         }
         $interface->assign('isbns', $isbns);
     }
     if ($upcField = $this->marcRecord->getField('024')) {
         /** @var File_MARC_Data_Field $upcField */
         if ($upcSubField = $upcField->getSubfield('a')) {
             $this->upc = trim($upcSubField->getData());
             $interface->assign('upc', $this->upc);
         }
     }
     if ($issnField = $this->marcRecord->getField('022')) {
         /** @var File_MARC_Data_Field $issnField */
         if ($issnSubField = $issnField->getSubfield('a')) {
             $this->issn = trim($issnSubField->getData());
             if ($pos = strpos($this->issn, ' ')) {
                 $this->issn = substr($this->issn, 0, $pos);
             }
             $interface->assign('issn', $this->issn);
             //Also setup GoldRush link
             if (isset($library) && strlen($library->goldRushCode) > 0) {
                 $interface->assign('goldRushLink', "http://goldrush.coalliance.org/index.cfm?fuseaction=Search&amp;inst_code={$library->goldRushCode}&amp;search_type=ISSN&amp;search_term={$this->issn}");
             }
         }
     }
     $timer->logTime("Got basic data from Marc Record subaction = {$subAction}, record_id = {$record_id}");
     //stop if this is not the main action.
     if ($subAction == true) {
         return;
     }
     //Get street date
     if ($streetDateField = $this->marcRecord->getField('263')) {
         $streetDate = $this->getSubfieldData($streetDateField, 'a');
         if ($streetDate != '') {
             $interface->assign('streetDate', $streetDate);
         }
     }
     /** @var File_MARC_Data_Field[] $marcField440 */
     $marcField440 = $marcRecord->getFields('440');
     /** @var File_MARC_Data_Field[] $marcField490 */
     $marcField490 = $marcRecord->getFields('490');
     /** @var File_MARC_Data_Field[] $marcField830 */
     $marcField830 = $marcRecord->getFields('830');
     if ($marcField440 || $marcField490 || $marcField830) {
         $series = array();
         foreach ($marcField440 as $field) {
             $series[] = $this->getSubfieldData($field, 'a');
         }
         foreach ($marcField490 as $field) {
             if ($field->getIndicator(1) == 0) {
                 $series[] = $this->getSubfieldData($field, 'a');
             }
         }
         foreach ($marcField830 as $field) {
             $series[] = $this->getSubfieldData($field, 'a');
         }
         $interface->assign('series', $series);
     }
     //Load description from Syndetics
     $useMarcSummary = true;
     if ($this->isbn || $this->upc) {
         if ($library && $library->preferSyndeticsSummary == 1) {
             require_once ROOT_DIR . '/Drivers/marmot_inc/GoDeeperData.php';
             $summaryInfo = GoDeeperData::getSummary($this->isbn, $this->upc);
             if (isset($summaryInfo['summary'])) {
                 $interface->assign('summaryTeaser', $summaryInfo['summary']);
                 $interface->assign('summary', $summaryInfo['summary']);
                 $useMarcSummary = false;
             }
         }
     }
     if ($useMarcSummary) {
         if ($summaryField = $this->marcRecord->getField('520')) {
             $interface->assign('summary', $this->getSubfieldData($summaryField, 'a'));
             $interface->assign('summaryTeaser', $this->getSubfieldData($summaryField, 'a'));
         } elseif ($library && $library->preferSyndeticsSummary == 0) {
             require_once ROOT_DIR . '/Drivers/marmot_inc/GoDeeperData.php';
             $summaryInfo = GoDeeperData::getSummary($this->isbn, $this->upc);
             if (isset($summaryInfo['summary'])) {
                 $interface->assign('summaryTeaser', $summaryInfo['summary']);
                 $interface->assign('summary', $summaryInfo['summary']);
                 $useMarcSummary = false;
             }
         }
     }
     if ($mpaaField = $this->marcRecord->getField('521')) {
         $interface->assign('mpaaRating', $this->getSubfieldData($mpaaField, 'a'));
     }
     if (isset($configArray['Content']['subjectFieldsToShow'])) {
         $subjectFieldsToShow = $configArray['Content']['subjectFieldsToShow'];
         $subjectFields = explode(',', $subjectFieldsToShow);
         $subjects = array();
         foreach ($subjectFields as $subjectField) {
             /** @var File_MARC_Data_Field[] $marcFields */
             $marcFields = $marcRecord->getFields($subjectField);
             if ($marcFields) {
                 foreach ($marcFields as $marcField) {
                     $searchSubject = "";
                     $subject = array();
                     foreach ($marcField->getSubFields() as $subField) {
                         /** @var File_MARC_Subfield $subField */
                         if ($subField->getCode() != 2) {
                             $searchSubject .= " " . $subField->getData();
                             $subject[] = array('search' => trim($searchSubject), 'title' => $subField->getData());
                         }
                     }
                     $subjects[] = $subject;
                 }
             }
             $interface->assign('subjects', $subjects);
         }
     }
     $format = $record['format'];
     $interface->assign('recordFormat', $record['format']);
     $format_category = isset($record['format_category'][0]) ? $record['format_category'][0] : '';
     $interface->assign('format_category', $format_category);
     $interface->assign('recordLanguage', isset($record['language']) ? $record['language'] : null);
     $timer->logTime('Got detailed data from Marc Record');
     $tableOfContents = array();
     $marcFields505 = $marcRecord->getFields('505');
     if ($marcFields505) {
         $tableOfContents = $this->processTableOfContentsFields($marcFields505);
     }
     $notes = array();
     $marcFields500 = $marcRecord->getFields('500');
     $marcFields504 = $marcRecord->getFields('504');
     $marcFields511 = $marcRecord->getFields('511');
     $marcFields518 = $marcRecord->getFields('518');
     $marcFields520 = $marcRecord->getFields('520');
     if ($marcFields500 || $marcFields504 || $marcFields505 || $marcFields511 || $marcFields518 || $marcFields520) {
         $allFields = array_merge($marcFields500, $marcFields504, $marcFields511, $marcFields518, $marcFields520);
         $notes = $this->processNoteFields($allFields);
     }
     if (isset($library) && $library->showTableOfContentsTab == 0 || count($tableOfContents) == 0) {
         $notes = array_merge($notes, $tableOfContents);
     } else {
         $interface->assign('tableOfContents', $tableOfContents);
     }
     if (isset($library) && strlen($library->notesTabName) > 0) {
         $interface->assign('notesTabName', $library->notesTabName);
     } else {
         $interface->assign('notesTabName', 'Notes');
     }
     $additionalNotesFields = array('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', '511' => 'Participant or Performer', '513' => 'Type of Report an Period Covered', '515' => 'Numbering Peculiarities', '518' => 'Date/Time and Place of Event', '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');
     foreach ($additionalNotesFields as $tag => $label) {
         $marcFields = $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[] = "<b>{$label}</b>: " . $note;
             }
         }
     }
     if (count($notes) > 0) {
         $interface->assign('notes', $notes);
     }
     /** @var File_MARC_Data_Field[] $linkFields */
     $linkFields = $marcRecord->getFields('856');
     if ($linkFields) {
         $internetLinks = array();
         $purchaseLinks = array();
         $field856Index = 0;
         foreach ($linkFields as $marcField) {
             $field856Index++;
             //Get the link
             if ($marcField->getSubfield('u')) {
                 $link = $marcField->getSubfield('u')->getData();
                 if ($marcField->getSubfield('3')) {
                     $linkText = $marcField->getSubfield('3')->getData();
                 } elseif ($marcField->getSubfield('y')) {
                     $linkText = $marcField->getSubfield('y')->getData();
                 } elseif ($marcField->getSubfield('z')) {
                     $linkText = $marcField->getSubfield('z')->getData();
                 } else {
                     $linkText = $link;
                 }
                 $showLink = true;
                 //Process some links differently so we can either hide them
                 //or show them in different areas of the catalog.
                 if (preg_match('/purchase|buy/i', $linkText) || preg_match('/barnesandnoble|tatteredcover|amazon|smashwords\\.com/i', $link)) {
                     $showLink = false;
                 }
                 $isBookLink = preg_match('/acs\\.dcl\\.lan|vufind\\.douglascountylibraries\\.org|catalog\\.douglascountylibraries\\.org/i', $link);
                 if ($isBookLink == 1) {
                     //e-book link, don't show
                     $showLink = false;
                 }
                 if ($showLink) {
                     //Rewrite the link so we can track usage
                     $link = $configArray['Site']['path'] . '/Record/' . $this->id . '/Link?index=' . $field856Index;
                     $internetLinks[] = array('link' => $link, 'linkText' => $linkText);
                 }
             }
         }
         if (count($internetLinks) > 0) {
             $interface->assign('internetLinks', $internetLinks);
         }
     }
     if (isset($purchaseLinks) && count($purchaseLinks) > 0) {
         $interface->assign('purchaseLinks', $purchaseLinks);
     }
     //Determine the cover to use
     $bookCoverUrl = $configArray['Site']['coverUrl'] . "/bookcover.php?id={$this->id}&amp;isn={$this->isbn}&amp;issn={$this->issn}&amp;size=large&amp;upc={$this->upc}&amp;category=" . urlencode($format_category) . "&amp;format=" . urlencode(isset($format[0]) ? $format[0] : '');
     $interface->assign('bookCoverUrl', $bookCoverUrl);
     //Load accelerated reader data
     if (isset($record['accelerated_reader_interest_level'])) {
         $arData = array('interestLevel' => $record['accelerated_reader_interest_level'], 'pointValue' => $record['accelerated_reader_point_value'], 'readingLevel' => $record['accelerated_reader_reading_level']);
         $interface->assign('arData', $arData);
     }
     if (isset($record['lexile_score']) && $record['lexile_score'] > -1) {
         $lexileScore = $record['lexile_score'];
         if (isset($record['lexile_code'])) {
             $lexileScore = $record['lexile_code'] . $lexileScore;
         }
         $interface->assign('lexileScore', $lexileScore . 'L');
     }
     //Do actions needed if this is the main action.
     //$interface->caching = 1;
     $interface->assign('id', $this->id);
     if (substr($this->id, 0, 1) == '.') {
         $interface->assign('shortId', substr($this->id, 1));
     } else {
         $interface->assign('shortId', $this->id);
     }
     $interface->assign('addHeader', '<link rel="alternate" type="application/rdf+xml" title="RDF Representation" href="' . $configArray['Site']['path'] . '/Record/' . urlencode($this->id) . '/RDF" />');
     // Define Default Tab
     $tab = isset($_GET['action']) ? $_GET['action'] : 'Description';
     $interface->assign('tab', $tab);
     if (isset($_REQUEST['detail'])) {
         $detail = strip_tags($_REQUEST['detail']);
         $interface->assign('defaultDetailsTab', $detail);
     }
     // Define External Content Provider
     if ($this->marcRecord->getField('020')) {
         if (isset($configArray['Content']['reviews'])) {
             $interface->assign('hasReviews', true);
         }
         if (isset($configArray['Content']['excerpts'])) {
             $interface->assign('hasExcerpt', true);
         }
     }
     // Retrieve User Search History
     $interface->assign('lastsearch', isset($_SESSION['lastSearchURL']) ? $_SESSION['lastSearchURL'] : false);
     // Retrieve tags associated with the record
     $limit = 5;
     $resource = new Resource();
     $resource->record_id = $_GET['id'];
     $resource->source = 'VuFind';
     $resource->find(true);
     $tags = $resource->getTags($limit);
     $interface->assign('tagList', $tags);
     $timer->logTime('Got tag list');
     $this->cacheId = 'Record|' . $_GET['id'] . '|' . get_class($this);
     // Find Similar Records
     /** @var Memcache $memCache */
     global $memCache;
     $similar = $memCache->get('similar_titles_' . $this->id);
     if ($similar == false) {
         $similar = $this->db->getMoreLikeThis($this->id);
         // Send the similar items to the template; if there is only one, we need
         // to force it to be an array or things will not display correctly.
         if (isset($similar) && count($similar['response']['docs']) > 0) {
             $similar = $similar['response']['docs'];
         } else {
             $similar = array();
             $timer->logTime("Did not find any similar records");
         }
         $memCache->set('similar_titles_' . $this->id, $similar, 0, $configArray['Caching']['similar_titles']);
     }
     $this->similarTitles = $similar;
     $interface->assign('similarRecords', $similar);
     $timer->logTime('Loaded similar titles');
     // Find Other Editions
     if ($configArray['Content']['showOtherEditionsPopup'] == false) {
         $editions = OtherEditionHandler::getEditions($this->id, $this->isbn, isset($this->record['issn']) ? $this->record['issn'] : null);
         if (!PEAR_Singleton::isError($editions)) {
             $interface->assign('editions', $editions);
         } else {
             $timer->logTime("Did not find any other editions");
         }
         $timer->logTime('Got Other editions');
     }
     $interface->assign('showStrands', isset($configArray['Strands']['APID']) && strlen($configArray['Strands']['APID']) > 0);
     // Send down text for inclusion in breadcrumbs
     $interface->assign('breadcrumbText', $this->recordDriver->getBreadcrumb());
     // Send down OpenURL for COinS use:
     $interface->assign('openURL', $this->recordDriver->getOpenURL());
     // Send down legal export formats (if any):
     $interface->assign('exportFormats', $this->recordDriver->getExportFormats());
     // Set AddThis User
     $interface->assign('addThis', isset($configArray['AddThis']['key']) ? $configArray['AddThis']['key'] : false);
     // Set Proxy URL
     if (isset($configArray['EZproxy']['host'])) {
         $interface->assign('proxy', $configArray['EZproxy']['host']);
     }
     //setup 5 star ratings
     global $user;
     $ratingData = $resource->getRatingData($user);
     $interface->assign('ratingData', $ratingData);
     $timer->logTime('Got 5 star data');
     //Get Next/Previous Links
     $searchSource = isset($_REQUEST['searchSource']) ? $_REQUEST['searchSource'] : 'local';
     $searchObject = SearchObjectFactory::initSearchObject();
     $searchObject->init($searchSource);
     $searchObject->getNextPrevLinks();
     //Load Staff Details
     $interface->assign('staffDetails', $this->recordDriver->getStaffView());
 }
 /**
  * Process inventory for a particular item in the catalog
  *
  * @param string $login     Login for the user doing the inventory
  * @param string $password1 Password for the user doing the inventory
  * @param string $initials
  * @param string $password2
  * @param string[] $barcodes
  * @param boolean $updateIncorrectStatuses
  *
  * @return array
  */
 function doInventory($login, $password1, $initials, $password2, $barcodes, $updateIncorrectStatuses)
 {
     global $configArray;
     global $logger;
     $results = array();
     if (!isset($configArray['Catalog']['url'])) {
         return array('success' => false, 'message' => 'There is not a url to millennium set in the config.ini file.  Please update the configuration');
     }
     $ils = $configArray['Catalog']['ils'];
     if ($login == '' || $password1 == '') {
         return array('success' => false, 'message' => 'Login information not provided correctly.  Please fill out all login fields');
     }
     if ($ils != 'Sierra') {
         if ($initials == '' || $password2 == '') {
             return array('success' => false, 'message' => 'Login information not provided correctly.  Please fill out all login fields');
         }
     }
     if (is_string($barcodes) && strlen($barcodes) == 0) {
         return array('success' => false, 'message' => 'Please enter at least one barcode to inventory.');
     } else {
         if (!is_array($barcodes)) {
             $barcodes = preg_split('/[\\s\\r\\n]+/', $barcodes);
         }
         if (count($barcodes) == 0) {
             return array('success' => false, 'message' => 'Please enter at least one barcode to inventory.');
         }
     }
     //Setup Solr to be able to get additional information about the title
     global $configArray;
     $class = $configArray['Index']['engine'];
     $url = $configArray['Index']['url'];
     $this->db = new $class($url);
     $baseUrl = $configArray['Catalog']['url'];
     $circaUrl = $configArray['Catalog']['url'] . '/iii/airwkst/airwkstcore';
     //Setup curl
     $curl_url = $circaUrl;
     $this->curl_connection = curl_init($curl_url);
     $cookieJar = tempnam("/tmp", "CURLCOOKIE");
     curl_setopt($this->curl_connection, CURLOPT_CONNECTTIMEOUT, 30);
     curl_setopt($this->curl_connection, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
     curl_setopt($this->curl_connection, CURLOPT_RETURNTRANSFER, true);
     curl_setopt($this->curl_connection, CURLOPT_SSL_VERIFYPEER, false);
     curl_setopt($this->curl_connection, CURLOPT_FOLLOWLOCATION, 1);
     curl_setopt($this->curl_connection, CURLOPT_UNRESTRICTED_AUTH, true);
     curl_setopt($this->curl_connection, CURLOPT_COOKIEJAR, $cookieJar);
     curl_setopt($this->curl_connection, CURLOPT_HTTPGET, true);
     curl_setopt($this->curl_connection, CURLOPT_COOKIESESSION, is_null($cookieJar) ? true : false);
     //First get the login page
     curl_exec($this->curl_connection);
     sleep(1);
     //Login to circa
     $post_data = array('action' => 'ValidateAirWkstUserAction', 'login' => $login, 'loginpassword' => $password1, 'nextaction' => 'null', 'purpose' => 'null', 'submit.x' => 41, 'submit.y' => 10, 'subpurpose' => 'null', 'validationstatus' => 'needlogin');
     $post_items = array();
     foreach ($post_data as $key => $value) {
         $post_items[] = $key . '=' . urlencode($value);
     }
     $post_string = implode('&', $post_items);
     curl_setopt($this->curl_connection, CURLOPT_POST, true);
     curl_setopt($this->curl_connection, CURLOPT_POSTFIELDS, $post_string);
     $sresult = curl_exec($this->curl_connection);
     $logger->log("Calling {$curl_url}?{$post_string}", PEAR_LOG_DEBUG);
     //$logger->log("result of circa login $sresult", PEAR_LOG_DEBUG);
     sleep(1);
     //Check that we logged in successfully
     $loginSuccess = false;
     if (!preg_match('/Invalid login\\/password/i', $sresult)) {
         if ($ils == 'Sierra') {
             $loginSuccess = true;
         } else {
             $loginSuccess = preg_match('/initials/i', $sresult);
         }
     }
     if ($loginSuccess) {
         if ($ils != 'Sierra') {
             //we logged in successfully.
             //enter initials
             $post_data = array('action' => 'ValidateAirWkstUserAction', 'initials' => $initials, 'initialspassword' => $password2, 'nextaction' => 'null', 'purpose' => 'null', 'submit.x' => 30, 'submit.y' => 10, 'subpurpose' => 'null', 'validationstatus' => 'needinitials');
             $post_items = array();
             foreach ($post_data as $key => $value) {
                 $post_items[] = $key . '=' . urlencode($value);
             }
             $post_string = implode('&', $post_items);
             curl_setopt($this->curl_connection, CURLOPT_POSTFIELDS, $post_string);
             $sresult = curl_exec($this->curl_connection);
             sleep(1);
             $logger->log("Calling {$curl_url}?{$post_string}", PEAR_LOG_DEBUG);
             //$logger->log("result of circa initials $sresult", PEAR_LOG_DEBUG);
         }
         if (!preg_match('/You are not authorized to use Circa/i', $sresult) && preg_match('/inventory control/i', $sresult)) {
             //Logged in and authorized, check in each barcode
             //Go to the Inventory page
             curl_setopt($this->curl_connection, CURLOPT_HTTPGET, true);
             curl_setopt($this->curl_connection, CURLOPT_URL, $baseUrl . '/iii/airwkst/?action=GetAirWkstUserInfoAction&purpose=updinvdt');
             curl_exec($this->curl_connection);
             curl_setopt($this->curl_connection, CURLOPT_POST, true);
             curl_setopt($this->curl_connection, CURLOPT_URL, $curl_url);
             $results['barcodes'] = array();
             foreach ($barcodes as $barcode) {
                 set_time_limit(60);
                 $post_data = array('action' => 'GetAirWkstItemOneAction', 'prevscreen' => 'AirWkstItemRequestPage', 'purpose' => 'updinvdt', 'searchstring' => $barcode, 'searchtype' => 'b', 'sourcebrowse' => 'airwkstpage');
                 $post_items = array();
                 foreach ($post_data as $key => $value) {
                     $post_items[] = $key . '=' . urlencode($value);
                 }
                 $post_string = implode('&', $post_items);
                 curl_setopt($this->curl_connection, CURLOPT_POSTFIELDS, $post_string);
                 $sresult = curl_exec($this->curl_connection);
                 $titleInfo = $this->db->getRecordByBarcode($barcode);
                 $itemInfo = null;
                 if ($titleInfo != null) {
                     $marcInfo = MarcLoader::loadMarcRecordFromRecord($titleInfo);
                     //Get the matching item from the item records
                     $marcItemField = isset($configArray['Reindex']['itemTag']) ? $configArray['Reindex']['itemTag'] : '989';
                     $itemFields = $marcInfo->getFields($marcItemField);
                     $itemInfo = null;
                     if ($itemFields) {
                         /** @var File_MARC_Data_Field $fieldInfo */
                         foreach ($itemFields as $fieldInfo) {
                             if ($fieldInfo->getSubfield('b')->getData() == $barcode) {
                                 $itemInfo = $fieldInfo;
                             }
                         }
                     } else {
                         $logger->log("Did not find item records {$barcode}", PEAR_LOG_ERR);
                     }
                 }
                 if ($itemInfo == null) {
                     $logger->log("Did not find an item for barcode {$barcode}", PEAR_LOG_ERR);
                 }
                 if (preg_match("/{$barcode} updated successfully/i", $sresult)) {
                     $results['barcodes'][$barcode] = array('inventoryResult' => 'Updated successfully.', 'title' => $titleInfo['title'], 'callNumber' => is_null($itemInfo) ? '' : $itemInfo->getSubfield('a')->getData());
                     if (preg_match('/Unexpected status; adjust below if appropriate/i', $sresult)) {
                         if ($updateIncorrectStatuses) {
                             //Automatically update the item to checked in
                             //extract the current status and item record
                             preg_match('/<input type="hidden" name="olditemstatuscode" value="(.*?)">/', $sresult, $matches);
                             $lastStatus = $matches[1];
                             preg_match('/<input type="hidden" name="itemrecordkey" value="(.*?)">/', $sresult, $matches);
                             $itemrecordkey = $matches[1];
                             $post_data = array('action' => 'UpdateAirWkstItemOneAction', 'itemrecordkey' => $itemrecordkey, 'lastaction' => 'updstatus', 'lastactionstatus' => 'good', 'lastitembarcode' => $barcode, 'newitemstatuscode' => '-', 'olditemstatuscode' => $lastStatus, 'purpose' => 'updstatus', 'submit.x' => 40, 'submit.y' => 10, 'ulang' => 'eng');
                             $post_items = array();
                             foreach ($post_data as $key => $value) {
                                 $post_items[] = $key . '=' . urlencode($value);
                             }
                             $post_string = implode('&', $post_items);
                             curl_setopt($this->curl_connection, CURLOPT_POSTFIELDS, $post_string);
                             $sresult = curl_exec($this->curl_connection);
                             if (preg_match("/{$barcode} updated successfully/i", $sresult)) {
                                 $results['barcodes'][$barcode]['inventoryResult'] = "Automatically changed status from {$lastStatus} to on shelf";
                                 $results['barcodes'][$barcode]['needsAdditionalProcessing'] = false;
                             } else {
                                 $logger->log("Could not update status for barcode {$barcode}/r/n{$sresult}", PEAR_LOG_ERR);
                                 $results['barcodes'][$barcode]['inventoryResult'] = "Could not automatically fix status, old status is {$lastStatus}";
                                 $results['barcodes'][$barcode]['needsAdditionalProcessing'] = true;
                             }
                         } else {
                             $results['barcodes'][$barcode]['inventoryResult'] = "Unexpected Status, Needs Update";
                             $results['barcodes'][$barcode]['needsAdditionalProcessing'] = true;
                         }
                     } elseif (preg_match('/Unexpected status; pull this item for correction/i', $sresult)) {
                         $results['barcodes'][$barcode]['inventoryResult'] .= " Pull this item for status correction";
                         $results['barcodes'][$barcode]['needsAdditionalProcessing'] = true;
                     } else {
                         $results['barcodes'][$barcode]['needsAdditionalProcessing'] = false;
                     }
                     sleep(1);
                 } else {
                     $results['barcodes'][$barcode] = array('inventoryResult' => 'Not updated', 'title' => $titleInfo['title'], 'callNumber' => is_null($itemInfo) ? '' : $itemInfo->getSubfield('a')->getData());
                 }
             }
             $results['success'] = true;
         } else {
             //Did not log in correctly.
             $results['success'] = false;
             $results['message'] = "The initials or password were incorrect or you are not authorized to use circa.";
             if (preg_match('/class="error">(.*?)<\\/h2>/i', $sresult, $matches)) {
                 $results['message'] = $matches[1];
             }
         }
     } else {
         //Did not log in correctly.
         $results['success'] = false;
         $results['message'] = "The login or password were incorrect.  Please reenter.";
     }
     //Logout of the system
     curl_setopt($this->curl_connection, CURLOPT_HTTPGET, true);
     curl_setopt($this->curl_connection, CURLOPT_URL, $circaUrl . '/iii/airwkst/airwkstcore?action=AirWkstReturnToWelcomeAction');
     $sresult = curl_exec($this->curl_connection);
     //Cleanup
     curl_close($this->curl_connection);
     unlink($cookieJar);
     return $results;
 }
 public function setDataObject($eContentRecord)
 {
     $this->eContentRecord = $eContentRecord;
     $this->marcRecord = MarcLoader::loadEContentMarcRecord($eContentRecord);
 }
Exemple #16
0
 public function getStaffView($eContentRecord)
 {
     global $interface;
     $marcRecord = MarcLoader::loadEContentMarcRecord($eContentRecord);
     if ($marcRecord != null) {
         $interface->assign('marcRecord', $marcRecord);
         return 'RecordDrivers/Marc/staff.tpl';
     } else {
         return null;
     }
 }
 /**
  * Load status (holdings) for a record and filter them based on the logged in user information.
  *
  * @param string            $id     the id of the record
  * @return array A list of holdings for the record
  */
 public function getStatus($id)
 {
     global $library;
     global $user;
     global $timer;
     global $logger;
     //Get information about holdings, order information, and issue information
     $millenniumInfo = $this->driver->getMillenniumRecordInfo($id);
     //Get the number of holds
     if ($millenniumInfo->framesetInfo) {
         if (preg_match('/(\\d+) hold(s?) on .*? of \\d+ (copies|copy)/', $millenniumInfo->framesetInfo, $matches)) {
             $holdQueueLength = $matches[1];
         } else {
             $holdQueueLength = 0;
         }
     }
     // Load Record Page
     $r = substr($millenniumInfo->holdingsInfo, stripos($millenniumInfo->holdingsInfo, 'bibItems'));
     $r = substr($r, strpos($r, ">") + 1);
     $r = substr($r, 0, stripos($r, "</table"));
     $rows = preg_split("/<tr([^>]*)>/", $r);
     // Load the full marc record so we can get the iType for each record.
     $marcRecord = MarcLoader::loadMarcRecordByILSId($id);
     $itemFields = $marcRecord->getFields("989");
     $marcItemData = array();
     $pType = $this->driver->getPType();
     $scope = $this->driver->getMillenniumScope();
     //Load item information from marc record
     foreach ($itemFields as $itemField) {
         /** @var $itemField File_MARC_Data_Field */
         $fullCallNumber = $itemField->getSubfield('s') != null ? $itemField->getSubfield('s')->getData() . ' ' : '';
         $fullCallNumber .= $itemField->getSubfield('a') != null ? $itemField->getSubfield('a')->getData() : '';
         $fullCallNumber .= $itemField->getSubfield('r') != null ? ' ' . $itemField->getSubfield('r')->getData() : '';
         $itemData['callnumber'] = $fullCallNumber;
         $itemData['location'] = $itemField->getSubfield('d') != null ? $itemField->getSubfield('d')->getData() : ($itemField->getSubfield('p') != null ? $itemField->getSubfield('p')->getData() : '?????');
         $itemData['iType'] = $itemField->getSubfield('j') != null ? $itemField->getSubfield('j')->getData() : '0';
         $itemData['matched'] = false;
         $marcItemData[] = $itemData;
     }
     //Process each row in the callnumber table.
     $ret = $this->parseHoldingRows($id, $rows);
     $timer->logTime('processed all holdings rows');
     global $locationSingleton;
     /** @var $locationSingleton Location */
     $physicalLocation = $locationSingleton->getPhysicalLocation();
     if ($physicalLocation != null) {
         $physicalBranch = $physicalLocation->holdingBranchLabel;
     } else {
         $physicalBranch = '';
     }
     $homeBranch = '';
     $homeBranchId = 0;
     $nearbyBranch1 = '';
     $nearbyBranch1Id = 0;
     $nearbyBranch2 = '';
     $nearbyBranch2Id = 0;
     //Set location information based on the user login.  This will override information based
     if (isset($user) && $user != false) {
         $homeBranchId = $user->homeLocationId;
         $nearbyBranch1Id = $user->myLocation1Id;
         $nearbyBranch2Id = $user->myLocation2Id;
     } else {
         //Check to see if the cookie for home location is set.
         if (isset($_COOKIE['home_location']) && is_numeric($_COOKIE['home_location'])) {
             $cookieLocation = new Location();
             $locationId = $_COOKIE['home_location'];
             $cookieLocation->whereAdd("locationId = '{$locationId}'");
             $cookieLocation->find();
             if ($cookieLocation->N == 1) {
                 $cookieLocation->fetch();
                 $homeBranchId = $cookieLocation->locationId;
                 $nearbyBranch1Id = $cookieLocation->nearbyLocation1;
                 $nearbyBranch2Id = $cookieLocation->nearbyLocation2;
             }
         }
     }
     //Load the holding label for the user's home location.
     $userLocation = new Location();
     $userLocation->whereAdd("locationId = '{$homeBranchId}'");
     $userLocation->find();
     if ($userLocation->N == 1) {
         $userLocation->fetch();
         $homeBranch = $userLocation->holdingBranchLabel;
     }
     //Load nearby branch 1
     $nearbyLocation1 = new Location();
     $nearbyLocation1->whereAdd("locationId = '{$nearbyBranch1Id}'");
     $nearbyLocation1->find();
     if ($nearbyLocation1->N == 1) {
         $nearbyLocation1->fetch();
         $nearbyBranch1 = $nearbyLocation1->holdingBranchLabel;
     }
     //Load nearby branch 2
     $nearbyLocation2 = new Location();
     $nearbyLocation2->whereAdd();
     $nearbyLocation2->whereAdd("locationId = '{$nearbyBranch2Id}'");
     $nearbyLocation2->find();
     if ($nearbyLocation2->N == 1) {
         $nearbyLocation2->fetch();
         $nearbyBranch2 = $nearbyLocation2->holdingBranchLabel;
     }
     $sorted_array = array();
     //Get a list of the display names for all locations based on holding label.
     $locationLabels = array();
     $location = new Location();
     $location->find();
     $libraryLocationLabels = array();
     $locationCodes = array();
     $suppressedLocationCodes = array();
     while ($location->fetch()) {
         if (strlen($location->holdingBranchLabel) > 0 && $location->holdingBranchLabel != '???') {
             if ($library && $library->libraryId == $location->libraryId) {
                 $cleanLabel = str_replace('/', '\\/', $location->holdingBranchLabel);
                 $libraryLocationLabels[] = str_replace('.', '\\.', $cleanLabel);
             }
             $locationLabels[$location->holdingBranchLabel] = $location->displayName;
             $locationCodes[$location->code] = $location->holdingBranchLabel;
             if ($location->suppressHoldings == 1) {
                 $suppressedLocationCodes[$location->code] = $location->code;
             }
         }
     }
     if (count($libraryLocationLabels) > 0) {
         $libraryLocationLabels = '/^(' . join('|', $libraryLocationLabels) . ').*/i';
     } else {
         $libraryLocationLabels = '';
     }
     //Get the current Ptype for later usage.
     $timer->logTime('setup for additional holdings processing.');
     //Now that we have the holdings, we need to filter and sort them according to scoping rules.
     $i = 0;
     foreach ($ret as $holdingKey => $holding) {
         $holding['type'] = 'holding';
         //Process holdings without call numbers - Need to show items without call numbers
         //because they may have links, etc.  Also show if there is a status.  Since some
         //In process items may not have a call number yet.
         if ((!isset($holding['callnumber']) || strlen($holding['callnumber']) == 0) && (!isset($holding['link']) || count($holding['link']) == 0) && !isset($holding['status'])) {
             continue;
         }
         //Determine if the holding is available or not.
         //First check the status
         if (preg_match('/^(' . $this->driver->availableStatiRegex . ')$/', $holding['status'])) {
             $holding['availability'] = 1;
         } else {
             $holding['availability'] = 0;
         }
         if (preg_match('/^(' . $this->driver->holdableStatiRegex . ')$/', $holding['status'])) {
             $holding['holdable'] = 1;
         } else {
             $holding['holdable'] = 0;
             $holding['nonHoldableReason'] = "This item is not currently available for Patron Holds";
         }
         if (!isset($holding['libraryDisplayName'])) {
             $holding['libraryDisplayName'] = $holding['location'];
         }
         //Get the location id for this holding
         $holding['locationCode'] = '?????';
         foreach ($locationCodes as $locationCode => $holdingLabel) {
             if (strlen($locationCode) > 0 && preg_match("~{$holdingLabel}~i", $holding['location'])) {
                 $holding['locationCode'] = $locationCode;
             }
         }
         if ($holding['locationCode'] == '?????') {
             $logger->log("Did not find location code for " . $holding['location'], PEAR_LOG_DEBUG);
         }
         if (array_key_exists($holding['locationCode'], $suppressedLocationCodes)) {
             $logger->log("Location " . $holding['locationCode'] . " is suppressed", PEAR_LOG_DEBUG);
             continue;
         }
         //Now that we have the location code, try to match with the marc record
         $holding['iType'] = 0;
         foreach ($marcItemData as $itemData) {
             if (!$itemData['matched']) {
                 $locationMatched = strpos($itemData['location'], $holding['locationCode']) === 0;
                 if (strlen($itemData['callnumber']) == 0 || strlen($holding['callnumber']) == 0) {
                     $callNumberMatched = strlen($holding['callnumber']) == strlen($holding['callnumber']);
                 } else {
                     $callNumberMatched = strpos($itemData['callnumber'], $holding['callnumber']) >= 0;
                 }
                 if ($locationMatched && $callNumberMatched) {
                     $holding['iType'] = $itemData['iType'];
                     $itemData['matched'] = true;
                 }
             }
         }
         //Check to see if this item can be held by the current patron.  Only important when
         //we know what pType is in use and we are showing all items.
         if ($scope == 93 && $pType > 0) {
             //Never remove the title if it is owned by the current library (could be in library use only)
             if (isset($library) && strlen($library->ilsCode) > 0 && strpos($holding['locationCode'], $library->ilsCode) === 0) {
                 $logger->log("Cannot remove holding because it belongs to the active library", PEAR_LOG_DEBUG);
             } else {
                 if (!$this->driver->isItemHoldableToPatron($holding['locationCode'], $holding['iType'], $pType)) {
                     $logger->log("Removing item {$holdingKey} because it is not usable by the current patronType {$pType}, iType is {$holding['iType']}, location is {$holding['locationCode']}", PEAR_LOG_DEBUG);
                     //echo("Removing item $holdingKey because it is not usable by the current patronType $pType, iType is {$holding['iType']}, location is {$holding['locationCode']}");
                     unset($ret[$holdingKey]);
                     continue;
                 }
             }
         }
         //Set the hold queue length
         $holding['holdQueueLength'] = isset($holdQueueLength) ? $holdQueueLength : null;
         //Add the holding to the sorted array to determine
         $sortString = $holding['location'] . '-' . $i;
         //$sortString = $holding['location'] . $holding['callnumber']. $i;
         if (strlen($physicalBranch) > 0 && stripos($holding['location'], $physicalBranch) !== false) {
             //If the user is in a branch, those holdings come first.
             $holding['section'] = 'In this library';
             $holding['sectionId'] = 1;
             $sorted_array['1' . $sortString] = $holding;
         } else {
             if (strlen($homeBranch) > 0 && stripos($holding['location'], $homeBranch) !== false) {
                 //Next come the user's home branch if the user is logged in or has the home_branch cookie set.
                 $holding['section'] = 'Your library';
                 $holding['sectionId'] = 2;
                 $sorted_array['2' . $sortString] = $holding;
             } else {
                 if (strlen($nearbyBranch1) > 0 && stripos($holding['location'], $nearbyBranch1) !== false) {
                     //Next come nearby locations for the user
                     $holding['section'] = 'Nearby Libraries';
                     $holding['sectionId'] = 3;
                     $sorted_array['3' . $sortString] = $holding;
                 } else {
                     if (strlen($nearbyBranch2) > 0 && stripos($holding['location'], $nearbyBranch2) !== false) {
                         //Next come nearby locations for the user
                         $holding['section'] = 'Nearby Libraries';
                         $holding['sectionId'] = 4;
                         $sorted_array['4' . $sortString] = $holding;
                     } else {
                         if (strlen($libraryLocationLabels) > 0 && preg_match($libraryLocationLabels, $holding['location'])) {
                             //Next come any locations within the same system we are in.
                             $holding['section'] = $library->displayName;
                             $holding['sectionId'] = 5;
                             $sorted_array['5' . $sortString] = $holding;
                         } else {
                             //Finally, all other holdings are shown sorted alphabetically.
                             $holding['section'] = 'Other Locations';
                             $holding['sectionId'] = 6;
                             $sorted_array['6' . $sortString] = $holding;
                         }
                     }
                 }
             }
         }
         $i++;
     }
     $timer->logTime('finished processing holdings');
     //Check to see if the title is holdable
     $holdable = $this->driver->isRecordHoldable($marcRecord);
     foreach ($sorted_array as $key => $holding) {
         $holding['holdable'] = $holdable ? 1 : 0;
         $sorted_array[$key] = $holding;
     }
     //Load order records, these only show in the full page view, not the item display
     $orderMatches = array();
     if (preg_match_all('/<tr\\s+class="bibOrderEntry">.*?<td\\s*>(.*?)<\\/td>/s', $millenniumInfo->framesetInfo, $orderMatches)) {
         for ($i = 0; $i < count($orderMatches[1]); $i++) {
             $location = trim($orderMatches[1][$i]);
             $location = preg_replace('/\\sC\\d{3}[\\s\\.]/', '', $location);
             //Remove courier code if any
             $sorted_array['7' . $location . $i] = array('location' => $location, 'section' => 'On Order', 'sectionId' => 7, 'holdable' => 1);
         }
     }
     $timer->logTime('loaded order records');
     ksort($sorted_array);
     //Check to see if we can remove the sections.
     //We can if all section keys are the same.
     $removeSection = true;
     $lastKeyIndex = '';
     foreach ($sorted_array as $key => $holding) {
         $currentKey = substr($key, 0, 1);
         if ($lastKeyIndex == '') {
             $lastKeyIndex = $currentKey;
         } else {
             if ($lastKeyIndex != $currentKey) {
                 $removeSection = false;
                 break;
             }
         }
     }
     foreach ($sorted_array as $key => $holding) {
         if ($removeSection == true) {
             $holding['section'] = '';
             $sorted_array[$key] = $holding;
         }
     }
     $issueSummaries = $this->driver->getIssueSummaries($millenniumInfo);
     $timer->logTime('loaded issue summaries');
     if (!is_null($issueSummaries)) {
         krsort($sorted_array);
         //Group holdings under the issue issue summary that is related.
         foreach ($sorted_array as $key => $holding) {
             //Have issue summary = false
             $haveIssueSummary = false;
             $issueSummaryKey = null;
             foreach ($issueSummaries as $issueKey => $issueSummary) {
                 if ($issueSummary['location'] == $holding['location']) {
                     $haveIssueSummary = true;
                     $issueSummaryKey = $issueKey;
                     break;
                 }
             }
             if ($haveIssueSummary) {
                 $issueSummaries[$issueSummaryKey]['holdings'][strtolower($key)] = $holding;
             } else {
                 //Need to automatically add a summary so we don't lose data
                 $issueSummaries[$holding['location']] = array('location' => $holding['location'], 'type' => 'issue', 'holdings' => array(strtolower($key) => $holding));
             }
         }
         foreach ($issueSummaries as $key => $issueSummary) {
             if (isset($issueSummary['holdings']) && is_array($issueSummary['holdings'])) {
                 krsort($issueSummary['holdings']);
                 $issueSummaries[$key] = $issueSummary;
             }
         }
         ksort($issueSummaries);
         return $issueSummaries;
     } else {
         return $sorted_array;
     }
 }
Exemple #18
0
 function __construct($subAction = false, $record_id = null)
 {
     global $interface;
     global $configArray;
     global $library;
     global $timer;
     $interface->assign('page_body_style', 'sidebar_left');
     //Load basic information needed in subclasses
     if ($record_id == null || !isset($record_id)) {
         $this->id = $_GET['id'];
     } else {
         $this->id = $record_id;
     }
     $interface->assign('id', $this->id);
     if (preg_match('/^[\\da-fA-F-]{36}$/', $this->id)) {
         header('Location:' . $configArray['Site']['path'] . '/GroupedWork/' . $this->id);
         die;
     }
     //Check to see if the record exists within the resources table
     $this->recordDriver = new MarcRecord($this->id);
     if (!$this->recordDriver->isValid()) {
         $interface->assign('sidebar', 'Record/full-record-sidebar.tpl');
         $interface->setTemplate('invalidRecord.tpl');
         $interface->display('layout.tpl');
         die;
     }
     if ($configArray['Catalog']['ils'] == 'Millennium' || $configArray['Catalog']['ils'] == 'Sierra') {
         $classicId = substr($this->id, 1, strlen($this->id) - 2);
         $interface->assign('classicId', $classicId);
         $millenniumScope = $interface->getVariable('millenniumScope');
         if (isset($configArray['Catalog']['linking_url'])) {
             $interface->assign('classicUrl', $configArray['Catalog']['linking_url'] . "/record={$classicId}&amp;searchscope={$millenniumScope}");
         }
     } elseif ($configArray['Catalog']['ils'] == 'Koha') {
         $interface->assign('classicId', $this->id);
         $interface->assign('classicUrl', $configArray['Catalog']['url'] . '/cgi-bin/koha/opac-detail.pl?biblionumber=' . $this->id);
         $interface->assign('staffClientUrl', $configArray['Catalog']['staffClientUrl'] . '/cgi-bin/koha/catalogue/detail.pl?biblionumber=' . $this->id);
     }
     // Process MARC Data
     require_once ROOT_DIR . '/sys/MarcLoader.php';
     $marcRecord = MarcLoader::loadMarcRecordByILSId($this->id);
     if ($marcRecord) {
         $this->marcRecord = $marcRecord;
         $interface->assign('marc', $marcRecord);
         require_once ROOT_DIR . '/RecordDrivers/MarcRecord.php';
         $this->recordDriver = new MarcRecord($marcRecord);
         $interface->assign('recordDriver', $this->recordDriver);
     } else {
         $interface->assign('error', 'Cannot Process MARC Record');
     }
     $timer->logTime('Processed the marc record');
     //Load information for display in the template rather than processing specific fields in the template
     $marcField = $marcRecord->getField('245');
     $recordTitle = $this->getSubfieldData($marcField, 'a');
     $interface->assign('recordTitle', $recordTitle);
     $recordTitleSubtitle = trim($this->concatenateSubfieldData($marcField, array('a', 'b', 'h', 'n', 'p')));
     $recordTitleSubtitle = preg_replace('~\\s+[\\/:]$~', '', $recordTitleSubtitle);
     $interface->assign('recordTitleSubtitle', $recordTitleSubtitle);
     $recordTitleWithAuth = trim($this->concatenateSubfieldData($marcField, array('a', 'b', 'h', 'n', 'p', 'c')));
     $interface->assign('recordTitleWithAuth', $recordTitleWithAuth);
     $marcField = $marcRecord->getField('100');
     if ($marcField) {
         $mainAuthor = $this->concatenateSubfieldData($marcField, array('a', 'b', 'c', 'd'));
         $interface->assign('mainAuthor', $mainAuthor);
     }
     $marcFields = $marcRecord->getFields('250');
     if ($marcFields) {
         $editionsThis = array();
         foreach ($marcFields as $marcField) {
             $editionsThis[] = $this->getSubfieldData($marcField, 'a');
         }
         $interface->assign('editionsThis', $editionsThis);
     }
     $marcFields = $marcRecord->getFields('300');
     if ($marcFields) {
         $physicalDescriptions = array();
         foreach ($marcFields as $marcField) {
             $description = $this->concatenateSubfieldData($marcField, array('a', 'b', 'c', 'e', 'f', 'g'));
             if ($description != 'p. cm.') {
                 $description = preg_replace("/[\\/|;:]\$/", '', $description);
                 $description = preg_replace("/p\\./", 'pages', $description);
                 $physicalDescriptions[] = $description;
             }
         }
         $interface->assign('physicalDescriptions', $physicalDescriptions);
     }
     // Get ISBN for cover and review use
     $mainIsbnSet = false;
     /** @var File_MARC_Data_Field[] $isbnFields */
     if ($isbnFields = $this->marcRecord->getFields('020')) {
         $isbns = array();
         //Use the first good ISBN we find.
         foreach ($isbnFields as $isbnField) {
             /** @var File_MARC_Subfield $isbnSubfieldA */
             if ($isbnSubfieldA = $isbnField->getSubfield('a')) {
                 $tmpIsbn = trim($isbnSubfieldA->getData());
                 if (strlen($tmpIsbn) > 0) {
                     $isbns[] = $isbnSubfieldA->getData();
                     $pos = strpos($tmpIsbn, ' ');
                     if ($pos > 0) {
                         $tmpIsbn = substr($tmpIsbn, 0, $pos);
                     }
                     $tmpIsbn = trim($tmpIsbn);
                     if (strlen($tmpIsbn) > 0) {
                         if (strlen($tmpIsbn) < 10) {
                             $tmpIsbn = str_pad($tmpIsbn, 10, "0", STR_PAD_LEFT);
                         }
                         if (!$mainIsbnSet) {
                             $this->isbn = $tmpIsbn;
                             $interface->assign('isbn', $tmpIsbn);
                             $mainIsbnSet = true;
                         }
                     }
                 }
             }
         }
         if (isset($this->isbn)) {
             if (strlen($this->isbn) == 13) {
                 require_once ROOT_DIR . '/Drivers/marmot_inc/ISBNConverter.php';
                 $this->isbn10 = ISBNConverter::convertISBN13to10($this->isbn);
             } else {
                 $this->isbn10 = $this->isbn;
             }
             $interface->assign('isbn10', $this->isbn10);
         }
         $interface->assign('isbns', $isbns);
     }
     if ($upcField = $this->marcRecord->getField('024')) {
         /** @var File_MARC_Data_Field $upcField */
         if ($upcSubField = $upcField->getSubfield('a')) {
             $this->upc = trim($upcSubField->getData());
             $interface->assign('upc', $this->upc);
         }
     }
     if ($issnField = $this->marcRecord->getField('022')) {
         /** @var File_MARC_Data_Field $issnField */
         if ($issnSubField = $issnField->getSubfield('a')) {
             $this->issn = trim($issnSubField->getData());
             if ($pos = strpos($this->issn, ' ')) {
                 $this->issn = substr($this->issn, 0, $pos);
             }
             $interface->assign('issn', $this->issn);
             //Also setup GoldRush link
             if (isset($library) && strlen($library->goldRushCode) > 0) {
                 $interface->assign('goldRushLink', "http://goldrush.coalliance.org/index.cfm?fuseaction=Search&amp;inst_code={$library->goldRushCode}&amp;search_type=ISSN&amp;search_term={$this->issn}");
             }
         }
     }
     $timer->logTime("Got basic data from Marc Record subaction = {$subAction}, record_id = {$record_id}");
     //stop if this is not the main action.
     if ($subAction == true) {
         return;
     }
     //Get street date
     if ($streetDateField = $this->marcRecord->getField('263')) {
         $streetDate = $this->getSubfieldData($streetDateField, 'a');
         if ($streetDate != '') {
             $interface->assign('streetDate', $streetDate);
         }
     }
     if ($mpaaField = $this->marcRecord->getField('521')) {
         $interface->assign('mpaaRating', $this->getSubfieldData($mpaaField, 'a'));
     }
     $format = $this->recordDriver->getFormat();
     $interface->assign('recordFormat', $format);
     $format_category = $format = $this->recordDriver->getFormatCategory();
     $interface->assign('format_category', $format_category);
     $interface->assign('recordLanguage', $this->recordDriver->getLanguage());
     $timer->logTime('Got detailed data from Marc Record');
     $notes = array();
     if (isset($library) && strlen($library->notesTabName) > 0) {
         $interface->assign('notesTabName', $library->notesTabName);
     } else {
         $interface->assign('notesTabName', 'Notes');
     }
     $notes = $this->recordDriver->getNotes();
     if (count($notes) > 0) {
         $interface->assign('notes', $notes);
     }
     /** @var File_MARC_Data_Field[] $linkFields */
     $linkFields = $marcRecord->getFields('856');
     if ($linkFields) {
         $internetLinks = array();
         $purchaseLinks = array();
         $field856Index = 0;
         foreach ($linkFields as $marcField) {
             $field856Index++;
             //Get the link
             if ($marcField->getSubfield('u')) {
                 $link = $marcField->getSubfield('u')->getData();
                 if ($marcField->getSubfield('3')) {
                     $linkText = $marcField->getSubfield('3')->getData();
                 } elseif ($marcField->getSubfield('y')) {
                     $linkText = $marcField->getSubfield('y')->getData();
                 } elseif ($marcField->getSubfield('z')) {
                     $linkText = $marcField->getSubfield('z')->getData();
                 } else {
                     $linkText = $link;
                 }
                 $showLink = true;
                 //Process some links differently so we can either hide them
                 //or show them in different areas of the catalog.
                 if (preg_match('/purchase|buy/i', $linkText) || preg_match('/barnesandnoble|tatteredcover|amazon|smashwords\\.com/i', $link)) {
                     $showLink = false;
                 }
                 $isBookLink = preg_match('/acs\\.dcl\\.lan|vufind\\.douglascountylibraries\\.org|catalog\\.douglascountylibraries\\.org/i', $link);
                 if ($isBookLink == 1) {
                     //e-book link, don't show
                     $showLink = false;
                 }
                 if ($showLink) {
                     //Rewrite the link so we can track usage
                     $link = $configArray['Site']['path'] . '/Record/' . $this->id . '/Link?index=' . $field856Index;
                     $internetLinks[] = array('link' => $link, 'linkText' => $linkText);
                 }
             }
         }
         if (count($internetLinks) > 0) {
             $interface->assign('internetLinks', $internetLinks);
         }
     }
     if (isset($purchaseLinks) && count($purchaseLinks) > 0) {
         $interface->assign('purchaseLinks', $purchaseLinks);
     }
     //Determine the cover to use
     $interface->assign('bookCoverUrl', $this->recordDriver->getBookcoverUrl('large'));
     //Load accelerated reader data
     if (isset($record['accelerated_reader_interest_level'])) {
         $arData = array('interestLevel' => $record['accelerated_reader_interest_level'], 'pointValue' => $record['accelerated_reader_point_value'], 'readingLevel' => $record['accelerated_reader_reading_level']);
         $interface->assign('arData', $arData);
     }
     if (isset($record['lexile_score']) && $record['lexile_score'] > -1) {
         $lexileScore = $record['lexile_score'];
         if (isset($record['lexile_code'])) {
             $lexileScore = $record['lexile_code'] . $lexileScore;
         }
         $interface->assign('lexileScore', $lexileScore . 'L');
     }
     //Do actions needed if this is the main action.
     //$interface->caching = 1;
     $interface->assign('id', $this->id);
     if (substr($this->id, 0, 1) == '.') {
         $interface->assign('shortId', substr($this->id, 1));
     } else {
         $interface->assign('shortId', $this->id);
     }
     $interface->assign('addHeader', '<link rel="alternate" type="application/rdf+xml" title="RDF Representation" href="' . $configArray['Site']['path'] . '/Record/' . urlencode($this->id) . '/RDF" />');
     // Define Default Tab
     $tab = isset($_GET['action']) ? $_GET['action'] : 'Description';
     $interface->assign('tab', $tab);
     if (isset($_REQUEST['detail'])) {
         $detail = strip_tags($_REQUEST['detail']);
         $interface->assign('defaultDetailsTab', $detail);
     }
     // Define External Content Provider
     if ($this->marcRecord->getField('020')) {
         if (isset($configArray['Content']['reviews'])) {
             $interface->assign('hasReviews', true);
         }
         if (isset($configArray['Content']['excerpts'])) {
             $interface->assign('hasExcerpt', true);
         }
     }
     // Retrieve User Search History
     $interface->assign('lastsearch', isset($_SESSION['lastSearchURL']) ? $_SESSION['lastSearchURL'] : false);
     $this->cacheId = 'Record|' . $_GET['id'] . '|' . get_class($this);
     // Send down text for inclusion in breadcrumbs
     $interface->assign('breadcrumbText', $this->recordDriver->getBreadcrumb());
     // Send down legal export formats (if any):
     $interface->assign('exportFormats', $this->recordDriver->getExportFormats());
     // Set AddThis User
     $interface->assign('addThis', isset($configArray['AddThis']['key']) ? $configArray['AddThis']['key'] : false);
     //Get Next/Previous Links
     $searchSource = isset($_REQUEST['searchSource']) ? $_REQUEST['searchSource'] : 'local';
     $searchObject = SearchObjectFactory::initSearchObject();
     $searchObject->init($searchSource);
     $searchObject->getNextPrevLinks();
     //Load Staff Details
     $interface->assign('staffDetails', $this->recordDriver->getStaffView());
 }
Exemple #19
0
 /**
  * Loads items information as quickly as possible (no direct calls to the ILS).  Does do filtering by loan rules
  *
  * return is an array of items with the following information:
  *  location
  *  callnumber
  *  available
  *  holdable
  *  lastStatusCheck (time)
  *
  * @param $id
  * @param $scopingEnabled
  * @param $marcRecord
  * @return mixed
  */
 public function getItemsFast($id, $scopingEnabled, $marcRecord = null)
 {
     if ($marcRecord == null) {
         $marcRecord = MarcLoader::loadMarcRecordByILSId($id);
         global $timer;
         $timer->logTime("Finished loading MARC Record for getItemsFast");
     }
     MillenniumDriver::loadLibraryLocationInformation();
     //Get the items Fields from the record
     /** @var File_MARC_Data_Field[] $itemFields */
     $itemFields = $marcRecord->getFields('989');
     global $timer;
     $timer->logTime("Finished loading item fields for {$id}, found " . count($itemFields));
     $items = array();
     $pType = $this->getPType();
     //$timer->logTime("Finished loading pType");
     global $configArray;
     $statusSubfield = $configArray['Reindex']['statusSubfield'];
     $iTypeSubfield = $configArray['Reindex']['iTypeSubfield'];
     $dueDateSubfield = $configArray['Reindex']['dueDateSubfield'];
     $lastCheckinDateSubfield = $configArray['Reindex']['lastCheckinDateSubfield'];
     foreach ($itemFields as $itemField) {
         //Ignore eContent items
         $eContentData = trim($itemField->getSubfield('w') != null ? $itemField->getSubfield('w')->getData() : '');
         if ($eContentData && strpos($eContentData, ':') > 0) {
             continue;
         }
         $locationCode = $itemField->getSubfield('d') != null ? trim($itemField->getSubfield('d')->getData()) : '';
         //Do a quick check of location code so we can remove this quickly when scoping is enabled
         if ($scopingEnabled && strlen(MillenniumDriver::$scopingLocationCode) > 0 && strpos($locationCode, MillenniumDriver::$scopingLocationCode) !== 0) {
             global $logger;
             $logger->log("Removed item because scoping is enabled and the location code {$locationCode} did not start with " . MillenniumDriver::$scopingLocationCode, PEAR_LOG_DEBUG);
             continue;
         }
         $iType = $itemField->getSubfield($iTypeSubfield) != null ? trim($itemField->getSubfield($iTypeSubfield)->getData()) : '';
         $holdable = $this->isItemHoldableToPatron($locationCode, $iType, $pType);
         $isLibraryItem = false;
         $locationLabel = '';
         foreach (MillenniumDriver::$libraryLocations as $tmpLocation) {
             if (strpos($locationCode, $tmpLocation) === 0) {
                 $isLibraryItem = true;
                 $locationLabel = MillenniumDriver::$libraryLocationLabels[$tmpLocation];
                 break;
             }
         }
         $timer->logTime("Finished checking if item is holdable");
         //Check to make sure the user has access to this item
         if ($holdable || $isLibraryItem) {
             $isLocalItem = false;
             if (MillenniumDriver::$homeLocationCode != null && strpos($locationCode, MillenniumDriver::$homeLocationCode) === 0) {
                 $isLocalItem = true;
                 $locationLabel = MillenniumDriver::$homeLocationLabel;
             }
             $status = trim($itemField->getSubfield($statusSubfield) != null ? trim($itemField->getSubfield($statusSubfield)->getData()) : '');
             $dueDate = $itemField->getSubfield($dueDateSubfield) != null ? trim($itemField->getSubfield($dueDateSubfield)->getData()) : null;
             $lastCheckinDate = $itemField->getSubfield($lastCheckinDateSubfield);
             if ($lastCheckinDate) {
                 // convert to timestamp for ease of display in template
                 $lastCheckinDate = trim($lastCheckinDate->getData());
                 $lastCheckinDate = DateTime::createFromFormat('m-d-Y G:i', $lastCheckinDate);
                 if ($lastCheckinDate) {
                     $lastCheckinDate = $lastCheckinDate->getTimestamp();
                 }
             }
             if (!$lastCheckinDate) {
                 $lastCheckinDate = null;
             }
             $available = in_array($status, array('-', 'o', 'd', 'w', ')', 'u')) && ($dueDate == null || strlen($dueDate) == 0);
             $inLibraryUseOnly = $status == 'o';
             $fullCallNumber = $itemField->getSubfield('s') != null ? $itemField->getSubfield('s')->getData() . ' ' : '';
             $fullCallNumber .= $itemField->getSubfield('a') != null ? $itemField->getSubfield('a')->getData() : '';
             $fullCallNumber .= $itemField->getSubfield('r') != null ? ' ' . $itemField->getSubfield('r')->getData() : '';
             $fullCallNumber .= $itemField->getSubfield('v') != null ? ' ' . $itemField->getSubfield('v')->getData() : '';
             $shelfLocation = mapValue('shelf_location', $locationCode);
             if (preg_match('/(.*?)\\sC\\d{3}\\w{0,2}$/', $shelfLocation, $locationParts)) {
                 $shelfLocation = $locationParts[1];
             }
             $item = array('location' => $locationCode, 'callnumber' => $fullCallNumber, 'availability' => $available, 'holdable' => $holdable, 'inLibraryUseOnly' => $inLibraryUseOnly, 'isLocalItem' => $isLocalItem, 'isLibraryItem' => $isLibraryItem, 'locationLabel' => $locationLabel, 'shelfLocation' => $shelfLocation, 'status' => $status, 'dueDate' => $dueDate, 'iType' => $iType, 'lastCheckinDate' => $lastCheckinDate);
             $items[] = $item;
         }
         //$timer->logTime("Finished processing item");
     }
     global $timer;
     $timer->logTime("Finished load items fast for Millennium record {$id} there were " . count($itemFields) . " item fields originally, filtered to " . count($items));
     return $items;
 }
Exemple #20
0
 function getPurchaseOptions()
 {
     global $interface;
     if (isset($_REQUEST['id'])) {
         $id = $_REQUEST['id'];
         $interface->assign('id', $id);
         $marcRecord = MarcLoader::loadMarcRecordByILSId($id);
         if ($marcRecord) {
             $linkFields = $marcRecord->getFields('856');
             $purchaseLinks = array();
             if ($linkFields) {
                 $field856Index = 0;
                 /** @var File_MARC_Data_Field[] $linkFields */
                 foreach ($linkFields as $marcField) {
                     $field856Index++;
                     //Get the link
                     if ($marcField->getSubfield('u')) {
                         $link = $marcField->getSubfield('u')->getData();
                         if ($marcField->getSubfield('3')) {
                             $linkText = $marcField->getSubfield('3')->getData();
                         } elseif ($marcField->getSubfield('y')) {
                             $linkText = $marcField->getSubfield('y')->getData();
                         } elseif ($marcField->getSubfield('z')) {
                             $linkText = $marcField->getSubfield('z')->getData();
                         } else {
                             $linkText = $link;
                         }
                         //Process some links differently so we can either hide them
                         //or show them in different areas of the catalog.
                         if (preg_match('/purchase|buy/i', $linkText) || preg_match('/barnesandnoble|tatteredcover|amazon\\.com/i', $link)) {
                             if (preg_match('/barnesandnoble/i', $link)) {
                                 $purchaseLinks[] = array('link' => $link, 'linkText' => 'Buy from Barnes & Noble', 'storeName' => 'Barnes & Noble', 'image' => '/images/barnes_and_noble.png', 'field856Index' => $field856Index);
                             } else {
                                 if (preg_match('/tatteredcover/i', $link)) {
                                     $purchaseLinks[] = array('link' => $link, 'linkText' => 'Buy from Tattered Cover', 'storeName' => 'Tattered Cover', 'image' => '/images/tattered_cover.png', 'field856Index' => $field856Index);
                                 } else {
                                     if (preg_match('/amazon\\.com/i', $link)) {
                                         $purchaseLinks[] = array('link' => $link, 'linkText' => 'Buy from Amazon', 'storeName' => 'Amazon', 'image' => '/images/amazon.png', 'field856Index' => $field856Index);
                                     } else {
                                         if (preg_match('/smashwords\\.com/i', $link)) {
                                             $purchaseLinks[] = array('link' => $link, 'linkText' => 'Buy from Smashwords', 'storeName' => 'Smashwords', 'image' => '/images/smashwords.png', 'field856Index' => $field856Index);
                                         } else {
                                             $purchaseLinks[] = array('link' => $link, 'linkText' => $linkText, 'storeName' => 'Smashwords', 'image' => '', 'field856Index' => $field856Index);
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
             //End checking for purchase information in the marc record
             if (count($purchaseLinks) > 0) {
                 $interface->assign('purchaseLinks', $purchaseLinks);
             } else {
                 $resource = new Resource();
                 $resource->record_id = $id;
                 $resource->source = 'VuFind';
                 if ($resource->find(true)) {
                     $title = $resource->title;
                     $author = $resource->author;
                     require_once ROOT_DIR . '/services/Record/Purchase.php';
                     $purchaseLinks = Record_Purchase::getStoresForTitle($title, $author);
                     if (count($purchaseLinks) > 0) {
                         $interface->assign('purchaseLinks', $purchaseLinks);
                     } else {
                         $interface->assign('errors', array("Sorry we couldn't find any stores that offer this title."));
                     }
                 } else {
                     $interface->assign('errors', array("Sorry we couldn't find a resource for that id."));
                 }
             }
         } else {
             $errors = array("Could not load marc information for that id.");
             $interface->assign('errors', $errors);
         }
     } else {
         $errors = array("You must provide the id of the title to be purchased. ");
         $interface->assign('errors', $errors);
     }
     echo $interface->fetch('Record/ajax-purchase-options.tpl');
 }
Exemple #21
0
 /**
  * Returns a summary of the holdings information for a single id. Used to display
  * within the search results and at the top of a full record display to ensure
  * the holding information makes sense to all users.
  *
  * @param string $id the id of the bid to load holdings for
  * @return array an associative array with a summary of the holdings.
  */
 public function getStatusSummary($id, $record = null, $mysip = null)
 {
     global $timer;
     global $library;
     global $locationSingleton;
     global $configArray;
     global $memCache;
     //Holdings summaries need to be cached based on the actual location since part of the information
     //includes local call numbers and statuses.
     $ipLocation = $locationSingleton->getPhysicalLocation();
     $location = $ipLocation;
     if (!isset($location) && $location == null) {
         $location = $locationSingleton->getUserHomeLocation();
     }
     $ipLibrary = null;
     if (isset($ipLocation)) {
         $ipLibrary = new Library();
         $ipLibrary->libraryId = $ipLocation->getLibraryId;
         if (!$ipLibrary->find(true)) {
             $ipLibrary = null;
         }
     }
     if (!isset($location) && $location == null) {
         $locationId = -1;
     } else {
         $locationId = $location->locationId;
     }
     $summaryInformation = $memCache->get("holdings_summary_{$id}_{$locationId}");
     if ($summaryInformation == false) {
         $canShowHoldButton = true;
         if ($library && $library->showHoldButton == 0) {
             $canShowHoldButton = false;
         }
         if ($location != null && $location->showHoldButton == 0) {
             $canShowHoldButton = false;
         }
         $holdings = $this->getStatus($id, $record, $mysip, true);
         $timer->logTime('Retrieved Status of holding');
         $counter = 0;
         $summaryInformation = array();
         $summaryInformation['recordId'] = $id;
         $summaryInformation['shortId'] = $id;
         $summaryInformation['isDownloadable'] = false;
         //Default value, reset later if needed.
         $summaryInformation['holdQueueLength'] = 0;
         //Check to see if we are getting issue summaries or actual holdings
         $isIssueSummary = false;
         $numSubscriptions = 0;
         if (count($holdings) > 0) {
             $lastHolding = end($holdings);
             if (isset($lastHolding['type']) && ($lastHolding['type'] == 'issueSummary' || $lastHolding['type'] == 'issue')) {
                 $isIssueSummary = true;
                 $issueSummaries = $holdings;
                 $numSubscriptions = count($issueSummaries);
                 $holdings = array();
                 foreach ($issueSummaries as $issueSummary) {
                     if (isset($issueSummary['holdings'])) {
                         $holdings = array_merge($holdings, $issueSummary['holdings']);
                     } else {
                         //Create a fake holding for subscriptions so something
                         //will be displayed in the holdings summary.
                         $holdings[$issueSummary['location']] = array('availability' => '1', 'location' => $issueSummary['location'], 'libraryDisplayName' => $issueSummary['location'], 'callnumber' => $issueSummary['cALL'], 'status' => 'Lib Use Only', 'statusfull' => 'In Library Use Only');
                     }
                 }
             }
         }
         $timer->logTime('Processed for subscriptions');
         //Valid statuses are:
         //Available by Request
         //  - not at the user's home branch or preferred location, but at least one copy is not checked out
         //  - do not show the call number
         //  - show place hold button
         //Checked Out
         //  - all copies are checked out
         //  - show the call number for the local library if any
         //  - show place hold button
         //Downloadable
         //  - there is at least one download link for the record.
         $numAvailableCopies = 0;
         $numHoldableCopies = 0;
         $numCopies = 0;
         $numCopiesOnOrder = 0;
         $availableLocations = array();
         $unavailableStatus = null;
         //The status of all items.  Will be set to an actual status if all are the same
         //or null if the item statuses are inconsistent
         $allItemStatus = '';
         $firstAvailableBarcode = '';
         $availableHere = false;
         foreach ($holdings as $holdingKey => $holding) {
             if (is_null($allItemStatus)) {
                 //Do nothing, the status is not distinct
             } else {
                 if ($allItemStatus == '') {
                     $allItemStatus = $holding['statusfull'];
                 } elseif ($allItemStatus != $holding['statusfull']) {
                     $allItemStatus = null;
                 }
             }
             if ($holding['availability'] == true) {
                 if ($ipLocation && strcasecmp($holding['locationCode'], $ipLocation->code) == 0) {
                     $availableHere = true;
                 }
                 $numAvailableCopies++;
                 $addToAvailableLocation = false;
                 $addToAdditionalAvailableLocation = false;
                 //Check to see if the location should be listed in the list of locations that the title is available at.
                 //Can only be in this system if there is a system active.
                 if (!in_array($holding['locationCode'], array_keys($availableLocations))) {
                     $locationMapLink = $this->getLocationMapLink($holding['locationCode']);
                     if (strlen($locationMapLink) > 0) {
                         $availableLocations[$holding['locationCode']] = "<a href='{$locationMapLink}' target='_blank'>" . preg_replace('/\\s/', '&nbsp;', $holding['location']) . "</a>";
                     } else {
                         $availableLocations[$holding['locationCode']] = $holding['location'];
                     }
                 }
             } else {
                 if ($unavailableStatus == null) {
                     $unavailableStatus = $holding['statusfull'];
                 }
             }
             if (isset($holding['holdable']) && $holding['holdable'] == 1) {
                 $numHoldableCopies++;
             }
             $numCopies++;
             //Check to see if the holding has a download link and if so, set that info.
             if (isset($holding['link'])) {
                 foreach ($holding['link'] as $link) {
                     if ($link['isDownload']) {
                         $summaryInformation['status'] = "Available for Download";
                         $summaryInformation['class'] = 'here';
                         $summaryInformation['isDownloadable'] = true;
                         $summaryInformation['downloadLink'] = $link['link'];
                         $summaryInformation['downloadText'] = $link['linkText'];
                     }
                 }
             }
             //Only show a call number if the book is at the user's home library, one of their preferred libraries, or in the library they are in.
             if (!isset($summaryInformation['callnumber'])) {
                 $summaryInformation['callnumber'] = $holding['callnumber'];
             }
             if ($holding['availability'] == 1) {
                 //The item is available within the physical library.  Patron should go get it off the shelf
                 $summaryInformation['status'] = "Available At";
                 if ($numHoldableCopies > 0) {
                     $summaryInformation['showPlaceHold'] = $canShowHoldButton;
                 } else {
                     $summaryInformation['showPlaceHold'] = 0;
                 }
                 $summaryInformation['class'] = 'available';
             }
             if ($holding['holdQueueLength'] > $summaryInformation['holdQueueLength']) {
                 $summaryInformation['holdQueueLength'] = $holding['holdQueueLength'];
             }
             if ($firstAvailableBarcode == '' && $holding['availability'] == true) {
                 $firstAvailableBarcode = $holding['barcode'];
             }
         }
         $timer->logTime('Processed copies');
         //If all items are checked out the status will still be blank
         $summaryInformation['availableCopies'] = $numAvailableCopies;
         $summaryInformation['holdableCopies'] = $numHoldableCopies;
         $summaryInformation['numCopiesOnOrder'] = $numCopiesOnOrder;
         //Do some basic sanity checking to make sure that we show the total copies
         //With at least as many copies as the number of copies on order.
         if ($numCopies < $numCopiesOnOrder) {
             $summaryInformation['numCopies'] = $numCopiesOnOrder;
         } else {
             $summaryInformation['numCopies'] = $numCopies;
         }
         if ($unavailableStatus != 'ONLINE') {
             $summaryInformation['unavailableStatus'] = $unavailableStatus;
         }
         //Status is not set, check to see if the item is downloadable
         if (!isset($summaryInformation['status']) && !isset($summaryInformation['downloadLink'])) {
             // Retrieve Full Marc Record
             $recordURL = null;
             // Process MARC Data
             require_once ROOT_DIR . '/sys/MarcLoader.php';
             $marcRecord = MarcLoader::loadMarcRecordByILSId($id);
             if ($marcRecord) {
                 //Check the 856 tag to see if there is a URL
                 if ($linkField = $marcRecord->getField('856')) {
                     if ($linkURLField = $linkField->getSubfield('u')) {
                         $linkURL = $linkURLField->getData();
                     }
                     if ($linkTextField = $linkField->getSubfield('3')) {
                         $linkText = $linkTextField->getData();
                     } else {
                         if ($linkTextField = $linkField->getSubfield('y')) {
                             $linkText = $linkTextField->getData();
                         } else {
                             if ($linkTextField = $linkField->getSubfield('z')) {
                                 $linkText = $linkTextField->getData();
                             }
                         }
                     }
                 }
             } else {
                 //Can't process the marc record, ignore it.
             }
             //If there is a link, add that status information.
             if (isset($linkURL)) {
                 $isImageLink = preg_match('/.*\\.(?:gif|jpg|jpeg|tif|tiff)/i', $linkURL);
                 $isInternalLink = preg_match('/vufind|catalog/i', $linkURL);
                 $isPurchaseLink = preg_match('/amazon|barnesandnoble/i', $linkURL);
                 if ($isImageLink == 0 && $isInternalLink == 0 && $isPurchaseLink == 0) {
                     $linkTestText = $linkText . ' ' . $linkURL;
                     $isDownload = preg_match('/SpringerLink|NetLibrary|digital media|Online version\\.|ebrary|gutenberg|emedia2go/i', $linkTestText);
                     if ($linkTestText == 'digital media') {
                         $linkText = 'OverDrive';
                     }
                     if (preg_match('/netlibrary/i', $linkURL)) {
                         $isDownload = true;
                         $linkText = 'NetLibrary';
                     } elseif (preg_match('/ebscohost/i', $linkURL)) {
                         $isDownload = true;
                         $linkText = 'Ebsco';
                     } elseif (preg_match('/overdrive|emedia2go/i', $linkURL)) {
                         $isDownload = true;
                         $linkText = 'OverDrive';
                     } elseif (preg_match('/ebrary/i', $linkURL)) {
                         $isDownload = true;
                         $linkText = 'ebrary';
                     } elseif (preg_match('/gutenberg/i', $linkURL)) {
                         $isDownload = true;
                         $linkText = 'Gutenberg Project';
                     } elseif (preg_match('/ezproxy/i', $linkURL)) {
                         $isDownload = true;
                     } elseif (preg_match('/.*\\.[pdf]/', $linkURL)) {
                         $isDownload = true;
                     }
                     if ($isDownload) {
                         $summaryInformation['status'] = "Available for Download";
                         $summaryInformation['class'] = 'here';
                         $summaryInformation['isDownloadable'] = true;
                         $summaryInformation['downloadLink'] = $linkURL;
                         $summaryInformation['downloadText'] = isset($linkText) ? $linkText : 'Download';
                         //Check to see if this is an eBook or eAudio book.  We can get this from the 245h tag
                         $isEBook = true;
                         $resource = new Resource();
                         $resource->record_id = $id;
                         $resource->source = 'VuFind';
                         if ($resource->find(true)) {
                             $formatCategory = $resource->format_category;
                             if (strcasecmp($formatCategory, 'eBooks') === 0) {
                                 $summaryInformation['eBookLink'] = $linkURL;
                             } elseif (strcasecmp($formatCategory, 'eAudio') === 0) {
                                 $summaryInformation['eAudioLink'] = $linkURL;
                             }
                         }
                     }
                 }
             }
             $timer->logTime('Checked for downloadable link in 856 tag');
         }
         $showItsHere = empty($ipLibrary) ? TRUE : $ipLibrary->showItsHere == 1;
         if ($availableHere && $showItsHere) {
             $summaryInformation['status'] = "It's Here";
             $summaryInformation['class'] = 'here';
             unset($availableLocations[$location->code]);
             $summaryInformation['currentLocation'] = $location->displayName;
             $summaryInformation['availableAt'] = join(', ', $availableLocations);
             $summaryInformation['numAvailableOther'] = count($availableLocations);
         } else {
             //Replace all spaces in the name of a location with no break spaces
             $summaryInformation['availableAt'] = join(', ', $availableLocations);
             $summaryInformation['numAvailableOther'] = count($availableLocations);
         }
         //If Status is still not set, apply some logic based on number of copies
         if (!isset($summaryInformation['status'])) {
             if ($numCopies == 0) {
                 if ($numCopiesOnOrder > 0) {
                     //No copies are currently available, but we do have some that are on order.
                     //show the status as on order and make it available.
                     $summaryInformation['status'] = "On Order";
                     $summaryInformation['class'] = 'available';
                     $summaryInformation['showPlaceHold'] = $canShowHoldButton;
                 } else {
                     //Deal with weird cases where there are no items by saying it is unavailable
                     $summaryInformation['status'] = "Unavailable";
                     $summaryInformation['showPlaceHold'] = false;
                     $summaryInformation['class'] = 'unavailable';
                 }
             } else {
                 if ($numHoldableCopies == 0 && $canShowHoldButton && (isset($summaryInformation['showPlaceHold']) && $summaryInformation['showPlaceHold'] != true)) {
                     $summaryInformation['status'] = "Not Available For Checkout";
                     $summaryInformation['showPlaceHold'] = false;
                     $summaryInformation['class'] = 'reserve';
                 } else {
                     $summaryInformation['status'] = "Checked Out";
                     $summaryInformation['showPlaceHold'] = $canShowHoldButton;
                     $summaryInformation['class'] = 'checkedOut';
                 }
             }
         }
         //Reset status if the status for all items is consistent.
         //That way it will jive with the actual full record display.
         if ($allItemStatus != null && $allItemStatus != '') {
             //Only override this for statuses that don't have special meaning
             if ($summaryInformation['status'] != 'Marmot' && $summaryInformation['status'] != 'Available At' && $summaryInformation['status'] != "It's Here") {
                 $summaryInformation['status'] = $allItemStatus;
             }
         }
         if ($allItemStatus == 'In Library Use Only') {
             $summaryInformation['inLibraryUseOnly'] = true;
         } else {
             $summaryInformation['inLibraryUseOnly'] = false;
         }
         if ($summaryInformation['availableCopies'] == 0 && $summaryInformation['isDownloadable'] == true) {
             $summaryInformation['showAvailabilityLine'] = false;
         } else {
             $summaryInformation['showAvailabilityLine'] = true;
         }
         $timer->logTime('Finished building summary');
         $memCache->set("holdings_summary_{$id}_{$locationId}", $summaryInformation, 0, $configArray['Caching']['holdings_summary']);
     }
     return $summaryInformation;
 }
Exemple #22
0
 function launch()
 {
     global $configArray;
     global $interface;
     //Grab the tracking data
     $store = urldecode(strip_tags($_GET['store']));
     $recordId = $_REQUEST['id'];
     $ipAddress = $_SERVER['REMOTE_ADDR'];
     $field856Index = isset($_REQUEST['index']) ? $_REQUEST['index'] : null;
     $libraryName = $configArray['Site']['title'];
     // Setup Search Engine Connection
     $class = $configArray['Index']['engine'];
     $url = $configArray['Index']['url'];
     $this->db = new $class($url);
     if ($configArray['System']['debugSolr']) {
         $this->db->debug = true;
     }
     // Retrieve Full Marc Record
     if (!($record = $this->db->getRecord($recordId))) {
         PEAR_Singleton::raiseError(new PEAR_Error('Record Does Not Exist'));
     }
     $this->record = $record;
     $interface->assign('record', $record);
     $titleTerm = $record["title"];
     $title = str_replace(":", " ", $titleTerm);
     $authorTerm = $record["auth_author"];
     $author = str_replace("/", "", $authorTerm);
     if ($field856Index == null) {
         // Find the store in the database
         require_once ROOT_DIR . '/Drivers/marmot_inc/BookStore.php';
         $storeDbObj = new BookStore();
         $storeDbObj->storeName = $store;
         $storeDbObj->find();
         if ($storeDbObj->N > 0) {
             $storeDbObj->fetch();
             $purchaseLinkUrl = self::getPurchaseLinkForTitle($storeDbObj->link, $title, $author, $libraryName);
         }
     } else {
         // Process MARC Data
         require_once ROOT_DIR . '/sys/MarcLoader.php';
         $marcRecord = MarcLoader::loadMarcRecordFromRecord($record);
         if ($marcRecord) {
             $this->marcRecord = $marcRecord;
         } else {
             PEAR_Singleton::raiseError(new PEAR_Error("Failed to load the MAC record for this title."));
         }
         $linkFields = $marcRecord->getFields('856');
         if ($linkFields) {
             $cur856Index = 0;
             foreach ($linkFields as $marcField) {
                 $cur856Index++;
                 if ($cur856Index == $field856Index) {
                     //Get the link
                     if ($marcField->getSubfield('u')) {
                         $link = $marcField->getSubfield('u')->getData();
                         $purchaseLinkUrl = $link;
                     }
                 }
             }
         }
     }
     //Do not track purchases from Bots
     require_once ROOT_DIR . '/sys/BotChecker.php';
     if (!BotChecker::isRequestFromBot()) {
         require_once ROOT_DIR . '/sys/PurchaseLinkTracking.php';
         $tracking = new PurchaseLinkTracking();
         $tracking->ipAddress = $ipAddress;
         $tracking->recordId = $recordId;
         $tracking->store = $store;
         $insertResult = $tracking->insert();
     }
     //redirects them to the link they clicked
     if ($purchaseLinkUrl != "") {
         header("Location:" . $purchaseLinkUrl);
     } else {
         PEAR_Singleton::raiseError(new PEAR_Error("Failed to load the store information for this title."));
     }
 }
Exemple #23
0
 function getSystemListTitles($listName)
 {
     /** @var Memcache $memCache */
     global $memCache;
     global $configArray;
     $listTitles = $memCache->get('system_list_titles_' . $listName);
     if ($listTitles == false) {
         require_once ROOT_DIR . '/services/Record/Description.php';
         //return a random selection of 30 titles from the list.
         $scrollerName = strip_tags($_GET['scrollerName']);
         $searchObj = SearchObjectFactory::initSearchObject();
         $searchObj->init();
         $searchObj->setBasicQuery("*:*");
         $searchObj->addFilter("system_list:{$listName}");
         $searchObj->setLimit(50);
         $searchObj->processSearch(false, false);
         $matchingRecords = $searchObj->getResultRecordSet();
         $listTitles = array();
         foreach ($matchingRecords as $record) {
             $isbn = $record['isbn'][0];
             if (strpos($isbn, ' ') > 0) {
                 $isbn = substr($isbn, 0, strpos($isbn, ' '));
             }
             if (isset($record['issn'])) {
                 $issn = $record['issn'][0];
                 if (strpos($issn, ' ') > 0) {
                     $issn = substr($isbn, 0, strpos($issn, ' '));
                 }
             } else {
                 $issn = '';
             }
             // Process MARC Data
             require_once ROOT_DIR . '/sys/MarcLoader.php';
             $marcRecord = MarcLoader::loadMarcRecordFromRecord($record);
             if ($marcRecord) {
                 $descriptiveInfo = Record_Description::loadDescriptionFromMarc($marcRecord);
             }
             $listTitles[] = array('id' => $record['id'], 'image' => $configArray['Site']['coverUrl'] . "/bookcover.php?id=" . $record['id'] . "&issn=" . $issn . "&isn=" . $isbn . "&size=medium&upc=" . $record['upc'][0] . "&category=" . $record['format_category'][0], 'small_image' => $configArray['Site']['coverUrl'] . "/bookcover.php?id=" . $record['id'] . "&issn=" . $issn . "&isn=" . $isbn . "&size=small&upc=" . $record['upc'][0] . "&category=" . $record['format_category'][0], 'title' => $record['title'], 'author' => $record['author'], 'description' => isset($descriptiveInfo) ? $descriptiveInfo['description'] : null, 'length' => isset($descriptiveInfo) ? $descriptiveInfo['length'] : null, 'publisher' => isset($descriptiveInfo) ? $descriptiveInfo['publisher'] : null);
         }
         $memCache->set('system_list_titles_' . $listName, $listTitles, 0, $configArray['Caching']['system_list_titles']);
     }
     return $listTitles;
 }
 private function getCoverFromMarc($marcRecord = null)
 {
     $this->log("Looking for picture as part of 856 tag.", PEAR_LOG_INFO);
     if ($marcRecord == null) {
         $this->initDatabaseConnection();
         //Process the marc record
         require_once ROOT_DIR . '/sys/MarcLoader.php';
         if ($this->isEContent) {
             $epubFile = new EContentRecord();
             $epubFile->id = $this->id;
             if ($epubFile->find(true)) {
                 $marcRecord = MarcLoader::loadEContentMarcRecord($epubFile);
             } else {
                 $marcRecord = false;
             }
         } elseif ($this->type == 'ils') {
             $marcRecord = MarcLoader::loadMarcRecordByILSId($this->id);
         }
     }
     if (!$marcRecord) {
         return false;
     }
     //Get the 856 tags
     $marcFields = $marcRecord->getFields('856');
     if ($marcFields) {
         /** @var File_MARC_Data_Field $marcField */
         foreach ($marcFields as $marcField) {
             //Check to see if this is a cover to use for VuFind
             if ($marcField->getSubfield('2') && strcasecmp(trim($marcField->getSubfield('2')->getData()), 'Vufind_Image') == 0) {
                 if ($marcField->getSubfield('3') && (strcasecmp(trim($marcField->getSubfield('3')->getData()), 'Cover Image') == 0 || strcasecmp(trim($marcField->getSubfield('3')->getData()), 'CoverImage') == 0)) {
                     //Can use either subfield f or subfield u
                     if ($marcField->getSubfield('f')) {
                         //Just references the file, add the original directory
                         $filename = $this->bookCoverPath . '/original/' . trim($marcField->getSubfield('f')->getData());
                         if ($this->processImageURL($filename, true)) {
                             //We got a successful match
                             return true;
                         }
                     } elseif ($marcField->getSubfield('u')) {
                         //Full url to the image
                         if ($this->processImageURL(trim($marcField->getSubfield('u')->getData()), true)) {
                             //We got a successful match
                             return true;
                         }
                     }
                 }
             }
         }
     }
     //Check the 690 field to see if this is a seed catalog entry
     $marcFields = $marcRecord->getFields('690');
     if ($marcFields) {
         $this->log("Found 690 field", PEAR_LOG_INFO);
         foreach ($marcFields as $marcField) {
             if ($marcField->getSubfield('a')) {
                 $this->log("Found 690a subfield", PEAR_LOG_INFO);
                 $subfield_a = $marcField->getSubfield('a')->getData();
                 if (preg_match('/seed library.*/i', $subfield_a, $matches)) {
                     $this->log("Title is a seed library title", PEAR_LOG_INFO);
                     $filename = "interface/themes/responsive/images/seed_library_logo.jpg";
                     if ($this->processImageURL($filename, true)) {
                         return true;
                     }
                 }
             } else {
                 //no image link available on this link
             }
         }
     }
     $marcFields = $marcRecord->getFields('590');
     if ($marcFields) {
         $this->log("Found 590 field", PEAR_LOG_INFO);
         foreach ($marcFields as $marcField) {
             if ($marcField->getSubfield('a')) {
                 $this->log("Found 590a subfield", PEAR_LOG_INFO);
                 $subfield_a = $marcField->getSubfield('a')->getData();
                 if (preg_match('/Colorado State Government Documents online.*/i', $subfield_a, $matches)) {
                     $this->log("Title is a Colorado state gov doc", PEAR_LOG_INFO);
                     $filename = "interface/themes/responsive/images/state_flag_of_colorado.png";
                     if ($this->processImageURL($filename, true)) {
                         return true;
                     }
                 }
             } else {
                 //no image link available on this link
             }
         }
     }
     return false;
 }