Exemplo n.º 1
0
 /**
  * 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
  *  locationCode
  *  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 getHolding($id)
 {
     if (array_key_exists($id, HorizonAPI::$loadedStatus)) {
         return HorizonAPI::$loadedStatus[$id];
     }
     global $configArray;
     global $library;
     //Get location information so we can put things into sections
     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;
     }
     //Get a list of items from Horizon
     $lookupTitleInfoUrl = $configArray['Catalog']['webServiceUrl'] . '/standard/lookupTitleInfo?clientID=' . $configArray['Catalog']['clientId'] . '&titleKey=' . $id . '&includeItemInfo=true&includeHoldCount=true';
     $lookupTitleInfoResponse = $this->getWebServiceResponse($lookupTitleInfoUrl);
     $holdings = array();
     if ($lookupTitleInfoResponse->titleInfo) {
         $i = 0;
         foreach ($lookupTitleInfoResponse->titleInfo->itemInfo as $itemInfo) {
             if (!isset($itemInfo->locationID)) {
                 //Suppress anything without a location code
                 continue;
             }
             $i++;
             $holding = array('id' => $id, 'number' => $i++, 'type' => 'holding', 'status' => isset($itemInfo->statusID) ? (string) $itemInfo->statusID : 'Unknown', 'statusfull' => isset($itemInfo->statusDescription) ? (string) $itemInfo->statusDescription : 'Unknown', 'availability' => isset($itemInfo->available) ? (string) $itemInfo->available == "true" : false, 'holdable' => true, 'reserve' => 'N', 'holdQueueLength' => (int) $lookupTitleInfoResponse->titleInfo->holdCount, 'dueDate' => isset($itemInfo->dueDate) ? (string) $itemInfo->dueDate : 'Unknown', 'locationCode' => (string) $itemInfo->locationID, 'location' => (string) $itemInfo->locationDescription, 'callnumber' => (string) $itemInfo->callNumber, 'isDownload' => false, 'barcode' => (string) $itemInfo->barcode, 'isLocalItem' => false, 'isLibraryItem' => true, 'locationLabel' => (string) $itemInfo->locationDescription, 'shelfLocation' => (string) $itemInfo->locationDescription);
             $holding['groupedStatus'] = mapValue('item_grouped_status', $holding['status']);
             $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;
                 $holding['isLocalItem'] = true;
                 $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;
                     $holding['isLocalItem'] = true;
                     $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;
                             //MDN 11/17 - taken out because all Horizon libraries are single institution (so far)
                             /*} 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'] = $library->displayName;
                             $holding['sectionId'] = 5;
                             $sorted_array['5' . $sortString] = $holding;
                         }
                     }
                 }
             }
             $holdings[] = $holding;
         }
     }
     return $holdings;
 }
Exemplo n.º 2
0
 public function parseHoldsPage($pageContents)
 {
     //global $logger;
     $availableHolds = array();
     $unavailableHolds = array();
     $holds = array('available' => $availableHolds, 'unavailable' => $unavailableHolds);
     //Get the headers from the table
     preg_match_all('/<th\\s+class="patFuncHeaders">\\s*([\\w\\s]*?)\\s*<\\/th>/si', $pageContents, $result, PREG_SET_ORDER);
     $sKeys = array();
     for ($matchi = 0; $matchi < count($result); $matchi++) {
         $sKeys[] = $result[$matchi][1];
     }
     //Get the rows for the table
     preg_match_all('/<tr\\s+class="patFuncEntry(?: on_ice)?">(.*?)<\\/tr>/si', $pageContents, $result, PREG_SET_ORDER);
     $sRows = array();
     for ($matchi = 0; $matchi < count($result); $matchi++) {
         $sRows[] = $result[$matchi][1];
     }
     $sCount = 0;
     foreach ($sRows as $sRow) {
         preg_match_all('/<td[^>]*>(.*?)<\\/td>/si', $sRow, $result, PREG_SET_ORDER);
         $sCols = array();
         for ($matchi = 0; $matchi < count($result); $matchi++) {
             $sCols[] = $result[$matchi][1];
         }
         //$sCols = preg_split("/<t(h|d)([^>]*)>/",$sRow);
         $curHold = array();
         $curHold['create'] = null;
         $curHold['reqnum'] = null;
         $curHold['holdSource'] = 'ILS';
         //Holds page occasionally has a header with number of items checked out.
         for ($i = 0; $i < sizeof($sCols); $i++) {
             $sCols[$i] = str_replace("&nbsp;", " ", $sCols[$i]);
             $sCols[$i] = preg_replace("/<br+?>/", " ", $sCols[$i]);
             $sCols[$i] = html_entity_decode(trim($sCols[$i]));
             //print_r($scols[$i]);
             /*if ($sCount <= 1) {
             			$sKeys[$i] = $sCols[$i];
             		} else if ($sCount > 1) {*/
             if ($sKeys[$i] == "CANCEL") {
                 //Only check Cancel key, not Cancel if not filled by
                 //Extract the id from the checkbox
                 $matches = array();
                 $numMatches = preg_match_all('/.*?cancel(.*?)x(\\d\\d).*/s', $sCols[$i], $matches);
                 if ($numMatches > 0) {
                     $curHold['renew'] = "BOX";
                     $curHold['cancelable'] = true;
                     $curHold['itemId'] = $matches[1][0];
                     $curHold['xnum'] = $matches[2][0];
                     $curHold['cancelId'] = $matches[1][0] . '~' . $matches[2][0];
                 } else {
                     $curHold['cancelable'] = false;
                 }
             }
             if (stripos($sKeys[$i], "TITLE") > -1) {
                 if (preg_match('/.*?<a href=\\"\\/record=(.*?)(?:~S\\d{1,2})\\">(.*?)<\\/a>.*/', $sCols[$i], $matches)) {
                     $shortId = $matches[1];
                     $bibid = '.' . $matches[1] . $this->driver->getCheckDigit($shortId);
                     $title = strip_tags($matches[2]);
                 } elseif (preg_match('/.*<a href=".*?\\/record\\/C__R(.*?)\\?.*?">(.*?)<\\/a>.*/si', $sCols[$i], $matches)) {
                     $shortId = $matches[1];
                     $bibid = '.' . $matches[1] . $this->driver->getCheckDigit($shortId);
                     $title = strip_tags($matches[2]);
                 } else {
                     //This happens for prospector titles
                     $bibid = '';
                     $shortId = '';
                     $title = trim($sCols[$i]);
                     /*global $configArray;
                     		if ($configArray['System']['debug']){
                     			echo("Unexpected format in title column.  Got " . htmlentities($sCols[$i]) . "<br/>");
                     		}*/
                 }
                 $curHold['id'] = $bibid;
                 $curHold['recordId'] = $bibid;
                 $curHold['shortId'] = $shortId;
                 $curHold['title'] = $title;
             }
             if (stripos($sKeys[$i], "Ratings") > -1) {
                 $curHold['request'] = "STARS";
             }
             if (stripos($sKeys[$i], "PICKUP LOCATION") > -1) {
                 //Extract the current location for the hold if possible
                 $matches = array();
                 if (preg_match('/<select\\s+name=loc(.*?)x(\\d\\d).*?<option\\s+value="([a-z]{1,5})[+ ]*"\\s+selected="selected">.*/s', $sCols[$i], $matches)) {
                     $curHold['locationId'] = $matches[1];
                     $curHold['locationXnum'] = $matches[2];
                     $curPickupBranch = new Location();
                     $curPickupBranch->whereAdd("code = '{$matches[3]}'");
                     $curPickupBranch->find(1);
                     if ($curPickupBranch->N > 0) {
                         $curPickupBranch->fetch();
                         $curHold['currentPickupId'] = $curPickupBranch->locationId;
                         $curHold['currentPickupName'] = $curPickupBranch->displayName;
                         $curHold['location'] = $curPickupBranch->displayName;
                     }
                     $curHold['locationUpdateable'] = true;
                     //Return the full select box for reference.
                     $curHold['locationSelect'] = $sCols[$i];
                 } else {
                     $curHold['location'] = $sCols[$i];
                     //Trim the carrier code if any
                     if (preg_match('/.*\\s[\\w\\d]{4}/', $curHold['location'])) {
                         $curHold['location'] = substr($curHold['location'], 0, strlen($curHold['location']) - 5);
                     }
                     $curHold['currentPickupName'] = $curHold['location'];
                     $curHold['locationUpdateable'] = false;
                 }
             }
             if (stripos($sKeys[$i], "STATUS") > -1) {
                 $status = trim(strip_tags($sCols[$i]));
                 $status = strtolower($status);
                 $status = ucwords($status);
                 if ($status != "&nbsp") {
                     $curHold['status'] = $status;
                     if (preg_match('/READY.*(\\d{2}-\\d{2}-\\d{2})/i', $status, $matches)) {
                         $curHold['status'] = 'Ready';
                         //Get expiration date
                         $exipirationDate = $matches[1];
                         $expireDate = DateTime::createFromFormat('m-d-y', $exipirationDate);
                         $curHold['expire'] = $expireDate->getTimestamp();
                     } elseif (preg_match('/READY\\sFOR\\sPICKUP/i', $status, $matches)) {
                         $curHold['status'] = 'Ready';
                     } else {
                         $curHold['status'] = $status;
                     }
                 } else {
                     $curHold['status'] = "Pending {$status}";
                 }
                 $matches = array();
                 $curHold['renewError'] = false;
                 if (preg_match('/.*DUE\\s(\\d{2}-\\d{2}-\\d{2}).*(?:<font color="red">\\s*(.*)<\\/font>).*/s', $sCols[$i], $matches)) {
                     //Renew error
                     $curHold['renewError'] = $matches[2];
                     $curHold['statusMessage'] = $matches[2];
                 } else {
                     if (preg_match('/.*DUE\\s(\\d{2}-\\d{2}-\\d{2})\\s(.*)?/s', $sCols[$i], $matches)) {
                         $curHold['statusMessage'] = $matches[2];
                     }
                 }
                 //$logger->log('Status for item ' . $curHold['id'] . '=' . $sCols[$i], PEAR_LOG_INFO);
             }
             if (stripos($sKeys[$i], "CANCEL IF NOT FILLED BY") > -1) {
                 //$curHold['expire'] = strip_tags($scols[$i]);
             }
             if (stripos($sKeys[$i], "FREEZE") > -1) {
                 $matches = array();
                 $curHold['frozen'] = false;
                 if (preg_match('/<input.*name="freeze(.*?)"\\s*(\\w*)\\s*\\/>/', $sCols[$i], $matches)) {
                     $curHold['freezeable'] = true;
                     if (strlen($matches[2]) > 0) {
                         $curHold['frozen'] = true;
                         $curHold['status'] = 'Frozen';
                     }
                 } elseif (preg_match('/This hold can\\s?not be frozen/i', $sCols[$i], $matches)) {
                     //If we detect an error Freezing the hold, save it so we can report the error to the user later.
                     $shortId = str_replace('.b', 'b', $curHold['id']);
                     $_SESSION['freezeResult'][$shortId]['message'] = $sCols[$i];
                     $_SESSION['freezeResult'][$shortId]['result'] = false;
                 } else {
                     $curHold['freezeable'] = false;
                 }
             }
             //}
         }
         //End of columns
         //if ($sCount > 1) {
         if (!isset($curHold['status']) || strcasecmp($curHold['status'], "ready") != 0) {
             $holds['unavailable'][] = $curHold;
         } else {
             $holds['available'][] = $curHold;
         }
         //}
         $sCount++;
     }
     //End of the row
     return $holds;
 }
