public function renewItem($itemId, $itemIndex)
 {
     global $logger;
     global $configArray;
     global $analytics;
     //Setup the call to Millennium
     $patronDump = $this->driver->_getPatronDump($this->driver->_getBarcode());
     $extraGetInfo = array('currentsortorder' => 'current_checkout', 'renewsome' => 'YES', 'renew' . $itemIndex => $itemId);
     $get_items = array();
     foreach ($extraGetInfo as $key => $value) {
         $get_items[] = $key . '=' . urlencode($value);
     }
     $renewItemParams = implode('&', $get_items);
     //Login to the patron's account
     $cookieJar = tempnam("/tmp", "CURLCOOKIE");
     $curl_url = $configArray['Catalog']['url'] . "/patroninfo";
     //$logger->log('Loading page ' . $curl_url, PEAR_LOG_INFO);
     $curl_connection = curl_init($curl_url);
     curl_setopt($curl_connection, CURLOPT_CONNECTTIMEOUT, 30);
     curl_setopt($curl_connection, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
     curl_setopt($curl_connection, CURLOPT_RETURNTRANSFER, true);
     curl_setopt($curl_connection, CURLOPT_SSL_VERIFYPEER, false);
     curl_setopt($curl_connection, CURLOPT_FOLLOWLOCATION, 1);
     curl_setopt($curl_connection, CURLOPT_UNRESTRICTED_AUTH, true);
     curl_setopt($curl_connection, CURLOPT_COOKIEJAR, $cookieJar);
     curl_setopt($curl_connection, CURLOPT_COOKIESESSION, false);
     curl_setopt($curl_connection, CURLOPT_POST, true);
     $post_data = $this->driver->_getLoginFormValues();
     $post_items = array();
     foreach ($post_data as $key => $value) {
         $post_items[] = $key . '=' . urlencode($value);
     }
     $post_string = implode('&', $post_items);
     curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
     curl_exec($curl_connection);
     //Go to the items page
     $scope = $this->driver->getDefaultScope();
     $curl_url = $configArray['Catalog']['url'] . "/patroninfo~S{$scope}/" . $patronDump['RECORD_#'] . "/items";
     curl_setopt($curl_connection, CURLOPT_URL, $curl_url);
     curl_setopt($curl_connection, CURLOPT_HTTPGET, true);
     curl_exec($curl_connection);
     //Post renewal information
     $curl_url = $configArray['Catalog']['url'] . "/patroninfo~S{$scope}/" . $patronDump['RECORD_#'] . "/items";
     curl_setopt($curl_connection, CURLOPT_URL, $curl_url);
     curl_setopt($curl_connection, CURLOPT_POST, true);
     curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $renewItemParams);
     $checkedOutPageText = curl_exec($curl_connection);
     //Parse the checked out titles into individual rows
     $message = 'Unable to load renewal information for this entry';
     $success = false;
     if (preg_match('/<h2>\\s*You cannot renew items because:\\s*<\\/h2><ul><li>(.*?)<\\/ul>/si', $checkedOutPageText, $matches)) {
         $success = false;
         $message = 'Unable to renew this item, ' . strtolower($matches[1]) . '.';
         if ($analytics) {
             $analytics->addEvent('ILS Integration', 'Renew Failed', strtolower($matches[1]));
         }
     } else {
         if (preg_match('/Your record is in use/si', $checkedOutPageText, $matches)) {
             $success = false;
             $message = 'Unable to renew this item now, your account is in use by the system.  Please try again later.';
             if ($analytics) {
                 $analytics->addEvent('ILS Integration', 'Renew Failed', 'Account in Use');
             }
         } else {
             if (preg_match('/<table border="0" class="patFunc">(.*?)<\\/table>/s', $checkedOutPageText, $matches)) {
                 $checkedOutTitleTable = $matches[1];
                 //$logger->log("Found checked out titles table", PEAR_LOG_DEBUG);
                 if (preg_match_all('/<tr class="patFuncEntry">(.*?)<\\/tr>/s', $checkedOutTitleTable, $rowMatches, PREG_SET_ORDER)) {
                     //$logger->log("Checked out titles table has " . count($rowMatches) . "rows", PEAR_LOG_DEBUG);
                     //$logger->log(print_r($rowMatches, true), PEAR_LOG_DEBUG);
                     for ($i = 0; $i < count($rowMatches); $i++) {
                         $rowData = $rowMatches[$i][1];
                         if (preg_match("/{$itemId}/", $rowData)) {
                             //$logger->log("Found the row for this item", PEAR_LOG_DEBUG);
                             //Extract the renewal message
                             if (preg_match('/<td align="left" class="patFuncStatus">.*?<em><font color="red">(.*?)<\\/font><\\/em>.*?<\\/td>/s', $rowData, $statusMatches)) {
                                 $success = false;
                                 $message = 'Unable to renew this item, ' . $statusMatches[1];
                             } elseif (preg_match('/<td align="left" class="patFuncStatus">.*?<em>(.*?)<\\/em>.*?<\\/td>/s', $rowData, $statusMatches)) {
                                 $success = true;
                                 $message = 'Your item was successfully renewed';
                             }
                             $logger->log("Renew success = {$success}, {$message}", PEAR_LOG_DEBUG);
                         }
                     }
                 } else {
                     $logger->log("Did not find any rows for the table {$checkedOutTitleTable}", PEAR_LOG_DEBUG);
                 }
             } else {
                 $success = true;
                 $message = 'Your item was successfully renewed';
                 if ($analytics) {
                     $analytics->addEvent('ILS Integration', 'Renew Successful');
                 }
             }
         }
     }
     curl_close($curl_connection);
     unlink($cookieJar);
     return array('itemId' => $itemId, 'result' => $success, 'message' => $message);
 }
 /**
  * Do an update or edit of reading history information.  Current actions are:
  * deleteMarked
  * deleteAll
  * exportList
  * optOut
  *
  * @param   string  $action         The action to perform
  * @param   array   $selectedTitles The titles to do the action on if applicable
  */
 function doReadingHistoryAction($action, $selectedTitles)
 {
     global $configArray;
     global $analytics;
     $patronDump = $this->driver->_getPatronDump($this->driver->_getBarcode());
     //Load the reading history page
     $scope = $this->driver->getDefaultScope();
     $curl_url = $configArray['Catalog']['url'] . "/patroninfo~S{$scope}/" . $patronDump['RECORD_#'] . "/readinghistory";
     $cookie = tempnam("/tmp", "CURLCOOKIE");
     $curl_connection = curl_init($curl_url);
     curl_setopt($curl_connection, CURLOPT_CONNECTTIMEOUT, 30);
     curl_setopt($curl_connection, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
     curl_setopt($curl_connection, CURLOPT_RETURNTRANSFER, true);
     curl_setopt($curl_connection, CURLOPT_SSL_VERIFYPEER, false);
     curl_setopt($curl_connection, CURLOPT_FOLLOWLOCATION, 1);
     curl_setopt($curl_connection, CURLOPT_UNRESTRICTED_AUTH, true);
     curl_setopt($curl_connection, CURLOPT_COOKIEJAR, $cookie);
     curl_setopt($curl_connection, CURLOPT_COOKIESESSION, true);
     curl_setopt($curl_connection, CURLOPT_POST, true);
     $post_data = $this->driver->_getLoginFormValues();
     $post_items = array();
     foreach ($post_data as $key => $value) {
         $post_items[] = $key . '=' . urlencode($value);
     }
     $post_string = implode('&', $post_items);
     curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
     $loginResult = curl_exec($curl_connection);
     //When a library uses Encore, the initial login does a redirect and requires additional parameters.
     if (preg_match('/<input type="hidden" name="lt" value="(.*?)" \\/>/si', $loginResult, $loginMatches)) {
         //Get the lt value
         $lt = $loginMatches[1];
         //Login again
         $post_data['lt'] = $lt;
         $post_data['_eventId'] = 'submit';
         $post_items = array();
         foreach ($post_data as $key => $value) {
             $post_items[] = $key . '=' . $value;
         }
         $post_string = implode('&', $post_items);
         curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
         curl_exec($curl_connection);
     }
     if ($action == 'deleteMarked') {
         //Load patron page readinghistory/rsh with selected titles marked
         if (!isset($selectedTitles) || count($selectedTitles) == 0) {
             return;
         }
         $titles = array();
         foreach ($selectedTitles as $titleId) {
             $titles[] = $titleId . '=1';
         }
         $title_string = implode('&', $titles);
         //Issue a get request to delete the item from the reading history.
         //Note: Millennium really does issue a malformed url, and it is required
         //to make the history delete properly.
         $curl_url = $configArray['Catalog']['url'] . "/patroninfo~S{$scope}/" . $patronDump['RECORD_#'] . "/readinghistory/rsh&" . $title_string;
         curl_setopt($curl_connection, CURLOPT_HTTPGET, true);
         curl_setopt($curl_connection, CURLOPT_URL, $curl_url);
         curl_exec($curl_connection);
         if ($analytics) {
             $analytics->addEvent('ILS Integration', 'Delete Marked Reading History Titles');
         }
     } elseif ($action == 'deleteAll') {
         //load patron page readinghistory/rah
         $curl_url = $configArray['Catalog']['url'] . "/patroninfo~S{$scope}/" . $patronDump['RECORD_#'] . "/readinghistory/rah";
         curl_setopt($curl_connection, CURLOPT_URL, $curl_url);
         curl_setopt($curl_connection, CURLOPT_HTTPGET, true);
         curl_exec($curl_connection);
         if ($analytics) {
             $analytics->addEvent('ILS Integration', 'Delete All Reading History Titles');
         }
     } elseif ($action == 'exportList') {
         //Leave this unimplemented for now.
     } elseif ($action == 'optOut') {
         //load patron page readinghistory/OptOut
         $curl_url = $configArray['Catalog']['url'] . "/patroninfo~S{$scope}/" . $patronDump['RECORD_#'] . "/readinghistory/OptOut";
         curl_setopt($curl_connection, CURLOPT_URL, $curl_url);
         curl_setopt($curl_connection, CURLOPT_HTTPGET, true);
         curl_exec($curl_connection);
         if ($analytics) {
             $analytics->addEvent('ILS Integration', 'Opt Out of Reading History');
         }
     } elseif ($action == 'optIn') {
         //load patron page readinghistory/OptIn
         $curl_url = $configArray['Catalog']['url'] . "/patroninfo~S{$scope}/" . $patronDump['RECORD_#'] . "/readinghistory/OptIn";
         curl_setopt($curl_connection, CURLOPT_URL, $curl_url);
         curl_setopt($curl_connection, CURLOPT_HTTPGET, true);
         curl_exec($curl_connection);
         if ($analytics) {
             $analytics->addEvent('ILS Integration', 'Opt in to Reading History');
         }
     }
     curl_close($curl_connection);
     unlink($cookie);
 }
 public function renewItem($itemId, $itemIndex)
 {
     global $logger;
     global $configArray;
     global $analytics;
     //Setup the call to Millennium
     $patronDump = $this->driver->_getPatronDump($this->driver->_getBarcode());
     $extraGetInfo = array('currentsortorder' => 'current_checkout', 'renewsome' => 'YES', 'renew' . $itemIndex => $itemId);
     $renewItemParams = http_build_query($extraGetInfo);
     //Login to the patron's account
     $cookieJar = tempnam("/tmp", "CURLCOOKIE");
     $curl_url = $configArray['Catalog']['url'] . "/patroninfo";
     //$logger->log('Loading page ' . $curl_url, PEAR_LOG_INFO);
     $curl_connection = curl_init($curl_url);
     curl_setopt($curl_connection, CURLOPT_CONNECTTIMEOUT, 30);
     curl_setopt($curl_connection, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
     curl_setopt($curl_connection, CURLOPT_RETURNTRANSFER, true);
     curl_setopt($curl_connection, CURLOPT_SSL_VERIFYPEER, false);
     curl_setopt($curl_connection, CURLOPT_FOLLOWLOCATION, 1);
     curl_setopt($curl_connection, CURLOPT_UNRESTRICTED_AUTH, true);
     curl_setopt($curl_connection, CURLOPT_COOKIEJAR, $cookieJar);
     curl_setopt($curl_connection, CURLOPT_COOKIESESSION, false);
     curl_setopt($curl_connection, CURLOPT_POST, true);
     $post_data = $this->driver->_getLoginFormValues();
     $post_string = http_build_query($post_data);
     curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
     $loginResult = curl_exec($curl_connection);
     //When a library uses Encore, the initial login does a redirect and requires additional parameters.
     if (preg_match('/<input type="hidden" name="lt" value="(.*?)" \\/>/si', $loginResult, $loginMatches)) {
         //Get the lt value
         $lt = $loginMatches[1];
         //Login again
         $post_data['lt'] = $lt;
         $post_data['_eventId'] = 'submit';
         $post_string = http_build_query($post_data);
         curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
         $loginResult = curl_exec($curl_connection);
         $curlInfo = curl_getinfo($curl_connection);
     }
     //Go to the items page
     $scope = $this->driver->getDefaultScope();
     $curl_url = $configArray['Catalog']['url'] . "/patroninfo~S{$scope}/" . $patronDump['RECORD_#'] . "/items";
     curl_setopt($curl_connection, CURLOPT_URL, $curl_url);
     curl_setopt($curl_connection, CURLOPT_HTTPGET, true);
     curl_exec($curl_connection);
     //Post renewal information
     $curl_url = $configArray['Catalog']['url'] . "/patroninfo~S{$scope}/" . $patronDump['RECORD_#'] . "/items";
     curl_setopt($curl_connection, CURLOPT_URL, $curl_url);
     curl_setopt($curl_connection, CURLOPT_POST, true);
     curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $renewItemParams);
     $checkedOutPageText = curl_exec($curl_connection);
     //Parse the checked out titles into individual rows
     $message = 'Unable to load renewal information for this entry.';
     $success = false;
     if (preg_match('/<h2>\\s*You cannot renew items because:\\s*<\\/h2><ul><li>(.*?)<\\/ul>/si', $checkedOutPageText, $matches)) {
         $success = false;
         $msg = ucfirst(strtolower(trim($matches[1])));
         $message = "Unable to renew this item: {$msg}.";
         if ($analytics) {
             $analytics->addEvent('ILS Integration', 'Renew Failed', $msg);
         }
     } elseif (preg_match('/Your record is in use/si', $checkedOutPageText, $matches)) {
         $success = false;
         $message = 'Unable to renew this item now, your account is in use by the system.  Please try again later.';
         if ($analytics) {
             $analytics->addEvent('ILS Integration', 'Renew Failed', 'Account in Use');
         }
     } elseif (preg_match('/<table border="0" class="patFunc">(.*?)<\\/table>/s', $checkedOutPageText, $matches)) {
         $checkedOutTitleTable = $matches[1];
         //$logger->log("Found checked out titles table", PEAR_LOG_DEBUG);
         if (preg_match_all('/<tr class="patFuncEntry">(.*?)<\\/tr>/s', $checkedOutTitleTable, $rowMatches, PREG_SET_ORDER)) {
             //$logger->log("Checked out titles table has " . count($rowMatches) . "rows", PEAR_LOG_DEBUG);
             //$logger->log(print_r($rowMatches, true), PEAR_LOG_DEBUG);
             //				for ($i = 0; $i < count($rowMatches); $i++) {
             foreach ($rowMatches as $i => $row) {
                 $rowData = $row[1];
                 if (preg_match("/{$itemId}/", $rowData)) {
                     //$logger->log("Found the row for this item", PEAR_LOG_DEBUG);
                     //Extract the renewal message
                     if (preg_match('/<td align="left" class="patFuncStatus">.*?<em><font color="red">(.*?)<\\/font><\\/em>.*?<\\/td>/s', $rowData, $statusMatches)) {
                         $success = false;
                         $msg = ucfirst(strtolower(trim($statusMatches[1])));
                         $title = $this->extract_title_from_row($rowData);
                         $message = "Unable to renew {$title}: {$msg}.";
                         // title needed for in renewSelectedItems to distinguish which item failed.
                     } elseif (preg_match('/<td align="left" class="patFuncStatus">.*?<em>(.*?)<\\/em>.*?<\\/td>/s', $rowData, $statusMatches)) {
                         $success = true;
                         $message = 'Your item was successfully renewed';
                     }
                     $logger->log("Renew success = {$success}, {$message}", PEAR_LOG_DEBUG);
                     break;
                     // found our item, get out of loop.
                 }
             }
         } else {
             $logger->log("Did not find any rows for the table {$checkedOutTitleTable}", PEAR_LOG_DEBUG);
         }
     } else {
         $success = true;
         $message = 'Your item was successfully renewed';
         if ($analytics) {
             $analytics->addEvent('ILS Integration', 'Renew Successful');
         }
     }
     curl_close($curl_connection);
     unlink($cookieJar);
     return array('itemId' => $itemId, 'result' => $success, 'message' => $message);
 }
 public function getMyHolds($patron = null, $page = 1, $recordsPerPage = -1, $sortOption = 'title')
 {
     global $timer;
     $patronDump = $this->driver->_getPatronDump($this->driver->_getBarcode());
     //Load the information from millennium using CURL
     $sResult = $this->driver->_fetchPatronInfoPage($patronDump, 'holds');
     $timer->logTime("Got holds page from Millennium");
     $holds = $this->parseHoldsPage($sResult);
     $timer->logTime("Parsed Holds page");
     require_once ROOT_DIR . '/RecordDrivers/MarcRecord.php';
     foreach ($holds as $section => $holdSections) {
         foreach ($holdSections as $key => $hold) {
             disableErrorHandler();
             $recordDriver = new MarcRecord($hold['recordId']);
             if ($recordDriver->isValid()) {
                 $hold['id'] = $recordDriver->getUniqueID();
                 $hold['shortId'] = $recordDriver->getShortId();
                 //Load title, author, and format information about the title
                 $hold['title'] = $recordDriver->getTitle();
                 $hold['sortTitle'] = $recordDriver->getSortableTitle();
                 $hold['author'] = $recordDriver->getAuthor();
                 $hold['format'] = $recordDriver->getFormat();
                 $hold['isbn'] = $recordDriver->getCleanISBN();
                 $hold['upc'] = $recordDriver->getCleanUPC();
                 $hold['format_category'] = $recordDriver->getFormatCategory();
                 //Load rating information
                 $hold['ratingData'] = $recordDriver->getRatingData();
                 $holds[$section][$key] = $hold;
             }
             enableErrorHandler();
         }
     }
     //Process sorting
     //echo ("<br/>\r\nSorting by $sortOption");
     foreach ($holds as $sectionName => $section) {
         $sortKeys = array();
         $i = 0;
         foreach ($section as $key => $hold) {
             $sortTitle = isset($hold['sortTitle']) ? $hold['sortTitle'] : (isset($hold['title']) ? $hold['title'] : "Unknown");
             if ($sectionName == 'available') {
                 $sortKeys[$key] = $sortTitle;
             } else {
                 if ($sortOption == 'title') {
                     $sortKeys[$key] = $sortTitle;
                 } elseif ($sortOption == 'author') {
                     $sortKeys[$key] = (isset($hold['author']) ? $hold['author'] : "Unknown") . '-' . $sortTitle;
                 } elseif ($sortOption == 'placed') {
                     $sortKeys[$key] = $hold['createTime'] . '-' . $sortTitle;
                 } elseif ($sortOption == 'format') {
                     $sortKeys[$key] = (isset($hold['format']) ? $hold['format'] : "Unknown") . '-' . $sortTitle;
                 } elseif ($sortOption == 'location') {
                     $sortKeys[$key] = (isset($hold['location']) ? $hold['location'] : "Unknown") . '-' . $sortTitle;
                 } elseif ($sortOption == 'holdQueueLength') {
                     $sortKeys[$key] = (isset($hold['holdQueueLength']) ? $hold['holdQueueLength'] : 0) . '-' . $sortTitle;
                 } elseif ($sortOption == 'position') {
                     $sortKeys[$key] = str_pad(isset($hold['position']) ? $hold['position'] : 1, 3, "0", STR_PAD_LEFT) . '-' . $sortTitle;
                 } elseif ($sortOption == 'status') {
                     $sortKeys[$key] = (isset($hold['status']) ? $hold['status'] : "Unknown") . '-' . (isset($hold['reactivateTime']) ? $hold['reactivateTime'] : "0") . '-' . $sortTitle;
                 } else {
                     $sortKeys[$key] = $sortTitle;
                 }
                 //echo ("<br/>\r\nSort Key for $key = {$sortKeys[$key]}");
             }
             $sortKeys[$key] = strtolower($sortKeys[$key] . '-' . $i++);
         }
         array_multisort($sortKeys, $section);
         $holds[$sectionName] = $section;
     }
     //Limit to a specific number of records
     if (isset($holds['unavailable'])) {
         $numUnavailableHolds = count($holds['unavailable']);
         if ($recordsPerPage != -1) {
             $startRecord = ($page - 1) * $recordsPerPage;
             $holds['unavailable'] = array_slice($holds['unavailable'], $startRecord, $recordsPerPage);
         }
     } else {
         $numUnavailableHolds = 0;
     }
     if (!isset($holds['available'])) {
         $holds['available'] = array();
     }
     if (!isset($holds['unavailable'])) {
         $holds['unavailable'] = array();
     }
     //Sort the hold sections so available holds are first.
     ksort($holds);
     $patronId = isset($patron) ? $patron['id'] : $this->driver->_getBarcode();
     $this->holds[$patronId] = $holds;
     $timer->logTime("Processed hold pagination and sorting");
     return array('holds' => $holds, 'numUnavailableHolds' => $numUnavailableHolds);
 }
 /**
  * Place Item Hold
  *
  * This is responsible for both placing item level holds.
  *
  * @param   string  $recordId   The id of the bib record
  * @param   string  $itemId     The id of the item to hold
  * @param   string  $patronId   The id of the patron
  * @param   string  $comment    Any comment regarding the hold or recall
  * @param   string  $type       Whether to place a hold or recall
  * @param   string  $type       The date when the hold should be cancelled if any
  * @return  mixed               True if successful, false if unsuccessful
  *                              If an error occurs, return a PEAR_Error
  * @access  public
  */
 public function placeItemHold($recordId, $itemId, $patronId, $comment, $type)
 {
     $patronDump = $this->driver->_getPatronDump($this->driver->_getBarcode());
     $bib1 = $recordId;
     if (substr($bib1, 0, 1) != '.') {
         $bib1 = '.' . $bib1;
     }
     $bib = substr(str_replace('.b', 'b', $bib1), 0, -1);
     if (strlen($bib) == 0) {
         return array('result' => false, 'message' => 'A valid record id was not provided. Please try again.');
     }
     //Get the title of the book.
     global $configArray;
     $class = $configArray['Index']['engine'];
     $url = $configArray['Index']['url'];
     $this->driver->db = new $class($url);
     if ($configArray['System']['debugSolr']) {
         $this->driver->db->debug = true;
     }
     // Retrieve Full Marc Record
     if (!($record = $this->driver->db->getRecord($bib1))) {
         $title = null;
     } else {
         if (isset($record['title_full'][0])) {
             $title = $record['title_full'][0];
         } else {
             $title = $record['title'];
         }
     }
     //Cancel a hold
     if ($type == 'cancel' || $type == 'recall' || $type == 'update') {
         $result = $this->updateHold($recordId, $patronId, $type, $title);
         $result['title'] = $title;
         $result['bid'] = $bib1;
         return $result;
     } else {
         //User is logged in before they get here, always use the info from patrondump
         $username = $patronDump['PATRN_NAME'];
         if (isset($_REQUEST['canceldate']) && !is_null($_REQUEST['canceldate']) && $_REQUEST['canceldate'] != '') {
             $date = $_REQUEST['canceldate'];
         } else {
             //Default to a date 6 months (half a year) in the future.
             $sixMonthsFromNow = time() + 182.5 * 24 * 60 * 60;
             $date = date('m/d/Y', $sixMonthsFromNow);
         }
         if (isset($_POST['campus'])) {
             $campus = trim($_POST['campus']);
         } else {
             global $user;
             $campus = $user->homeLocationId;
         }
         if (is_numeric($campus)) {
             $location = new Location();
             $location->locationId = $campus;
             if ($location->find(true)) {
                 $campus = $location->code;
             }
         }
         list($Month, $Day, $Year) = explode("/", $date);
         //------------BEGIN CURL-----------------------------------------------------------------
         $fullName = $patronDump['PATRN_NAME'];
         $nameParts = explode(', ', $fullName);
         $lastName = $nameParts[0];
         if (isset($nameParts[1])) {
             $secondName = $nameParts[1];
             $secondNameParts = explode(' ', $secondName);
             $firstName = $secondNameParts[0];
             if (isset($secondNameParts[1])) {
                 $middleName = $secondNameParts[1];
             }
         }
         list($first, $last) = explode(' ', $username);
         $header = array();
         $header[0] = "Accept: text/xml,application/xml,application/xhtml+xml,";
         $header[0] .= "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
         $header[] = "Cache-Control: max-age=0";
         $header[] = "Connection: keep-alive";
         $header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";
         $header[] = "Accept-Language: en-us,en;q=0.5";
         $id = $patronDump['RECORD_#'];
         $cookie = tempnam("/tmp", "CURLCOOKIE");
         $curl_connection = curl_init();
         curl_setopt($curl_connection, CURLOPT_CONNECTTIMEOUT, 30);
         curl_setopt($curl_connection, CURLOPT_HTTPHEADER, $header);
         curl_setopt($curl_connection, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
         curl_setopt($curl_connection, CURLOPT_RETURNTRANSFER, true);
         curl_setopt($curl_connection, CURLOPT_SSL_VERIFYPEER, false);
         curl_setopt($curl_connection, CURLOPT_FOLLOWLOCATION, true);
         curl_setopt($curl_connection, CURLOPT_UNRESTRICTED_AUTH, true);
         curl_setopt($curl_connection, CURLOPT_COOKIEJAR, $cookie);
         curl_setopt($curl_connection, CURLOPT_COOKIESESSION, true);
         curl_setopt($curl_connection, CURLOPT_FORBID_REUSE, false);
         curl_setopt($curl_connection, CURLOPT_HEADER, false);
         curl_setopt($curl_connection, CURLOPT_POST, true);
         if (isset($configArray['Catalog']['loginPriorToPlacingHolds']) && ($configArray['Catalog']['loginPriorToPlacingHolds'] = true)) {
             //User must be logged in as a separate step to placing holds
             $curl_url = $configArray['Catalog']['url'] . "/patroninfo";
             $post_data = $this->driver->_getLoginFormValues();
             $post_data['submit.x'] = "35";
             $post_data['submit.y'] = "21";
             $post_data['submit'] = "submit";
             curl_setopt($curl_connection, CURLOPT_REFERER, $curl_url);
             curl_setopt($curl_connection, CURLOPT_URL, $curl_url);
             $post_items = array();
             foreach ($post_data as $key => $value) {
                 $post_items[] = $key . '=' . $value;
             }
             $post_string = implode('&', $post_items);
             curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
             curl_exec($curl_connection);
             $post_data = array();
         } else {
             $post_data = $this->driver->_getLoginFormValues();
         }
         $curl_url = $configArray['Catalog']['url'] . "/search/." . $bib . "/." . $bib . "/1,1,1,B/request~" . $bib;
         //echo "$curl_url";
         curl_setopt($curl_connection, CURLOPT_URL, $curl_url);
         $post_data['needby_Month'] = $Month;
         $post_data['needby_Day'] = $Day;
         $post_data['needby_Year'] = $Year;
         $post_data['submit.x'] = "35";
         $post_data['submit.y'] = "21";
         $post_data['submit'] = "submit";
         $post_data['locx00'] = str_pad($campus, 5 - strlen($campus), '+');
         if (!is_null($itemId) && $itemId != -1) {
             $post_data['radio'] = $itemId;
         }
         $post_data['x'] = "48";
         $post_data['y'] = "15";
         $post_items = array();
         foreach ($post_data as $key => $value) {
             $post_items[] = $key . '=' . $value;
         }
         $post_string = implode('&', $post_items);
         curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
         $sresult = curl_exec($curl_connection);
         global $logger;
         $logger->log("Placing hold {$curl_url}?{$post_string}", PEAR_LOG_INFO);
         $sresult = preg_replace("/<!--([^(-->)]*)-->/", "", $sresult);
         curl_close($curl_connection);
         //Parse the response to get the status message
         $hold_result = $this->_getHoldResult($sresult);
         $hold_result['title'] = $title;
         $hold_result['bid'] = $bib1;
         global $analytics;
         if ($analytics) {
             if ($hold_result['result'] == true) {
                 $analytics->addEvent('ILS Integration', 'Successful Hold', $title);
             } else {
                 $analytics->addEvent('ILS Integration', 'Failed Hold', $hold_result['message'] . ' - ' . $title);
             }
         }
         return $hold_result;
     }
 }