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(" ", " ", $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 != " ") { $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; }
private function parseReadingHistoryPage($pageContents, $patron, $sortOption, $recordsRead) { set_time_limit(60); //Get the headers from the table preg_match_all('/<th\\s+class="patFuncHeaders">\\s*(.*?)\\s*<\\/th>/si', $pageContents, $result, PREG_SET_ORDER); $sKeys = array(); for ($matchi = 0; $matchi < count($result); $matchi++) { $sKeys[] = strip_tags($result[$matchi][1]); } //Get the rows for the table preg_match_all('/<tr\\s+class="patFuncEntry">(.*?)<\\/tr>/si', $pageContents, $result, PREG_SET_ORDER); $sRows = array(); for ($matchi = 0; $matchi < count($result); $matchi++) { $sRows[] = $result[$matchi][1]; } $sCount = 1; $readingHistoryTitles = array(); 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]; } $historyEntry = array(); for ($i = 0; $i < sizeof($sCols); $i++) { $sCols[$i] = str_replace(" ", " ", $sCols[$i]); $sCols[$i] = preg_replace("/<br+?>/", " ", $sCols[$i]); $sCols[$i] = html_entity_decode(trim($sCols[$i])); if (stripos($sKeys[$i], "Mark") > -1) { if (preg_match('/id="rsh(\\d+)"/', $sCols[$i], $matches)) { $itemIndex = $matches[1]; $historyEntry['itemindex'] = $itemIndex; } $historyEntry['deletable'] = "BOX"; } if (stripos($sKeys[$i], "Title") > -1) { //echo("Title value is <br/>$sCols[$i]<br/>"); if (preg_match('/.*?<a href=\\"\\/record=(.*?)(?:~S\\d{1,2})\\">(.*?)<\\/a>.*/', $sCols[$i], $matches)) { $shortId = $matches[1]; $bibId = '.' . $matches[1]; $historyEntry['id'] = $bibId; $historyEntry['shortId'] = $shortId; } elseif (preg_match('/.*<a href=".*?\\/record\\/C__R(.*?)\\?.*?">(.*?)<\\/a>.*/si', $sCols[$i], $matches)) { $shortId = $matches[1]; $bibId = '.' . $matches[1] . $this->driver->getCheckDigit($shortId); $historyEntry['id'] = $bibId; $historyEntry['shortId'] = $shortId; } $title = strip_tags($sCols[$i]); $historyEntry['title'] = utf8_encode($title); } if (stripos($sKeys[$i], "Author") > -1) { $historyEntry['author'] = utf8_encode(strip_tags($sCols[$i])); } if (stripos($sKeys[$i], "Checked Out") > -1) { $historyEntry['checkout'] = strip_tags($sCols[$i]); } if (stripos($sKeys[$i], "Details") > -1) { $historyEntry['details'] = strip_tags($sCols[$i]); } if (is_array($patron)) { $historyEntry['borrower_num'] = $patron['id']; } else { $historyEntry['borrower_num'] = $patron->id; } } //Done processing row $historyEntry['title_sort'] = preg_replace('/[^a-z\\s]/', '', strtolower($historyEntry['title'])); //$historyEntry['itemindex'] = $itemindex++; if ($sortOption == "title") { $titleKey = $historyEntry['title_sort']; } elseif ($sortOption == "author") { $titleKey = $historyEntry['author'] . "_" . $historyEntry['title_sort']; } elseif ($sortOption == "checkedOut" || $sortOption == "returned") { $checkoutTime = DateTime::createFromFormat('m-d-Y', $historyEntry['checkout']); if ($checkoutTime) { $titleKey = $checkoutTime->getTimestamp() . "_" . $historyEntry['title_sort']; } else { //print_r($historyEntry); $titleKey = $historyEntry['title_sort']; } } elseif ($sortOption == "format") { $titleKey = $historyEntry['format'] . "_" . $historyEntry['title_sort']; } else { $titleKey = $historyEntry['title_sort']; } $titleKey .= '_' . ($sCount + $recordsRead); $readingHistoryTitles[$titleKey] = $historyEntry; $sCount++; } //processed all rows in the table return $readingHistoryTitles; }
public function getMyTransactions($page = 1, $recordsPerPage = -1, $sortOption = 'dueDate') { global $timer; $patronDump = $this->driver->_getPatronDump($this->driver->_getBarcode()); $timer->logTime("Ready to load checked out titles from Millennium"); //Load the information from millennium using CURL $sResult = $this->driver->_fetchPatronInfoPage($patronDump, 'items'); $timer->logTime("Loaded checked out titles from Millennium"); $sResult = preg_replace("/<[^<]+?>\\W<[^<]+?>\\W\\d* ITEM.? CHECKED OUT<[^<]+?>\\W<[^<]+?>/i", "", $sResult); $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, ""); $checkedOutTitles = array(); //Get patron's location to determine if renewals are allowed. global $locationSingleton; /** @var Location $patronLocation */ $patronLocation = $locationSingleton->getUserHomeLocation(); if (isset($patronLocation)) { $patronPType = $this->driver->getPType(); $patronCanRenew = false; if ($patronLocation->ptypesToAllowRenewals == '*') { $patronCanRenew = true; } else { if (preg_match("/^({$patronLocation->ptypesToAllowRenewals})\$/", $patronPType)) { $patronCanRenew = true; } } } else { $patronCanRenew = true; } $timer->logTime("Determined if patron can renew"); foreach ($sRows as $srow) { $scols = preg_split("/<t(h|d)([^>]*)>/", $srow); $curTitle = array(); for ($i = 0; $i < sizeof($scols); $i++) { $scols[$i] = str_replace(" ", " ", $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 (stripos($sKeys[$i], "TITLE") > -1) { if (preg_match('/.*?<a href=\\"\\/record=(.*?)(?:~S\\d{1,2})\\">(.*?)<\\/a>.*/', $scols[$i], $matches)) { //Standard Millennium WebPAC $shortId = $matches[1]; $bibid = '.' . $matches[1]; //Technically, this isn't correct since the check digit is missing $title = strip_tags($matches[2]); } elseif (preg_match('/.*<a href=".*?\\/record\\/C__R(.*?)\\?.*?">(.*?)<\\/a>.*/si', $scols[$i], $matches)) { //Encore $shortId = $matches[1]; $bibid = '.' . $matches[1]; //Technically, this isn't correct since the check digit is missing $title = strip_tags($matches[2]); } else { $title = strip_tags($scols[$i]); $shortId = ''; $bibid = ''; } $curTitle['checkoutSource'] = 'ILS'; $curTitle['shortId'] = $shortId; $curTitle['id'] = $bibid; $curTitle['title'] = utf8_encode($title); } if (stripos($sKeys[$i], "STATUS") > -1) { // $sret[$scount-2]['duedate'] = strip_tags($scols[$i]); $due = trim(str_replace("DUE", "", strip_tags($scols[$i]))); $renewCount = 0; if (preg_match('/FINE\\(up to now\\) (\\$\\d+\\.\\d+)/i', $due, $matches)) { $curTitle['fine'] = trim($matches[1]); } if (preg_match('/(.*)Renewed (\\d+) time(?:s)?/i', $due, $matches)) { $due = trim($matches[1]); $renewCount = $matches[2]; } else { if (preg_match('/(.*)\\+\\d+ HOLD.*/i', $due, $matches)) { $due = trim($matches[1]); } } if (preg_match('/(\\d{2}-\\d{2}-\\d{2})/', $due, $dueMatches)) { $dateDue = DateTime::createFromFormat('m-d-y', $dueMatches[1]); if ($dateDue) { $dueTime = $dateDue->getTimestamp(); } else { $dueTime = null; } } else { $dueTime = strtotime($due); } if ($dueTime != null) { $daysUntilDue = ceil(($dueTime - time()) / (24 * 60 * 60)); $overdue = $daysUntilDue < 0; $curTitle['duedate'] = $dueTime; $curTitle['overdue'] = $overdue; $curTitle['daysUntilDue'] = $daysUntilDue; } $curTitle['renewCount'] = $renewCount; } if (stripos($sKeys[$i], "BARCODE") > -1) { $curTitle['barcode'] = strip_tags($scols[$i]); } if (stripos($sKeys[$i], "RENEW") > -1) { $matches = array(); if (preg_match('/<input\\s*type="checkbox"\\s*name="renew(\\d+)"\\s*id="renew(\\d+)"\\s*value="(.*?)"\\s*\\/>/', $scols[$i], $matches)) { $curTitle['canrenew'] = $patronCanRenew; $curTitle['itemindex'] = $matches[1]; $curTitle['itemid'] = $matches[3]; $curTitle['renewIndicator'] = $curTitle['itemid'] . '|' . $curTitle['itemindex']; $curTitle['renewMessage'] = ''; } else { $curTitle['canrenew'] = false; } } if (stripos($sKeys[$i], "CALL NUMBER") > -1) { $curTitle['request'] = "null"; } } } } if ($sCount > 1) { //Get additional information from resources table if ($curTitle['shortId'] && strlen($curTitle['shortId']) > 0) { $checkDigit = $this->driver->getCheckDigit($curTitle['shortId']); $curTitle['recordId'] = '.' . $curTitle['shortId'] . $checkDigit; $curTitle['id'] = '.' . $curTitle['shortId'] . $checkDigit; require_once ROOT_DIR . '/RecordDrivers/MarcRecord.php'; $recordDriver = new MarcRecord($curTitle['recordId']); if ($recordDriver->isValid()) { $curTitle['coverUrl'] = $recordDriver->getBookcoverUrl('medium'); $curTitle['groupedWorkId'] = $recordDriver->getGroupedWorkId(); $formats = $recordDriver->getFormats(); $curTitle['format'] = reset($formats); $curTitle['author'] = $recordDriver->getPrimaryAuthor(); if (!isset($curTitle['title']) || empty($curTitle['title'])) { $curTitle['title'] = $recordDriver->getTitle(); } } else { $curTitle['coverUrl'] = ""; $curTitle['groupedWorkId'] = ""; $curTitle['format'] = "Unknown"; $curTitle['author'] = ""; } } $sortTitle = isset($curTitle['title_sort']) ? $curTitle['title_sort'] : $curTitle['title']; $sortKey = $sortTitle; if ($sortOption == 'title') { $sortKey = $sortTitle; } elseif ($sortOption == 'author') { $sortKey = (isset($curTitle['author']) ? $curTitle['author'] : "Unknown") . '-' . $sortTitle; } elseif ($sortOption == 'dueDate') { if (isset($curTitle['duedate'])) { if (preg_match('/.*?(\\d{1,2})[-\\/](\\d{1,2})[-\\/](\\d{2,4}).*/', $curTitle['duedate'], $matches)) { $sortKey = $matches[3] . '-' . $matches[1] . '-' . $matches[2] . '-' . $sortTitle; } else { $sortKey = $curTitle['duedate'] . '-' . $sortTitle; } } } elseif ($sortOption == 'format') { $sortKey = (isset($curTitle['format']) ? $curTitle['format'] : "Unknown") . '-' . $sortTitle; } elseif ($sortOption == 'renewed') { $sortKey = (isset($curTitle['renewCount']) ? $curTitle['renewCount'] : 0) . '-' . $sortTitle; } elseif ($sortOption == 'holdQueueLength') { $sortKey = (isset($curTitle['holdQueueLength']) ? $curTitle['holdQueueLength'] : 0) . '-' . $sortTitle; } $sortKey .= "_{$sCount}"; $checkedOutTitles[utf8_encode($sortKey)] = $curTitle; } $sCount++; } ksort($checkedOutTitles); $timer->logTime("Parsed checkout information"); $numTransactions = count($checkedOutTitles); //Process pagination if ($recordsPerPage != -1) { $startRecord = ($page - 1) * $recordsPerPage; if ($startRecord > $numTransactions) { $startRecord = 0; } $checkedOutTitles = array_slice($checkedOutTitles, $startRecord, $recordsPerPage); } return array('transactions' => $checkedOutTitles, 'numTransactions' => $numTransactions); }