Exemplo n.º 3
0
 public function getItemsFast()
 {
     global $configArray;
     if ($this->fastItems == null) {
         $searchLibrary = Library::getSearchLibrary();
         if ($searchLibrary) {
             $libraryLocationCode = $searchLibrary->ilsCode;
         }
         $searchLocation = Location::getSearchLocation();
         if ($searchLocation) {
             $homeLocationCode = $searchLocation->code;
         } else {
             $homeLocation = Location::getUserHomeLocation();
             if ($homeLocation) {
                 $homeLocationCode = $homeLocation->code;
             }
         }
         $this->fastItems = array();
         if ($this->itemsFromIndex) {
             $this->fastItems = array();
             foreach ($this->itemsFromIndex as $itemData) {
                 $isLocalItem = false;
                 $isLibraryItem = false;
                 if (array_key_exists('item', $itemData)) {
                     $itemId = $itemData['item'][0];
                     $locationCode = $itemData['item'][1];
                     $shelfLocation = mapValue('shelf_location', $locationCode);
                     $sharing = $itemData['item'][3];
                     $source = $itemData['item'][4];
                     $fileOrUrl = '';
                     if (count($itemData['item']) > 5) {
                         $fileOrUrl = $itemData['item'][5];
                     }
                     if (array_key_exists('scope', $itemData)) {
                         $isLocalItem = $itemData['scope'][1] == 'true';
                         $isLibraryItem = $itemData['scope'][2] == 'true';
                     }
                 } else {
                     $itemId = $itemData[1];
                     $locationCode = $itemData[2];
                     $shelfLocation = mapValue('shelf_location', $itemData[2]);
                     $sharing = $itemData[4];
                     $source = $itemData[5];
                     $fileOrUrl = '';
                     if (count($itemData) > 6) {
                         $fileOrUrl = $itemData[6];
                     }
                     $isLocalItem = isset($libraryLocationCode) && strlen($libraryLocationCode) > 0 && strpos($locationCode, $libraryLocationCode) === 0;
                     $isLibraryItem = isset($homeLocationCode) && strlen($homeLocationCode) > 0 && strpos($locationCode, $homeLocationCode) === 0;
                 }
                 $actions = $this->getActionsForItem($itemId, $fileOrUrl, null);
                 $libraryLabelObj = new Library();
                 $libraryLabelObj->whereAdd("'{$locationCode}' LIKE CONCAT(ilsCode, '%') and ilsCode <> ''");
                 $libraryLabelObj->selectAdd();
                 $libraryLabelObj->selectAdd('displayName');
                 if ($libraryLabelObj->find(true)) {
                     $libraryLabel = $libraryLabelObj->displayName;
                 } else {
                     $libraryLabel = $locationCode . ' Online';
                 }
                 //TODO: Get the correct number of available copies
                 $totalCopies = 1;
                 $this->fastItems[] = array('itemId' => $itemId, 'location' => $locationCode, 'callnumber' => '', 'availability' => $this->isItemAvailable($itemId, $totalCopies), 'holdable' => $this->isEContentHoldable($locationCode, $itemData), 'inLibraryUseOnly' => false, 'isLocalItem' => $isLocalItem, 'isLibraryItem' => $isLibraryItem, 'locationLabel' => 'Online', 'libraryLabel' => $libraryLabel, 'shelfLocation' => $shelfLocation, 'source' => 'Online ' . $source, 'sharing' => $sharing, 'actions' => $actions);
             }
         } else {
             /** @var File_MARC_Data_Field[] $itemFields */
             $itemFields = $this->getMarcRecord()->getFields('989');
             foreach ($itemFields as $itemField) {
                 $locationCode = trim($itemField->getSubfield('d') != null ? $itemField->getSubfield('d')->getData() : '');
                 //Each item can have multiple item fields
                 /** @var File_MARC_Subfield[] $eContentFields */
                 $eContentFields = $itemField->getSubfields('w');
                 $itemId = $itemField->getSubfield('1')->getData();
                 $iType = $itemField->getSubfield($configArray['Reindex']['iTypeSubfield'])->getData();
                 foreach ($eContentFields as $eContentField) {
                     $eContentData = trim($eContentField->getData() != null ? $eContentField->getData() : '');
                     if ($eContentData && strpos($eContentData, ':') > 0) {
                         $eContentFieldData = explode(':', $eContentData);
                         $source = trim($eContentFieldData[0]);
                         $protectionType = strtolower(trim($eContentFieldData[1]));
                         $totalCopies = 1;
                         if ($this->isValidProtectionType($protectionType)) {
                             if ($this->isValidForUser($locationCode, $eContentFieldData)) {
                                 $libraryLabelObj = new Library();
                                 $libraryLabelObj->whereAdd("'{$locationCode}' LIKE CONCAT(ilsCode, '%') and ilsCode <> ''");
                                 $libraryLabelObj->selectAdd();
                                 $libraryLabelObj->selectAdd('displayName');
                                 if ($libraryLabelObj->find(true)) {
                                     $libraryLabel = $libraryLabelObj->displayName;
                                 } else {
                                     $libraryLabel = $locationCode . ' Online';
                                 }
                                 $locationLabelObj = new Location();
                                 $locationLabelObj->whereAdd("'{$locationCode}' LIKE CONCAT(code, '%') and code <> ''");
                                 if ($locationLabelObj->find(true)) {
                                     $locationLabel = $locationLabelObj->displayName;
                                 } else {
                                     $locationLabel = $locationCode . ' Online';
                                 }
                                 //Get the file or url that is related to this item.
                                 $fileOrUrl = '';
                                 $acsId = null;
                                 if ($protectionType == 'external') {
                                     $urlSubfield = $itemField->getSubfield('u');
                                     if ($urlSubfield != null) {
                                         $fileOrUrl = $urlSubfield->getData();
                                     } else {
                                         //Get from the 856 field
                                         /** @var File_MARC_Data_Field[] $linkFields */
                                         $linkFields = $this->getMarcRecord()->getFields('856');
                                         foreach ($linkFields as $link) {
                                             $urlSubfield = $link->getSubfield('u');
                                             if ($urlSubfield != null) {
                                                 $fileOrUrl = $urlSubfield->getData();
                                             }
                                         }
                                     }
                                 } else {
                                     if (count($eContentFieldData) > 3) {
                                         $fileOrUrl = trim($eContentFieldData[3]);
                                     }
                                     if (count($eContentFieldData) > 4) {
                                         $acsId = trim($eContentFieldData[4]);
                                     }
                                     if (count($eContentFieldData) > 5) {
                                         $totalCopies = trim($eContentFieldData[5]);
                                     }
                                 }
                                 $fileOrUrl = trim($fileOrUrl);
                                 $actions = $this->getActionsForItem($itemId, $fileOrUrl, $acsId);
                                 $format = $this->getEContentFormat($fileOrUrl, $iType);
                                 $sharing = $this->getSharing($locationCode, $eContentFieldData);
                                 //Add an item
                                 $item = array('itemId' => $itemId, 'location' => $locationCode, 'locationLabel' => $locationLabel, 'libraryLabel' => $libraryLabel, 'callnumber' => '', 'availability' => $this->isItemAvailable($itemId, $totalCopies), 'holdable' => $this->isEContentHoldable($locationCode, $eContentFieldData), 'isLocalItem' => $this->isLocalItem($locationCode, $eContentFieldData), 'isLibraryItem' => $this->isLibraryItem($locationCode, $eContentFieldData), 'shelfLocation' => 'Online ' . $source, 'source' => $source, 'sharing' => $sharing, 'fileOrUrl' => $fileOrUrl, 'format' => $format, 'helpText' => $this->getHelpText($fileOrUrl), 'usageNotes' => $this->getUsageRestrictions($sharing, $libraryLabel, $locationLabel), 'formatNotes' => $this->getFormatNotes($fileOrUrl), 'size' => $this->getFileSize($fileOrUrl), 'actions' => $actions);
                                 $this->fastItems[] = $item;
                             }
                         }
                     }
                 }
             }
         }
     }
     return $this->fastItems;
 }
Exemplo n.º 4
0
 protected function _updateVuFindPatronInfo()
 {
     global $user;
     //Validate that the input data is correct
     if (isset($_POST['myLocation1']) && preg_match('/^\\d{1,3}$/', $_POST['myLocation1']) == 0) {
         PEAR_Singleton::raiseError('The 1st location had an incorrect format.');
     }
     if (isset($_POST['myLocation2']) && preg_match('/^\\d{1,3}$/', $_POST['myLocation2']) == 0) {
         PEAR_Singleton::raiseError('The 2nd location had an incorrect format.');
     }
     if (isset($_REQUEST['bypassAutoLogout'])) {
         if ($_REQUEST['bypassAutoLogout'] == 'yes') {
             $user->bypassAutoLogout = 1;
         } else {
             $user->bypassAutoLogout = 0;
         }
     }
     if (isset($_REQUEST['promptForOverdriveEmail'])) {
         if ($_REQUEST['promptForOverdriveEmail'] == 'yes') {
             $user->promptForOverdriveEmail = 1;
         } else {
             $user->promptForOverdriveEmail = 0;
         }
     }
     if (isset($_REQUEST['overdriveEmail'])) {
         $user->overdriveEmail = strip_tags($_REQUEST['overdriveEmail']);
     }
     //Make sure the selected location codes are in the database.
     if (isset($_POST['myLocation1'])) {
         $location = new Location();
         $location->whereAdd("locationId = '{$_POST['myLocation1']}'");
         $location->find();
         if ($location->N != 1) {
             PEAR_Singleton::raiseError('The 1st location could not be found in the database.');
         }
         $user->myLocation1Id = $_POST['myLocation1'];
     }
     if (isset($_POST['myLocation2'])) {
         $location = new Location();
         $location->whereAdd();
         $location->whereAdd("locationId = '{$_POST['myLocation2']}'");
         $location->find();
         if ($location->N != 1) {
             PEAR_Singleton::raiseError('The 2nd location could not be found in the database.');
         }
         $user->myLocation2Id = $_POST['myLocation2'];
     }
     $user->update();
     //Update the serialized instance stored in the session
     $_SESSION['userinfo'] = serialize($user);
 }
Exemplo n.º 5
0
 protected static function getSortingDataForHoldings()
 {
     if (self::$holdingSortingData == null) {
         global $user;
         global $library;
         global $locationSingleton;
         /** @var $locationSingleton Location */
         $holdingSortingData = array();
         //Get location information so we can put things into sections
         $physicalLocation = $locationSingleton->getPhysicalLocation();
         if ($physicalLocation != null) {
             $holdingSortingData['physicalBranch'] = $physicalLocation->holdingBranchLabel;
         } else {
             $holdingSortingData['physicalBranch'] = '';
         }
         $holdingSortingData['homeBranch'] = '';
         $homeBranchId = 0;
         $holdingSortingData['nearbyBranch1'] = '';
         $nearbyBranch1Id = 0;
         $holdingSortingData['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();
             $holdingSortingData['homeBranch'] = $userLocation->holdingBranchLabel;
         }
         //Load nearby branch 1
         $nearbyLocation1 = new Location();
         $nearbyLocation1->whereAdd("locationId = '{$nearbyBranch1Id}'");
         $nearbyLocation1->find();
         if ($nearbyLocation1->N == 1) {
             $nearbyLocation1->fetch();
             $holdingSortingData['nearbyBranch1'] = $nearbyLocation1->holdingBranchLabel;
         }
         //Load nearby branch 2
         $nearbyLocation2 = new Location();
         $nearbyLocation2->whereAdd();
         $nearbyLocation2->whereAdd("locationId = '{$nearbyBranch2Id}'");
         $nearbyLocation2->find();
         if ($nearbyLocation2->N == 1) {
             $nearbyLocation2->fetch();
             $holdingSortingData['nearbyBranch2'] = $nearbyLocation2->holdingBranchLabel;
         }
         //Get a list of the display names for all locations based on holding label.
         $locationLabels = array();
         $location = new Location();
         $location->find();
         $holdingSortingData['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($holdingSortingData['libraryLocationLabels']) > 0) {
             $holdingSortingData['libraryLocationLabels'] = '/^(' . join('|', $holdingSortingData['libraryLocationLabels']) . ').*/i';
         } else {
             $holdingSortingData['libraryLocationLabels'] = '';
         }
         self::$holdingSortingData = $holdingSortingData;
         global $timer;
         $timer->logTime("Finished loading sorting information for holdings");
     }
     return self::$holdingSortingData;
 }
Exemplo n.º 6
0
 /**
  * Get Patron Profile
  *
  * This is responsible for retrieving the profile for a specific patron.
  * Interface defined in CatalogConnection.php
  *
  * @param   array   $patron     The patron array
  * @param   boolean $forceReload Whether or not we should force a reload of the data
  * @return  array               Array of the patron's profile data
  *                              If an error occurs, return a PEAR_Error
  * @access  public
  */
 public function getMyProfile($patron, $forceReload = false)
 {
     global $timer;
     global $configArray;
     /** @var Memcache $memCache */
     global $memCache;
     global $serverName;
     $memCacheProfileKey = "patronProfile_{$serverName}_";
     if (is_object($patron)) {
         $patron = get_object_vars($patron);
         $memCacheProfileKey .= $patron['username'];
         $id2 = $this->_getBarcode($patron);
     } else {
         global $user;
         $memCacheProfileKey .= $user->username;
         $id2 = $patron['cat_password'];
     }
     if (!$forceReload && !isset($_REQUEST['reload'])) {
         $patronProfile = $memCache->get($memCacheProfileKey);
         if ($patronProfile) {
             $timer->logTime('Retrieved Cached Profile for Patron');
             return $patronProfile;
         }
     }
     global $user;
     if ($configArray['Catalog']['offline'] == true) {
         $fullName = $patron['cat_username'];
         $Address1 = "";
         $City = "";
         $State = "";
         $Zip = "";
         $finesVal = 0;
         $expireClose = false;
         $homeBranchCode = '';
         $numHoldsAvailable = '?';
         $numHoldsRequested = '?';
         if (!$user) {
             $user = new User();
             $user->cat_password = $id2;
             if ($user->find(true)) {
                 $location = new Location();
                 $location->locationId = $user->homeLocationId;
                 $location->find(1);
                 $homeBranchCode = $location->code;
             }
         }
     } else {
         //Load the raw information about the patron
         $patronDump = $this->_getPatronDump($id2);
         if (isset($patronDump['ADDRESS'])) {
             $fullAddress = $patronDump['ADDRESS'];
             $addressParts = explode('$', $fullAddress);
             $Address1 = $addressParts[0];
             $City = isset($addressParts[1]) ? $addressParts[1] : '';
             $State = isset($addressParts[2]) ? $addressParts[2] : '';
             $Zip = isset($addressParts[3]) ? $addressParts[3] : '';
             if (preg_match('/(.*?),\\s+(.*)\\s+(\\d*(?:-\\d*)?)/', $City, $matches)) {
                 $City = $matches[1];
                 $State = $matches[2];
                 $Zip = $matches[3];
             } else {
                 if (preg_match('/(.*?)\\s+(\\w{2})\\s+(\\d*(?:-\\d*)?)/', $City, $matches)) {
                     $City = $matches[1];
                     $State = $matches[2];
                     $Zip = $matches[3];
                 }
             }
         } else {
             $Address1 = "";
             $City = "";
             $State = "";
             $Zip = "";
         }
         $fullName = $patronDump['PATRN_NAME'];
         //Get additional information about the patron's home branch for display.
         $location = null;
         if (isset($patronDump['HOME_LIBR']) || isset($patronDump['HOLD_LIBR'])) {
             $homeBranchCode = isset($patronDump['HOME_LIBR']) ? $patronDump['HOME_LIBR'] : $patronDump['HOLD_LIBR'];
             $homeBranchCode = str_replace('+', '', $homeBranchCode);
             //Translate home branch to plain text
             $location = new Location();
             $location->whereAdd("code = '{$homeBranchCode}'");
             $location->find(1);
             if ($location->N == 0) {
                 unset($location);
             }
         }
         if ($user) {
             if (isset($location)) {
                 if ($user->homeLocationId == 0) {
                     $user->homeLocationId = $location->locationId;
                     if ($location->nearbyLocation1 > 0) {
                         $user->myLocation1Id = $location->nearbyLocation1;
                     } else {
                         $user->myLocation1Id = $location->locationId;
                     }
                     if ($location->nearbyLocation2 > 0) {
                         $user->myLocation2Id = $location->nearbyLocation2;
                     } else {
                         $user->myLocation2Id = $location->locationId;
                     }
                     if ($user instanceof User) {
                         //Update the database
                         $user->update();
                         //Update the serialized instance stored in the session
                         $_SESSION['userinfo'] = serialize($user);
                     }
                 } else {
                     if ($location->locationId != $user->homeLocationId) {
                         $user->homeLocationId = $location->locationId;
                         //Update the database
                         $user->update();
                         //Update the serialized instance stored in the session
                         $_SESSION['userinfo'] = serialize($user);
                     }
                 }
             }
         }
         //see if expiration date is close
         if (trim($patronDump['EXP_DATE']) != '-  -') {
             list($monthExp, $dayExp, $yearExp) = explode("-", $patronDump['EXP_DATE']);
             $timeExpire = strtotime($monthExp . "/" . $dayExp . "/" . $yearExp);
             $timeNow = time();
             $timeToExpire = $timeExpire - $timeNow;
             $expired = 0;
             if ($timeToExpire <= 30 * 24 * 60 * 60) {
                 if ($timeToExpire <= 0) {
                     $expired = 1;
                 }
                 $expireClose = 1;
             } else {
                 $expireClose = 0;
             }
         } else {
             $expired = 0;
             $expireClose = 0;
         }
         $finesVal = floatval(preg_replace('/[^\\d.]/', '', $patronDump['MONEY_OWED']));
         $numHoldsAvailable = 0;
         $numHoldsRequested = 0;
         $availableStatusRegex = isset($configArray['Catalog']['patronApiAvailableHoldsRegex']) ? $configArray['Catalog']['patronApiAvailableHoldsRegex'] : "/ST=(105|98),/";
         if (isset($patronDump) && isset($patronDump['HOLD']) && count($patronDump['HOLD']) > 0) {
             foreach ($patronDump['HOLD'] as $hold) {
                 if (preg_match("{$availableStatusRegex}", $hold)) {
                     $numHoldsAvailable++;
                 } else {
                     $numHoldsRequested++;
                 }
             }
         }
     }
     $nameParts = explode(', ', $fullName);
     $lastName = $nameParts[0];
     $secondName = isset($nameParts[1]) ? $nameParts[1] : '';
     if (strpos($secondName, ' ')) {
         $nameParts2 = explode(' ', $secondName);
         $firstName = $nameParts2[0];
     } else {
         $firstName = $secondName;
     }
     if ($user) {
         //Get display name for preferred location 1
         $myLocation1 = new Location();
         $myLocation1->whereAdd("locationId = '{$user->myLocation1Id}'");
         $myLocation1->find(1);
         //Get display name for preferred location 1
         $myLocation2 = new Location();
         $myLocation2->whereAdd("locationId = '{$user->myLocation2Id}'");
         $myLocation2->find(1);
     }
     $noticeLabels = array('-' => '', 'a' => 'Mail', 'p' => 'Telephone', 'z' => 'E-mail');
     $profile = array('lastname' => $lastName, 'firstname' => $firstName, 'fullname' => $fullName, 'address1' => $Address1, 'address2' => $City . ', ' . $State, 'city' => $City, 'state' => $State, 'zip' => $Zip, 'email' => $user && $user->email ? $user->email : (isset($patronDump) && isset($patronDump['EMAIL_ADDR']) ? $patronDump['EMAIL_ADDR'] : ''), 'overdriveEmail' => $user ? $user->overdriveEmail : (isset($patronDump) && isset($patronDump['EMAIL_ADDR']) ? $patronDump['EMAIL_ADDR'] : ''), 'promptForOverdriveEmail' => $user ? $user->promptForOverdriveEmail : 1, 'phone' => isset($patronDump) && isset($patronDump['TELEPHONE']) ? $patronDump['TELEPHONE'] : (isset($patronDump['HOME_PHONE']) ? $patronDump['HOME_PHONE'] : ''), 'workPhone' => isset($patronDump) && isset($patronDump['G/WK_PHONE']) ? $patronDump['G/WK_PHONE'] : '', 'mobileNumber' => isset($patronDump) && isset($patronDump['MOBILE_NO']) ? $patronDump['MOBILE_NO'] : '', 'fines' => isset($patronDump) ? $patronDump['MONEY_OWED'] : '0', 'finesval' => $finesVal, 'expires' => isset($patronDump) ? $patronDump['EXP_DATE'] : '', 'expireclose' => $expireClose, 'expired' => $expired, 'homeLocationCode' => isset($homeBranchCode) ? trim($homeBranchCode) : '', 'homeLocationId' => isset($location) ? $location->locationId : 0, 'homeLocation' => isset($location) ? $location->displayName : '', 'myLocation1Id' => $user ? $user->myLocation1Id : -1, 'myLocation1' => isset($myLocation1) ? $myLocation1->displayName : '', 'myLocation2Id' => $user ? $user->myLocation2Id : -1, 'myLocation2' => isset($myLocation2) ? $myLocation2->displayName : '', 'numCheckedOut' => isset($patronDump) ? $patronDump['CUR_CHKOUT'] : '?', 'numHolds' => isset($patronDump) ? isset($patronDump['HOLD']) ? count($patronDump['HOLD']) : 0 : '?', 'numHoldsAvailable' => $numHoldsAvailable, 'numHoldsRequested' => $numHoldsRequested, 'bypassAutoLogout' => $user ? $user->bypassAutoLogout : 0, 'ptype' => $user && $user->patronType ? $user->patronType : (isset($patronDump) ? $patronDump['P_TYPE'] : 0), 'notices' => isset($patronDump) ? $patronDump['NOTICE_PREF'] : '-', 'web_note' => isset($patronDump) ? isset($patronDump['WEB_NOTE']) ? $patronDump['WEB_NOTE'] : '' : '');
     if (array_key_exists($profile['notices'], $noticeLabels)) {
         $profile['noticePreferenceLabel'] = $noticeLabels[$profile['notices']];
     } else {
         $profile['noticePreferenceLabel'] = 'Unknown';
     }
     //Get eContent info as well
     require_once ROOT_DIR . '/Drivers/EContentDriver.php';
     $eContentDriver = new EContentDriver();
     $eContentAccountSummary = $eContentDriver->getAccountSummary();
     $profile = array_merge($profile, $eContentAccountSummary);
     require_once ROOT_DIR . '/Drivers/OverDriveDriverFactory.php';
     $overDriveDriver = OverDriveDriverFactory::getDriver();
     if ($overDriveDriver->isUserValidForOverDrive($user)) {
         $overDriveSummary = $overDriveDriver->getOverDriveSummary($user);
         $profile['numOverDriveCheckedOut'] = $overDriveSummary['numCheckedOut'];
         $profile['numOverDriveHoldsAvailable'] = $overDriveSummary['numAvailableHolds'];
         $profile['numOverDriveHoldsRequested'] = $overDriveSummary['numUnavailableHolds'];
         $profile['canUseOverDrive'] = true;
     } else {
         $profile['numOverDriveCheckedOut'] = 0;
         $profile['numOverDriveHoldsAvailable'] = 0;
         $profile['numOverDriveHoldsRequested'] = 0;
         $profile['canUseOverDrive'] = false;
     }
     $profile['numCheckedOutTotal'] = $profile['numCheckedOut'] + $profile['numOverDriveCheckedOut'] + $eContentAccountSummary['numEContentCheckedOut'];
     $profile['numHoldsAvailableTotal'] = $profile['numHoldsAvailable'] + $profile['numOverDriveHoldsAvailable'] + $eContentAccountSummary['numEContentAvailableHolds'];
     $profile['numHoldsRequestedTotal'] = $profile['numHoldsRequested'] + $profile['numOverDriveHoldsRequested'] + $eContentAccountSummary['numEContentUnavailableHolds'];
     $profile['numHoldsTotal'] = $profile['numHoldsAvailableTotal'] + $profile['numHoldsRequestedTotal'];
     //Get a count of the materials requests for the user
     if ($user) {
         $materialsRequest = new MaterialsRequest();
         $materialsRequest->createdBy = $user->id;
         $homeLibrary = Library::getPatronHomeLibrary();
         $statusQuery = new MaterialsRequestStatus();
         $statusQuery->isOpen = 1;
         $statusQuery->libraryId = $homeLibrary->libraryId;
         $materialsRequest->joinAdd($statusQuery);
         $materialsRequest->find();
         $profile['numMaterialsRequests'] = $materialsRequest->N;
     }
     $timer->logTime("Got Patron Profile");
     $memCache->set($memCacheProfileKey, $profile, 0, $configArray['Caching']['patron_profile']);
     return $profile;
 }
Exemplo n.º 7
0
/**
 * Update the configuration array as needed based on scoping rules defined
 * by the subdomain.
 *
 * @param array $configArray the existing main configuration options.
 *
 * @return array the configuration options adjusted based on the scoping rules.
 */
function updateConfigForScoping($configArray)
{
    global $timer;
    //Get the subdomain for the request
    global $serverName;
    //split the servername based on
    global $subdomain;
    $subdomain = null;
    if (strpos($_SERVER['SERVER_NAME'], '.')) {
        $serverComponents = explode('.', $_SERVER['SERVER_NAME']);
        if (count($serverComponents) >= 3) {
            //URL is probably of the form subdomain.marmot.org or subdomain.opac.marmot.org
            $subdomain = $serverComponents[0];
        } else {
            if (count($serverComponents) == 2) {
                //URL could be either subdomain.localhost or marmot.org. Only use the subdomain
                //If the second component is localhost.
                if (strcasecmp($serverComponents[1], 'localhost') == 0) {
                    $subdomain = $serverComponents[0];
                }
            }
        }
        //Trim off test indicator when doing lookups for library/location
        if (substr($subdomain, -1) == '2' || substr($subdomain, -1) == '3') {
            $subdomain = substr($subdomain, 0, -1);
        }
    }
    $timer->logTime('got subdomain');
    //Load the library system information
    global $library;
    global $locationSingleton;
    if (isset($_SESSION['library']) && isset($_SESSION['location'])) {
        $library = $_SESSION['library'];
        $locationSingleton = $_SESSION['library'];
    } else {
        $Library = new Library();
        $Library->whereAdd("subdomain = '{$subdomain}'");
        $Library->find();
        if ($Library->N == 1) {
            $Library->fetch();
            //Make the library information global so we can work with it later.
            $library = $Library;
        } else {
            //The subdomain can also indicate a location.
            $Location = new Location();
            $Location->whereAdd("code = '{$subdomain}'");
            $Location->find();
            if ($Location->N == 1) {
                $Location->fetch();
                //We found a location for the subdomain, get the library.
                /** @var Library $librarySingleton */
                global $librarySingleton;
                $library = $librarySingleton->getLibraryForLocation($Location->locationId);
                $locationSingleton->setActiveLocation(clone $Location);
            } else {
                //Check to see if there is only one library in the system
                $Library = new Library();
                $Library->find();
                if ($Library->N == 1) {
                    $Library->fetch();
                    $library = $Library;
                }
            }
        }
    }
    if (isset($library) && $library != null) {
        //Update the title
        $configArray['Site']['theme'] = $library->themeName . ',' . $configArray['Site']['theme'] . ',default';
        $configArray['Site']['title'] = $library->displayName;
        $location = $locationSingleton->getActiveLocation();
        //Add an extra css file for the location if it exists.
        $themes = explode(',', $library->themeName);
        foreach ($themes as $themeName) {
            if ($location != null && file_exists('./interface/themes/' . $themeName . '/images/' . $location->code . '_logo_responsive.png')) {
                $configArray['Site']['responsiveLogo'] = '/interface/themes/' . $themeName . '/images/' . $location->code . '_logo_responsive.png';
            }
            if ($subdomain != null && file_exists('./interface/themes/' . $themeName . '/images/' . $subdomain . '_logo_responsive.png')) {
                $configArray['Site']['responsiveLogo'] = '/interface/themes/' . $themeName . '/images/' . $subdomain . '_logo_responsive.png';
            }
            if ($location != null && file_exists('./interface/themes/' . $themeName . '/images/' . $location->code . '_logo_small.png')) {
                $configArray['Site']['smallLogo'] = '/interface/themes/' . $themeName . '/images/' . $location->code . '_logo_small.png';
            }
            if ($location != null && file_exists('./interface/themes/' . $themeName . '/images/' . $location->code . '_logo_large.png')) {
                $configArray['Site']['largeLogo'] = '/interface/themes/' . $themeName . '/images/' . $location->code . '_logo_large.png';
            }
        }
    }
    $timer->logTime('finished update config for scoping');
    return $configArray;
}
 /**
  * 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;
 }
Exemplo n.º 9
0
 function updateCatalogOptions()
 {
     //Validate that the input data is correct
     if (isset($_POST['myLocation1']) && preg_match('/^\\d{1,3}$/', $_POST['myLocation1']) == 0) {
         PEAR_Singleton::raiseError('The 1st location had an incorrect format.');
     }
     if (isset($_POST['myLocation2']) && preg_match('/^\\d{1,3}$/', $_POST['myLocation2']) == 0) {
         PEAR_Singleton::raiseError('The 2nd location had an incorrect format.');
     }
     if (isset($_REQUEST['bypassAutoLogout']) && ($_REQUEST['bypassAutoLogout'] == 'yes' || $_REQUEST['bypassAutoLogout'] == 'on')) {
         $this->bypassAutoLogout = 1;
     } else {
         $this->bypassAutoLogout = 0;
     }
     //Make sure the selected location codes are in the database.
     if (isset($_POST['myLocation1'])) {
         $location = new Location();
         $location->whereAdd("locationId = '{$_POST['myLocation1']}'");
         $location->find();
         if ($location->N != 1) {
             PEAR_Singleton::raiseError('The 1st location could not be found in the database.');
         }
         $this->myLocation1Id = $_POST['myLocation1'];
     }
     if (isset($_POST['myLocation2'])) {
         $location = new Location();
         $location->whereAdd();
         $location->whereAdd("locationId = '{$_POST['myLocation2']}'");
         $location->find();
         if ($location->N != 1) {
             PEAR_Singleton::raiseError('The 2nd location could not be found in the database.');
         }
         $this->myLocation2Id = $_POST['myLocation2'];
     }
     $this->update();
     //Update the serialized instance stored in the session
     $_SESSION['userinfo'] = serialize($this);
     /** @var Memcache $memCache */
     global $memCache;
     global $serverName;
     $memCache->delete("patronProfile_{$serverName}_" . $this->username);
 }
Exemplo n.º 10
0
 public function parseHoldsPage($sResult)
 {
     global $logger;
     $availableHolds = array();
     $unavailableHolds = array();
     $holds = array('available' => $availableHolds, 'unavailable' => $unavailableHolds);
     $sResult = preg_replace("/<[^<]+?>\\W<[^<]+?>\\W\\d* HOLD.?\\W<[^<]+?>\\W<[^<]+?>/", "", $sResult);
     //$logger->log('Hold information = ' . $sresult, PEAR_LOG_INFO);
     $s = substr($sResult, stripos($sResult, 'patFunc'));
     $s = substr($s, strpos($s, ">") + 1);
     $s = substr($s, 0, stripos($s, "</table"));
     $s = preg_replace("/<br \\/>/", "", $s);
     $sRows = preg_split("/<tr([^>]*)>/", $s);
     $sCount = 0;
     $sKeys = array_pad(array(), 10, "");
     foreach ($sRows as $sRow) {
         $sCols = preg_split("/<t(h|d)([^>]*)>/", $sRow);
         $curHold = array();
         $curHold['create'] = null;
         $curHold['reqnum'] = null;
         //Holds page occassionally has a header with number of items checked out.
         for ($i = 0; $i < sizeof($sCols); $i++) {
             $sCols[$i] = str_replace("&nbsp;", " ", $sCols[$i]);
             $sCols[$i] = preg_replace("/<br+?>/", " ", $sCols[$i]);
             $sCols[$i] = html_entity_decode(trim(substr($sCols[$i], 0, stripos($sCols[$i], "</t"))));
             //print_r($scols[$i]);
             if ($sCount <= 1) {
                 $sKeys[$i] = $sCols[$i];
             } else {
                 if ($sCount > 1) {
                     if ($sKeys[$i] == "CANCEL") {
                         //Only check Cancel key, not Cancel if not filled by
                         //Extract the id from the checkbox
                         $matches = array();
                         $numMatches = preg_match_all('/.*?cancel(.*?)x(\\d\\d).*/s', $sCols[$i], $matches);
                         if ($numMatches > 0) {
                             $curHold['renew'] = "BOX";
                             $curHold['cancelable'] = true;
                             $curHold['itemId'] = $matches[1][0];
                             $curHold['xnum'] = $matches[2][0];
                             $curHold['cancelId'] = $matches[1][0] . '~' . $matches[2][0];
                         } else {
                             $curHold['cancelable'] = false;
                         }
                     }
                     if (stripos($sKeys[$i], "TITLE") > -1) {
                         if (preg_match('/.*?<a href=\\"\\/record=(.*?)(?:~S\\d{1,2})\\">(.*?)<\\/a>.*/', $sCols[$i], $matches)) {
                             $shortId = $matches[1];
                             $bibid = '.' . $matches[1];
                             //Technically, this isn't corrcect since the check digit is missing
                             $title = $matches[2];
                         } else {
                             $bibid = '';
                             $shortId = '';
                             $title = trim($sCols[$i]);
                         }
                         $curHold['id'] = $bibid;
                         $curHold['shortId'] = $shortId;
                         $curHold['title'] = $title;
                     }
                     if (stripos($sKeys[$i], "Ratings") > -1) {
                         $curHold['request'] = "STARS";
                     }
                     if (stripos($sKeys[$i], "PICKUP LOCATION") > -1) {
                         //Extract the current location for the hold if possible
                         $matches = array();
                         if (preg_match('/<select\\s+name=loc(.*?)x(\\d\\d).*?<option\\s+value="([a-z]{1,5})[+ ]*"\\s+selected="selected">.*/s', $sCols[$i], $matches)) {
                             $curHold['locationId'] = $matches[1];
                             $curHold['locationXnum'] = $matches[2];
                             $curPickupBranch = new Location();
                             $curPickupBranch->whereAdd("code = '{$matches[3]}'");
                             $curPickupBranch->find(1);
                             if ($curPickupBranch->N > 0) {
                                 $curPickupBranch->fetch();
                                 $curHold['currentPickupId'] = $curPickupBranch->locationId;
                                 $curHold['currentPickupName'] = $curPickupBranch->displayName;
                                 $curHold['location'] = $curPickupBranch->displayName;
                             }
                             $curHold['locationUpdateable'] = true;
                             //Return the full select box for reference.
                             $curHold['locationSelect'] = $sCols[$i];
                         } else {
                             $curHold['location'] = $sCols[$i];
                             //Trim the carrier code if any
                             if (preg_match('/.*\\s[\\w\\d]{4}/', $curHold['location'])) {
                                 $curHold['location'] = substr($curHold['location'], 0, strlen($curHold['location']) - 5);
                             }
                             $curHold['currentPickupName'] = $curHold['location'];
                             $curHold['locationUpdateable'] = false;
                         }
                     }
                     if (stripos($sKeys[$i], "STATUS") > -1) {
                         $status = trim(strip_tags($sCols[$i]));
                         $status = strtolower($status);
                         $status = ucwords($status);
                         if ($status != "&nbsp") {
                             $curHold['status'] = $status;
                             if (preg_match('/READY.*(\\d{2}-\\d{2}-\\d{2})/i', $status, $matches)) {
                                 $curHold['status'] = 'Ready';
                                 //Get expiration date
                                 $exipirationDate = $matches[1];
                                 $expireDate = DateTime::createFromFormat('m-d-y', $exipirationDate);
                                 $curHold['expire'] = $expireDate->getTimestamp();
                             } elseif (preg_match('/READY\\sFOR\\sPICKUP/i', $status, $matches)) {
                                 $curHold['status'] = 'Ready';
                             } else {
                                 $curHold['status'] = $status;
                             }
                         } else {
                             $curHold['status'] = "Pending {$status}";
                         }
                         $matches = array();
                         $curHold['renewError'] = false;
                         if (preg_match('/.*DUE\\s(\\d{2}-\\d{2}-\\d{2}).*(?:<font color="red">\\s*(.*)<\\/font>).*/s', $sCols[$i], $matches)) {
                             //Renew error
                             $curHold['renewError'] = $matches[2];
                             $curHold['statusMessage'] = $matches[2];
                         } else {
                             if (preg_match('/.*DUE\\s(\\d{2}-\\d{2}-\\d{2})\\s(.*)?/s', $sCols[$i], $matches)) {
                                 $curHold['statusMessage'] = $matches[2];
                             }
                         }
                         $logger->log('Status for item ' . $curHold['id'] . '=' . $sCols[$i], PEAR_LOG_INFO);
                     }
                     if (stripos($sKeys[$i], "CANCEL IF NOT FILLED BY") > -1) {
                         //$curHold['expire'] = strip_tags($scols[$i]);
                     }
                     if (stripos($sKeys[$i], "FREEZE") > -1) {
                         $matches = array();
                         $curHold['frozen'] = false;
                         if (preg_match('/<input.*name="freeze(.*?)"\\s*(\\w*)\\s*\\/>/', $sCols[$i], $matches)) {
                             $curHold['freezeable'] = true;
                             if (strlen($matches[2]) > 0) {
                                 $curHold['frozen'] = true;
                                 $curHold['status'] = 'Frozen';
                             }
                         } elseif (preg_match('/This hold can\\s?not be frozen/i', $sCols[$i], $matches)) {
                             //If we detect an error Freezing the hold, save it so we can report the error to the user later.
                             $shortId = str_replace('.b', 'b', $curHold['id']);
                             $_SESSION['freezeResult'][$shortId]['message'] = $sCols[$i];
                             $_SESSION['freezeResult'][$shortId]['result'] = false;
                         } else {
                             $curHold['freezeable'] = false;
                         }
                     }
                 }
             }
         }
         //End of columns
         if ($sCount > 1) {
             if (!isset($curHold['status']) || strcasecmp($curHold['status'], "ready") != 0) {
                 $holds['unavailable'][] = $curHold;
             } else {
                 $holds['available'][] = $curHold;
             }
         }
         $sCount++;
     }
     //End of the row
     return $holds;
 }
 /**
  * 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;
     }
 }
Exemplo n.º 12
0
 /**
  * In Sierra, all status information is up to date within the MARC record
  * due to the export so we don't need to screen scrape!
  *
  * 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
  *  reserve
  *  holdQueueLength
  *  duedate
  *  location
  *  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)
 {
     $recordDriver = RecordDriverFactory::initRecordDriverById('ils:' . $id);
     $format = $recordDriver->getFormat();
     if ($format[0] == 'Journal') {
         return parent::getStatus($id);
     }
     if (array_key_exists($id, SierraStatusLoader::$loadedStatus)) {
         return SierraStatusLoader::$loadedStatus[$id];
     }
     //Load local information
     global $library;
     global $locationSingleton;
     /** @var $locationSingleton Location */
     global $user;
     $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;
     }
     //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 = '';
     }
     //In Sierra, we can just load data from the MARC Record/Index
     $items = $recordDriver->getItemsFast();
     $holdQueueLength = $recordDriver->getNumHolds();
     $itemStatus = array();
     $i = 0;
     foreach ($items as $item) {
         //Determine what section this holding is in
         $sectionId = 1;
         $location = $item['shelfLocation'];
         if (strlen($physicalBranch) > 0 && stripos($location, $physicalBranch) !== false) {
             //If the user is in a branch, those holdings come first.
             $section = 'In this library';
             $sectionId = 1;
         } else {
             if (strlen($homeBranch) > 0 && stripos($location, $homeBranch) !== false) {
                 //Next come the user's home branch if the user is logged in or has the home_branch cookie set.
                 $section = 'Your library';
                 $sectionId = 2;
             } else {
                 if (strlen($nearbyBranch1) > 0 && stripos($location, $nearbyBranch1) !== false) {
                     //Next come nearby locations for the user
                     $section = 'Nearby Libraries';
                     $sectionId = 3;
                 } else {
                     if (strlen($nearbyBranch2) > 0 && stripos($location, $nearbyBranch2) !== false) {
                         //Next come nearby locations for the user
                         $section = 'Nearby Libraries';
                         $sectionId = 4;
                     } else {
                         if (strlen($libraryLocationLabels) > 0 && preg_match($libraryLocationLabels, $location)) {
                             //Next come any locations within the same system we are in.
                             $section = $library->displayName;
                             $sectionId = 5;
                         } else {
                             //Finally, all other holdings are shown sorted alphabetically.
                             $section = 'Other Locations';
                             $sectionId = 6;
                         }
                     }
                 }
             }
         }
         $holding = array('location' => $item['shelfLocation'], 'reserve' => stripos($item['shelfLocation'], 'reserve') !== false ? 'Y' : 'N', 'callnumber' => $item['callnumber'], 'status' => $item['status'], 'duedate' => $item['dueDate'], 'lastCheckinDate' => $item['lastCheckinDate'], 'statusfull' => $this->translateStatusCode($item['status'], $item['dueDate']), 'id' => $id, 'number' => $i++, 'holdQueueLength' => $holdQueueLength, 'type' => 'holding', 'availability' => $item['availability'], 'holdable' => $item['holdable'] ? 1 : 0, 'libraryDisplayName' => $item['shelfLocation'], 'locationCode' => $item['location'], 'iType' => $item['iType'], 'section' => $section, 'sectionId' => $sectionId);
         $paddedNumber = str_pad($i, 3, '0', STR_PAD_LEFT);
         $holdingKey = $sectionId . $holding['location'] . $paddedNumber;
         $itemStatus[$holdingKey] = $holding;
     }
     ksort($itemStatus);
     SierraStatusLoader::$loadedStatus[$id] = $itemStatus;
     return $itemStatus;
 }