/** * Constructor * * @access public */ public function __construct() { global $configArray; global $user; global $interface; //$interface->caching = 1; // Setup Search Engine Connection $this->db = ConnectionManager::connectToIndex(); // Connect to Database $this->catalog = ConnectionManager::connectToCatalog(); // Set up object for formatting dates and times: $this->dateFormat = new VuFindDate(); // Register Library Catalog Account if (isset($_POST['submit']) && !empty($_POST['submit'])) { if (isset($_POST['cat_username']) && isset($_POST['cat_password'])) { $username = $_POST['cat_username']; if (isset($_POST['login_target'])) { $username = $_POST['login_target'] . '.' . $username; } $result = UserAccount::processCatalogLogin($username, $_POST['cat_password']); if ($result) { $interface->assign('user', $user); } else { $interface->assign('loginError', 'Invalid Patron Login'); } } } // Retrieve the record from the index if (!($record = $this->db->getRecord($_REQUEST['id']))) { PEAR::raiseError(new PEAR_Error('Record Does Not Exist')); } $this->setRecord($_REQUEST['id'], $record); }
/** * Get a list of pickup locations for the given library * * @return void * @access public */ public function getPickUpLocations() { if (isset($_REQUEST['id']) && isset($_REQUEST['pickupLib'])) { // check if user is logged in $user = UserAccount::isLoggedIn(); if (!$user) { return $this->output(array('msg' => translate('You must be logged in first')), JSON::STATUS_NEED_AUTH); } $catalog = ConnectionManager::connectToCatalog(); if ($catalog && $catalog->status) { if ($patron = UserAccount::catalogLogin()) { if (!PEAR::isError($patron)) { $results = $catalog->getUBPickupLocations(array('id' => $_REQUEST['id'], 'patron' => $patron, 'pickupLibrary' => $_REQUEST['pickupLib'])); if (!PEAR::isError($results)) { foreach ($results as &$result) { $result['name'] = translate(array('prefix' => 'location_', 'text' => $result['name'])); } return $this->output(array('locations' => $results), JSON::STATUS_OK); } } } } } return $this->output(translate('An error has occurred'), JSON::STATUS_ERROR); }
/** * Attempt to authenticate the current user. * * @return object User object if successful, PEAR_Error otherwise. * @access public */ public function authenticate() { global $configArray; $username = $_POST['username']; $password = $_POST['password']; $loginTarget = isset($_POST['login_target']) ? $_POST['login_target'] : false; if ($loginTarget) { $username = "******"; } if ($username == '' || $password == '') { $user = new PEAR_Error('authentication_error_blank'); } else { // Connect to catalog: $catalog = ConnectionManager::connectToCatalog(); if ($catalog && $catalog->status) { $patron = $catalog->patronLogin($username, $password); if ($patron && !PEAR::isError($patron)) { // If the login command did not return an email address, try to fetch it from the profile information if (empty($patron['email'])) { $profile = $catalog->getMyProfile($patron); $patron['email'] = $profile['email']; } $confirm = isset($_POST['confirm']); if (!$confirm) { list($ILSUserExists) = $this->checkIfILSUserExists($patron); if (!$ILSUserExists) { // First login with library card // Check if account is connected to existing user(s) $accounts = $this->checkIfLibraryCardIsConnectedToOtherUser($patron); if (!empty($accounts)) { $res = array(); foreach ($accounts as $account) { $tmp = array('email' => $account->email); if ($account->authMethod !== null) { $tmp['authMethod'] = translate("confirm_create_account_{$account->authMethod}"); } $res[] = $tmp; } // Confirm if new user account should be created return new PEAR_Error('confirm_create_account', ILSAuthentication::ERROR_CONFIRM_CREATE_ACCOUNT, null, null, json_encode($res)); } } } $user = $this->_processILSUser($patron); } else { $user = PEAR::isError($patron) ? $patron : new PEAR_Error('authentication_error_invalid'); } } else { $user = new PEAR_Error('authentication_error_technical'); } } return $user; }
/** * Constructor * * @access public */ public function __construct() { global $configArray; $this->useReservesIndex = isset($configArray['Reserves']['search_enabled']) && $configArray['Reserves']['search_enabled']; // connect to the ILS if not using course reserves Solr index if (!$this->useReservesIndex) { $catalog = ConnectionManager::connectToCatalog(); if (!$catalog || !$catalog->status) { PEAR::raiseError(new PEAR_Error('Cannot Load Catalog Driver')); } $this->catalog = $catalog; } }
/** * Constructor * * @param bool $skipLogin Set to true to bypass the default login requirement. * * @access public */ public function __construct($skipLogin = false) { global $interface; global $configArray; global $user; if (!$skipLogin && !UserAccount::isLoggedIn()) { include_once 'Login.php'; Login::launch(); exit; } // Setup Search Engine Connection $this->db = ConnectionManager::connectToIndex(); // Connect to Database $this->catalog = ConnectionManager::connectToCatalog(); // Is Placing Holds allowed? $this->checkHolds = $this->catalog->checkFunction("Holds", null); // Is Cancelling Holds allowed? $this->cancelHolds = $this->catalog->checkFunction("cancelHolds", null); // Is Renewing Items allowed? $this->checkRenew = $this->catalog->checkFunction("Renewals", null); // Register Library Catalog Account if (isset($_POST['submit']) && !empty($_POST['submit']) && $this->catalog && isset($_POST['cat_username']) && isset($_POST['cat_password'])) { $username = $_POST['cat_username']; $password = $_POST['cat_password']; $loginTarget = isset($_POST['login_target']) ? $_POST['login_target'] : false; if ($loginTarget) { $username = "******"; } if (UserAccount::processCatalogLogin($username, $password)) { $interface->assign('user', $user); } else { $interface->assign('loginError', 'Invalid Patron Login'); } } // Assign Exporter Options $exportOptions = array(); if ($configArray['BulkExport']['enabled']) { $options = explode(':', $configArray['BulkExport']['options']); foreach ($options as $option) { if ($configArray['Export'][$option] == true) { $exportOptions[] = $option; } } $interface->assign('exportOptions', $exportOptions); } // Get Messages $this->infoMsg = isset($_GET['infoMsg']) ? $_GET['infoMsg'] : false; $this->errorMsg = isset($_GET['errorMsg']) ? $_GET['errorMsg'] : false; $this->showExport = isset($_GET['showExport']) ? $_GET['showExport'] : false; $this->followupUrl = false; }
/** * Constructor. * * @access public */ public function __construct() { global $interface; global $configArray; global $user; parent::__construct(); $this->user = UserAccount::isLoggedIn(); // Setup Search Engine Connection $this->db = ConnectionManager::connectToIndex(); // Connect to Database $this->catalog = ConnectionManager::connectToCatalog(); // Assign Exporter Options $exportOptions = array(); if ($configArray['BulkExport']['enabled']) { $options = explode(':', $configArray['BulkExport']['options']); foreach ($options as $option) { if ($configArray['Export'][$option] == true) { $exportOptions[] = $option; } } $this->exportOptions = $exportOptions; } // Get Messages $this->infoMsg = isset($_GET['infoMsg']) ? $_GET['infoMsg'] : false; $this->errorMsg = isset($_GET['errorMsg']) ? $_GET['errorMsg'] : false; $this->showExport = isset($_GET['showExport']) ? $_GET['showExport'] : false; $this->origin = isset($_REQUEST['origin']) ? $_REQUEST['origin'] : false; // Set FollowUp URL if (isset($_REQUEST['followup'])) { $this->followupUrl = $configArray['Site']['url'] . "/" . $_REQUEST['followupModule']; $this->followupUrl .= "/" . $_REQUEST['followupAction']; } else { if (isset($_REQUEST['listID']) && !empty($_REQUEST['listID'])) { $this->followupUrl = $configArray['Site']['url'] . "/MyResearch/MyList/" . urlencode($_REQUEST['listID']); } else { $this->followupUrl = $configArray['Site']['url'] . "/Cart/Home"; } } }
/** * Check Request is Valid * * @return void * @access public */ public function checkRequestIsValid() { if (isset($_REQUEST['id']) && isset($_REQUEST['data'])) { // check if user is logged in $user = UserAccount::isLoggedIn(); if (!$user) { return $this->output(array('status' => false, 'msg' => translate('You must be logged in first')), JSON::STATUS_NEED_AUTH); } $catalog = ConnectionManager::connectToCatalog(); if ($catalog && $catalog->status) { if ($patron = UserAccount::catalogLogin()) { if (!PEAR::isError($patron)) { $results = $catalog->checkCallSlipRequestIsValid($_REQUEST['id'], $_REQUEST['data'], $patron); if (!PEAR::isError($results)) { $msg = $results ? translate('call_slip_place_text') : translate('call_slip_error_blocked'); return $this->output(array('status' => $results, 'msg' => $msg), JSON::STATUS_OK); } } } } } return $this->output(translate('An error has occurred'), JSON::STATUS_ERROR); }
/** * Constructor * * @param object $catalog A catalog connection * * @access public */ public function __construct($catalog = false) { global $configArray; $this->hideHoldings = isset($configArray['Record']['hide_holdings']) ? $configArray['Record']['hide_holdings'] : array(); $this->catalog = $catalog == true ? $catalog : ConnectionManager::connectToCatalog(); }
/** * Send due date reminders * * @return void */ public function send() { global $configArray; global $interface; global $translator; $iso8601 = 'Y-m-d\\TH:i:s\\Z'; ini_set('display_errors', true); $configArray = $mainConfig = readConfig(); $datasourceConfig = getExtraConfigArray('datasources'); $siteLocal = $configArray['Site']['local']; // Set up time zone. N.B. Don't use msg() or other functions requiring date before this. date_default_timezone_set($configArray['Site']['timezone']); $this->msg('Sending due date reminders'); // Setup Local Database Connection ConnectionManager::connectToDatabase(); // And index $db = ConnectionManager::connectToIndex(); // Initialize Mailer $mailer = new VuFindMailer(); // Find all scheduled alerts $sql = 'SELECT * FROM "user" WHERE "due_date_reminder" > 0 ORDER BY id'; $user = new User(); $user->query($sql); $this->msg('Processing ' . $user->N . ' users'); $interface = false; $institution = false; $todayTime = new DateTime(); $catalog = ConnectionManager::connectToCatalog(); while ($user->fetch()) { if (!$user->email || trim($user->email) == '') { $this->msg('User ' . $user->username . ' does not have an email address, bypassing due date reminders'); continue; } // Initialize settings and interface $userInstitution = reset(explode(':', $user->username, 2)); if (!$institution || $institution != $userInstitution) { $institution = $userInstitution; if (!isset($datasourceConfig[$institution])) { foreach ($datasourceConfig as $code => $values) { if (isset($values['institution']) && strcasecmp($values['institution'], $institution) == 0) { $institution = $code; break; } } } if (!($configArray = $this->readInstitutionConfig($institution))) { continue; } // Start Interface $interface = new UInterface($siteLocal); $validLanguages = array_keys($configArray['Languages']); $dateFormat = new VuFindDate(); } $language = $user->language; if (!in_array($user->language, $validLanguages)) { $language = $configArray['Site']['language']; } $translator = new I18N_Translator(array($configArray['Site']['local'] . '/lang', $configArray['Site']['local'] . '/lang_local'), $language, $configArray['System']['debug']); $interface->setLanguage($language); // Go through accounts and check loans $account = new User_account(); $account->user_id = $user->id; if (!$account->find(false)) { continue; } $remindLoans = array(); while ($account->fetch()) { $patron = $catalog->patronLogin($account->cat_username, $account->cat_password); if ($patron === null || PEAR::isError($patron)) { $this->msg('Catalog login failed for user ' . $user->id . ', account ' . $account->id . ' (' . $account->cat_username . '): ' . ($patron ? $patron->getMessage() : 'patron not found')); continue; } $loans = $catalog->getMyTransactions($patron); if (PEAR::isError($loans)) { $this->msg('Could not fetch loans for user ' . $user->id . ', account ' . $account->id . ' (' . $account->cat_username . ')'); continue; } foreach ($loans as $loan) { $dueDate = new DateTime($loan['duedate']); if ($todayTime >= $dueDate || $dueDate->diff($todayTime)->days <= $user->due_date_reminder) { // Check that a reminder hasn't been sent already $reminder = new Due_date_reminder(); $reminder->user_id = $user->id; $reminder->loan_id = $loan['item_id']; $reminder->due_date = $dueDate->format($iso8601); if ($reminder->find(false)) { // Reminder already sent continue; } // Store also title for display in email $title = isset($loan['title']) ? $loan['title'] : translate('Title not available'); if (isset($loan['id'])) { $record = $db->getRecord($loan['id']); if ($record && isset($record['title'])) { $title = $record['title']; } } $remindLoans[] = array('loanId' => $loan['item_id'], 'dueDate' => $loan['duedate'], 'dueDateFormatted' => $dueDate->format(isset($configArray['Site']['displayDateFormat']) ? $configArray['Site']['displayDateFormat'] : "m-d-Y"), 'title' => $title); } } } if ($remindLoans) { $this->msg(count($remindLoans) . ' new loans to remind for user ' . $user->id); $interface->assign('date', $dateFormat->convertToDisplayDate("U", floor(time()))); $interface->assign('loans', $remindLoans); $key = $this->getSecret($user, $user->id); $params = array('id' => $user->id, 'type' => 'reminder', 'key' => $key); $unsubscribeUrl = $configArray['Site']['url'] . '/MyResearch/Unsubscribe?' . http_build_query($params); $interface->assign(compact('unsubscribeUrl')); // Load template $message = $interface->fetch('MyResearch/due-date-email.tpl'); if (strstr($message, 'Warning: Smarty error:')) { $this->msg("Message template processing failed: {$message}"); continue; } $result = $mailer->send($user->email, $configArray['Site']['email'], translate('due_date_email_subject'), $message); if (PEAR::isError($result)) { $this->msg("Failed to send message to {$user->email}: " . $result->getMessage()); continue; } // Mark reminders sent foreach ($remindLoans as $loan) { $reminder = new Due_date_reminder(); $reminder->user_id = $user->id; $reminder->loan_id = $loan['loanId']; $reminder->delete(); $dueDate = new DateTime($loan['dueDate']); $reminder->due_date = $dueDate->format($iso8601); $reminder->notification_date = gmdate($iso8601, time()); $reminder->insert(); } } else { $this->msg('No loans to remind for user ' . $user->id); } } $this->reportErrors(); $this->msg('Due date reminders execution completed'); }
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link http://vufind.org/wiki Wiki */ ini_set('memory_limit', '50M'); ini_set('max_execution_time', '3600'); /** * Set up util environment */ require_once 'util.inc.php'; require_once 'sys/ConnectionManager.php'; // Read Config file $configArray = readConfig(); // Setup Solr Connection $solr = ConnectionManager::connectToIndex('SolrReserves'); // Connect to ILS $catalog = ConnectionManager::connectToCatalog(); // Records to index $index = array(); // Get instructors $instructors = $catalog->getInstructors(); // Get Courses $courses = $catalog->getCourses(); // Get Departments $departments = $catalog->getDepartments(); // Get all reserve records $reserves = $catalog->findReserves('', '', ''); if (!empty($instructors) && !empty($courses) && !empty($departments) && !empty($reserves)) { // Delete existing records $solr->deleteAll(); // Build the index $solr->buildIndex($instructors, $courses, $departments, $reserves);
/** * Get Item Statuses * * This is responsible for printing the holdings information for a * collection of records in JSON format. * * @return void * @access public * @author Chris Delis <*****@*****.**> * @author Tuan Nguyen <*****@*****.**> */ public function getItemStatuses() { global $interface; global $configArray; $catalog = ConnectionManager::connectToCatalog(); if (!$catalog || !$catalog->status) { return $this->output(translate('An error has occurred'), JSON::STATUS_ERROR); } $results = $catalog->getStatuses($_GET['id']); if (PEAR::isError($results)) { return $this->output($results->getMessage(), JSON::STATUS_ERROR); } else { if (!is_array($results)) { // If getStatuses returned garbage, let's turn it into an empty array // to avoid triggering a notice in the foreach loop below. $results = array(); } } // In order to detect IDs missing from the status response, create an // array with a key for every requested ID. We will clear keys as we // encounter IDs in the response -- anything left will be problems that // need special handling. $missingIds = array_flip($_GET['id']); // Load messages for response: $messages = array('available' => $interface->fetch('AJAX/status-available.tpl'), 'unavailable' => $interface->fetch('AJAX/status-unavailable.tpl'), 'unknown' => $interface->fetch('AJAX/status-unknown.tpl')); // Load callnumber and location settings: $callnumberSetting = isset($configArray['Item_Status']['multiple_call_nos']) ? $configArray['Item_Status']['multiple_call_nos'] : 'msg'; $locationSetting = isset($configArray['Item_Status']['multiple_locations']) ? $configArray['Item_Status']['multiple_locations'] : 'msg'; $showFullStatus = isset($configArray['Item_Status']['show_full_status']) ? $configArray['Item_Status']['show_full_status'] : false; // Loop through all the status information that came back $statuses = array(); $patron = null; foreach ($results as $record) { // Skip errors and empty records: if (!PEAR::isError($record) && count($record)) { // Filter out suppressed locations, and skip record if none remain: $record = $this->_filterSuppressedLocations($record); if (empty($record)) { continue; } // Special case for Axiell holdings if (isset($record[0]['holdings'])) { if ($patron === null) { $patron = UserAccount::catalogLogin(); } $current = array('id' => $record[0]['id'], 'full_status' => $this->getAxiellItemStatusFull($record, $catalog, $patron)); } else { if ($locationSetting == "group") { $current = $this->_getItemStatusGroup($record, $messages, $callnumberSetting); } else { $current = $this->_getItemStatus($record, $messages, $locationSetting, $callnumberSetting); } // If a full status display has been requested, append the HTML: if ($showFullStatus) { $current['full_status'] = $this->_getItemStatusFull($record); } } $statuses[] = $current; // The current ID is not missing -- remove it from the missing list. unset($missingIds[$current['id']]); } } // If any IDs were missing, send back appropriate dummy data, including a // "missing data" flag which can be used to completely suppress status info: foreach ($missingIds as $missingId => $junk) { $statuses[] = array('id' => $missingId, 'availability' => 'false', 'availability_message' => $messages['unavailable'], 'location' => translate('Unknown'), 'locationList' => false, 'reserve' => 'false', 'reserve_message' => translate('Not On Reserve'), 'callnumber' => '', 'missing_data' => true); } // Done return $this->output($statuses, JSON::STATUS_OK); }
/** * Process incoming parameters and display the page. * * @return void * @access public */ public function launch() { global $configArray; global $interface; $catalog = ConnectionManager::connectToCatalog(); if (!$catalog || !$catalog->status) { PEAR::raiseError(new PEAR_Error('Cannot Load Catalog Driver')); } // Read in search-specific configurations: $searchSettings = getExtraConfigArray('searches'); if (isset($_GET['range'])) { // Initialise from the current search globals $searchObject = SearchObjectFactory::initSearchObject(); $searchObject->init(); // Are there "new item" filter queries specified in the config file? // If so, we should apply them as hidden filters so they do not show // up in the user-selected facet list. if (isset($searchSettings['NewItem']['filter'])) { $filter = is_array($searchSettings['NewItem']['filter']) ? $searchSettings['NewItem']['filter'] : array($searchSettings['NewItem']['filter']); foreach ($filter as $current) { $searchObject->addHiddenFilter($current); } } // Must have atleast Action and Module set to continue $interface->setPageTitle('New Item Search Results'); $interface->setTemplate('newitem-list.tpl'); //Get view & load template $currentView = $searchObject->getView(); $interface->assign('subpage', 'Search/list-' . $currentView . '.tpl'); $interface->assign('viewList', $searchObject->getViewList()); $interface->assign('sortList', $searchObject->getSortList()); $interface->assign('limitList', $searchObject->getLimitList()); $interface->assign('rssLink', $searchObject->getRSSUrl()); $interface->assign('range', $_GET['range']); // This code was originally designed to page through the results // retrieved from the catalog in parallel with paging through the // Solr results. The logical flaw in this approach is that if // we only retrieve one page of results from the catalog, we never // know the full extent of available results there! // // The code has now been changed to always pull in enough catalog // results to get a fixed number of pages worth of Solr results. Note // that if the Solr index is out of sync with the ILS, we may see fewer // results than expected. $tmp = $searchObject->getResultSummary(); $limit = $tmp['perPage']; if (isset($searchSettings['NewItem']['result_pages'])) { $resultPages = intval($searchSettings['NewItem']['result_pages']); if ($resultPages < 1) { $resultPages = 10; } } else { $resultPages = 10; } if (isset($configArray['Site']['indexBasedNewItems']) && $configArray['Site']['indexBasedNewItems']) { // Build RSS Feed for Results (if requested) if ($searchObject->getView() == 'rss') { // Throw the XML to screen echo $searchObject->buildRSS(); // And we're done exit; } // Process Search $result = $searchObject->processSearch(false, true); if (PEAR::isError($result)) { PEAR::raiseError($result->getMessage()); } // Store recommendations (facets, etc.) $interface->assign('topRecommendations', $searchObject->getRecommendationsTemplates('top')); $interface->assign('sideRecommendations', $searchObject->getRecommendationsTemplates('side')); } else { $newItems = $catalog->getNewItems(1, $limit * $resultPages, $_GET['range'], isset($_GET['department']) ? $_GET['department'] : null); // Special case -- if no new items were found, don't bother hitting // the index engine: if ($newItems['count'] > 0) { // Query Index for BIB Data $bibIDs = array(); for ($i = 0; $i < count($newItems['results']); $i++) { $bibIDs[] = $newItems['results'][$i]['id']; } if (!$searchObject->setQueryIDs($bibIDs)) { $interface->assign('infoMsg', 'too_many_new_items'); } // Build RSS Feed for Results (if requested) if ($searchObject->getView() == 'rss') { // Throw the XML to screen echo $searchObject->buildRSS(); // And we're done exit; } // Process Search $result = $searchObject->processSearch(false, true); if (PEAR::isError($result)) { PEAR::raiseError($result->getMessage()); } // Store recommendations (facets, etc.) $interface->assign('topRecommendations', $searchObject->getRecommendationsTemplates('top')); $interface->assign('sideRecommendations', $searchObject->getRecommendationsTemplates('side')); } else { if ($searchObject->getView() == 'rss') { // Special case -- empty RSS feed: // Throw the XML to screen echo $searchObject->buildRSS(array('response' => array('numFound' => 0), 'responseHeader' => array('params' => array('rows' => 0)))); // And we're done exit; } } } // Send the new items to the template $interface->assign('recordSet', $searchObject->getResultRecordHTML()); // Setup Record Count Display $summary = $searchObject->getResultSummary(); $interface->assign('recordCount', $summary['resultTotal']); $interface->assign('recordStart', $summary['startRecord']); $interface->assign('recordEnd', $summary['endRecord']); // Setup Paging $link = $searchObject->renderLinkPageTemplate(); $total = isset($result['response']['numFound']) ? $result['response']['numFound'] : 0; $options = array('totalItems' => $total, 'perPage' => $limit, 'fileName' => $link); $pager = new VuFindPager($options); $interface->assign('pageLinks', $pager->getLinks()); // Save the URL of this search to the session so we can return to it // easily: $_SESSION['lastSearchURL'] = $searchObject->renderSearchUrl(); // Use 'New Items' as the display query e.g. in the breadcrumbs $_SESSION['lastSearchDisplayQuery'] = translate('New Items'); } else { $interface->setPageTitle('New Item Search'); $interface->setTemplate('newitem.tpl'); if (!isset($configArray['Site']['indexBasedNewItems']) || !$configArray['Site']['indexBasedNewItems']) { $list = $catalog->getFunds(); $interface->assign('fundList', $list); } // Find out if there are user configured range options; if not, // default to the standard 1/5/30 days: $ranges = array(); if (isset($searchSettings['NewItem']['ranges'])) { $tmp = explode(',', $searchSettings['NewItem']['ranges']); foreach ($tmp as $range) { $range = intval($range); if ($range > 0) { $ranges[] = $range; } } } if (empty($ranges)) { $ranges = array(1, 5, 30); } $interface->assign('ranges', $ranges); } $interface->display('layout.tpl'); }
/** * Constructor * * @param string $local Local directory for cache and compile * * @access public */ public function UInterface($local = '') { global $configArray; if (!$local) { $local = $configArray['Site']['local']; } $this->_vufindTheme = $configArray['Site']['theme']; // Use mobile theme for mobile devices (if enabled in config.ini) if (isset($configArray['Site']['mobile_theme'])) { // If the user is overriding the UI setting, store that: if (isset($_GET['ui'])) { $_COOKIE['ui'] = $_GET['ui']; setcookie('ui', $_GET['ui'], null, '/'); } else { if (!isset($_COOKIE['ui'])) { // If we don't already have a UI setting, detect if we're on a // mobile device and store the result in a cookie so we don't waste // time doing the detection routine on every page: $_COOKIE['ui'] = mobile_device_detect() ? 'mobile' : 'standard'; setcookie('ui', $_COOKIE['ui'], null, '/'); } } // If we're mobile, override the standard theme with the mobile one: if ($_COOKIE['ui'] == 'mobile') { $this->_vufindTheme = $configArray['Site']['mobile_theme']; } } // Check to see if multiple themes were requested; if so, build an array, // otherwise, store a single string. $themeArray = explode(',', $this->_vufindTheme); if (count($themeArray) > 1) { $this->template_dir = array(); foreach ($themeArray as $currentTheme) { $currentTheme = trim($currentTheme); $this->template_dir[] = "{$local}/interface/themes/{$currentTheme}"; } } else { $this->template_dir = "{$local}/interface/themes/{$this->_vufindTheme}"; } // Create an MD5 hash of the theme name -- this will ensure that it's a // writeable directory name (since some config.ini settings may include // problem characters like commas or whitespace). $md5 = md5($this->_vufindTheme); $this->compile_dir = "{$local}/interface/compile/{$md5}"; if (!is_dir($this->compile_dir)) { mkdir($this->compile_dir); } $this->cache_dir = "{$local}/interface/cache/{$md5}"; if (!is_dir($this->cache_dir)) { mkdir($this->cache_dir); } $this->plugins_dir = array('plugins', "{$local}/interface/plugins"); $this->caching = false; $this->debug = true; $this->compile_check = true; unset($local); $this->register_function('translate', 'translate'); $this->register_function('char', 'char'); $this->assign('site', $configArray['Site']); $this->assign('path', $configArray['Site']['path']); $this->assign('url', $configArray['Site']['url']); $this->assign('fullPath', isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : false); $this->assign('supportEmail', $configArray['Site']['email']); $searchObject = SearchObjectFactory::initSearchObject(); $this->assign('basicSearchTypes', is_object($searchObject) ? $searchObject->getBasicTypes() : array()); $this->assign('autocomplete', is_object($searchObject) ? $searchObject->getAutocompleteStatus() : false); $this->assign('retainFiltersByDefault', $searchObject->getRetainFilterByDefaultSetting()); if (isset($configArray['Site']['showBookBag'])) { $this->assign('bookBag', $configArray['Site']['showBookBag'] ? Cart_Model::getInstance() : false); } if (isset($configArray['OpenURL']) && isset($configArray['OpenURL']['url'])) { // Trim off any parameters (for legacy compatibility -- default config // used to include extraneous parameters): list($base) = explode('?', $configArray['OpenURL']['url']); } else { $base = false; } $this->assign('openUrlBase', empty($base) ? false : $base); // Other OpenURL settings: $this->assign('openUrlWindow', empty($configArray['OpenURL']['window_settings']) ? false : $configArray['OpenURL']['window_settings']); $this->assign('openUrlGraphic', empty($configArray['OpenURL']['graphic']) ? false : $configArray['OpenURL']['graphic']); $this->assign('openUrlGraphicWidth', empty($configArray['OpenURL']['graphic_width']) ? false : $configArray['OpenURL']['graphic_width']); $this->assign('openUrlGraphicHeight', empty($configArray['OpenURL']['graphic_height']) ? false : $configArray['OpenURL']['graphic_height']); if (isset($configArray['OpenURL']['embed']) && !empty($configArray['OpenURL']['embed'])) { include_once 'sys/Counter.php'; $this->assign('openUrlEmbed', true); $this->assign('openUrlCounter', new Counter()); } $this->assign('currentTab', 'Search'); $this->assign('authMethod', $configArray['Authentication']['method']); if (isset($configArray['Authentication']['libraryCard']) && !$configArray['Authentication']['libraryCard']) { $this->assign('libraryCard', false); } else { $this->assign('libraryCard', true); } $this->assign('sidebarOnLeft', !isset($configArray['Site']['sidebarOnLeft']) ? false : $configArray['Site']['sidebarOnLeft']); $piwikUrl = isset($configArray['Piwik']['url']) ? $configArray['Piwik']['url'] : false; if ($piwikUrl && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') { $piwikUrl = preg_replace('/^http:/', 'https:', $piwikUrl); } $this->assign('piwikUrl', $piwikUrl); $this->assign('piwikSiteId', !isset($configArray['Piwik']['site_id']) ? false : $configArray['Piwik']['site_id']); // Create prefilter list $prefilters = getExtraConfigArray('prefilters'); if (isset($prefilters['Prefilters'])) { $filters = array(); foreach ($prefilters['Prefilters'] as $key => $filter) { $filters[$key] = $filter; } $this->assign('prefilterList', $filters); } if (isset($_REQUEST['prefiltered'])) { $this->assign('activePrefilter', $_REQUEST['prefiltered']); } $metalib = getExtraConfigArray('MetaLib'); if (!empty($metalib)) { $this->assign('metalibEnabled', isset($metalib['General']['enabled']) ? $metalib['General']['enabled'] : true); } $pci = getExtraConfigArray('PCI'); if (!empty($pci)) { $this->assign('pciEnabled', isset($pci['General']['enabled']) ? $pci['General']['enabled'] : true); } $rssFeeds = getExtraConfigArray('rss'); if (isset($rssFeeds)) { $this->assign('rssFeeds', $rssFeeds); } $catalog = ConnectionManager::connectToCatalog(); $this->assign("offlineMode", $catalog->getOfflineMode()); $hideLogin = isset($configArray['Authentication']['hideLogin']) ? $configArray['Authentication']['hideLogin'] : false; $this->assign("hideLogin", $hideLogin ? true : $catalog->loginIsHidden()); if (isset($configArray['Site']['development']) && $configArray['Site']['development']) { $this->assign('developmentSite', true); } if (isset($configArray['Site']['dualResultsEnabled']) && $configArray['Site']['dualResultsEnabled']) { $this->assign('dualResultsEnabled', true); } // Resolve enabled context-help ids $contextHelp = array(); if (isset($configArray['ContextHelp'])) { foreach ($configArray['ContextHelp'] as $key => $val) { if ((bool) $val) { $contextHelp[] = $key; } } } $this->assign('contextHelp', $contextHelp); // Set Advanced Search start year and scale // The default values: $advSearchYearScale = array(0, 900, 1800, 1910); $yearScale = !isset($configArray['Site']['advSearchYearScale']) ? false : $configArray['Site']['advSearchYearScale']; if (isset($yearScale)) { $scaleArray = explode(',', $yearScale); $i = count($scaleArray); // Do we have more values or just the starting year if ($i > 1) { $j = 0; if ($i <= 4) { while ($j < $i) { $advSearchYearScale[$j] = (int) $scaleArray[$j]; $j++; } } else { while ($j < 4) { $advSearchYearScale[$j] = (int) $scaleArray[$j]; $j++; } } } else { // Only the starting year is set $advSearchYearScale[0] = (int) $yearScale; } } $this->assign('advSearchYearScale', $advSearchYearScale); }
/** * Change pick up location of a hold * * @return void * @access public */ public function changePickUpLocation() { if (isset($_REQUEST['reservationId'])) { // check if user is logged in $user = UserAccount::isLoggedIn(); if (!$user) { return $this->output(array('msg' => translate('You must be logged in first')), JSON::STATUS_NEED_AUTH); } $catalog = ConnectionManager::connectToCatalog(); if ($catalog && $catalog->status) { if ($patron = UserAccount::catalogLogin()) { if (!PEAR::isError($patron)) { $result = $catalog->changePickupLocation($patron, array('pickup' => $_REQUEST['pickup'], 'reservationId' => $_REQUEST['reservationId'], 'created' => $_REQUEST['created'], 'expires' => $_REQUEST['expires'])); if (!$result['success']) { return $this->output(array($result['sysMessage']), JSON::STATUS_ERROR); } return $this->output(array($result), JSON::STATUS_OK); } else { return $this->output($patron->getMessage(), JSON::STATUS_ERROR); } } } } return $this->output(translate('An error has occurred'), JSON::STATUS_ERROR); }
/** * Validate and save account information after editing * * @return boolean Success */ protected function saveAccount() { global $interface; global $user; $username = $_POST['username']; $password = $_POST['password']; $loginTarget = isset($_POST['login_target']) ? $_POST['login_target'] : false; if ($loginTarget) { $username = "******"; } $catalog = ConnectionManager::connectToCatalog(); $result = $catalog->patronLogin($username, $password); if (!$result || PEAR::isError($result)) { $interface->assign('errorMsg', $result ? $result->getMessage() : 'authentication_error_failed'); $this->editAccount(isset($_REQUEST['id']) ? $_REQUEST['id'] : null); return false; } $exists = false; $account = new User_account(); $account->user_id = $user->id; if (isset($_REQUEST['id']) && $_REQUEST['id']) { $account->id = $_REQUEST['id']; $exists = $account->find(true); } // Check that the user name is not in use in another account if (!$exists || $account->cat_username != $username) { $otherAccount = new User_account(); $otherAccount->user_id = $user->id; $otherAccount->cat_username = $username; if ($otherAccount->find()) { $interface->assign('errorMsg', 'Username already in use in another library card'); $this->editAccount(isset($_REQUEST['id']) ? $_REQUEST['id'] : null); return false; } } if (!$exists) { $account->created = date('Y-m-d h:i:s'); } else { if ($user->cat_username == $account->cat_username) { // Active account modified, update UserAccount::activateCatalogAccount($username, $password, $account->home_library); } } $account->account_name = isset($_REQUEST['account_name']) ? $_REQUEST['account_name'] : '-'; $account->description = isset($_REQUEST['description']) ? $_REQUEST['description'] : ''; $account->cat_username = $username; $account->cat_password = $password; if ($exists) { $account->update(); } else { $account->insert(); // If this is the first one, activate it if (count($user->getCatalogAccounts()) == 1) { UserAccount::activateCatalogAccount($username, $password, $account->home_library); } } return true; }
/** * Send the SMS message by email. * * @return mixed Boolean true on success, PEAR_Error on failure. * @access public */ public function sendSMS() { global $configArray; global $interface; // Get Holdings $catalog = ConnectionManager::connectToCatalog(); if (!$catalog || !$catalog->status) { return new PEAR_Error('Cannot connect to ILS'); } $holdings = $catalog->getStatus($_GET['id']); if (PEAR::isError($holdings)) { return $holdings; } $interface->assign('callnumber', $holdings[0]['callnumber']); $interface->assign('location', $holdings[0]['location']); $interface->assign('title', $this->recordDriver->getBreadcrumb()); $interface->assign('recordID', $_GET['id']); $message = $interface->fetch('Emails/catalog-sms.tpl'); return $this->_sms->text($_REQUEST['provider'], $_REQUEST['to'], $configArray['Site']['email'], $message); }
/** * Process transactions. Try to register unregistered transactions * and inform on expired transactions. * * @return void * @access public */ public function process() { global $configArray; global $interface; ini_set('display_errors', true); $configArray = $mainConfig = readConfig(); $datasourceConfig = getExtraConfigArray('datasources'); // Set up time zone. N.B. Don't use msg() or other // functions requiring date before this. date_default_timezone_set($configArray['Site']['timezone']); $this->msg("OnlinePayment monitor started"); // Setup Local Database Connection ConnectionManager::connectToDatabase(); // Initialize Mailer $mailer = new VuFindMailer(); $now = new DateTime(); $expiredCnt = 0; $failedCnt = 0; $registeredCnt = 0; $remindCnt = 0; $user = false; $report = array(); // Attempt to re-register paid transactions whose registration has failed. $tr = new Transaction(); foreach ($tr->getFailedTransactions() as $t) { $this->msg(" Registering transaction id {$t->id} / {$t->transaction_id}"); // check if the transaction has not been registered for too long $paid_time = new DateTime($t->paid); $diff = $now->diff($paid_time); $diffHours = $diff->days * 24 + $diff->h; if ($diffHours > $this->expireHours) { if (!isset($report[$t->driver])) { $report[$t->driver] = 0; } $report[$t->driver]++; $expiredCnt++; if (!$t->setTransactionReported($t->transaction_id)) { $this->err(' Failed to update transaction ' . $t->transaction_id . 'as reported'); } $transaction = clone $t; $transaction->complete = Transaction::STATUS_REGISTRATION_EXPIRED; if ($transaction->update($t) === false) { $this->err(' Failed to update transaction ' . $t->transaction_id . 'as expired.'); } else { $this->msg(' Transaction ' . $t->transaction_id . ' expired.'); } } else { if ($user === false || $t->user_id != $user->id) { $user = User::staticGet($t->user_id); } $catalog = ConnectionManager::connectToCatalog(); if ($catalog && $catalog->status) { $account = new User_account(); $account->user_id = $t->user_id; $account->cat_username = $t->cat_username; if ($account->find(true)) { if (!($patron = $catalog->patronLogin($t->cat_username, $account->cat_password))) { $this->err(' Could not perform patron login for transaction ' . $t->transaction_id); $failedCnt++; continue; } } $res = $catalog->markFeesAsPaid($patron, $t->amount); if ($res === true) { if (!$t->setTransactionRegistered($t->transaction_id)) { $this->err(' Failed to update transaction ' . $t->transaction_id . 'as registered'); } $registeredCnt++; } else { $t->setTransactionRegistrationFailed($t->transaction_id, $res); $failedCnt++; $this->msg(' Registration of transaction ' . $t->transaction_id . ' failed'); $this->msg(" {$res}"); } } else { $this->err("Failed to connect to catalog ({$patronId})"); continue; } } } // Report paid and unregistered transactions whose registration // can not be re-tried: $tr = new Transaction(); foreach ($tr->getUnresolvedTransactions($this->reportIntervalHours) as $t) { $this->msg(" Transaction id {$t->transaction_id} still unresolved."); if (!$t->setTransactionReported($t->transaction_id)) { $this->err(' Failed to update transaction ' . $t->transaction_id . ' as reported'); } if (!isset($report[$t->driver])) { $report[$t->driver] = 0; } $report[$t->driver]++; $remindCnt++; } if ($registeredCnt) { $this->msg(" Total registered: {$registeredCnt}"); } if ($expiredCnt) { $this->msg(" Total expired: {$expiredCnt}"); } if ($failedCnt) { $this->msg(" Total failed: {$failedCnt}"); } if ($remindCnt) { $this->msg(" Total to be reminded: {$remindCnt}"); } $configArray = readConfig(); $siteLocal = $configArray['Site']['local']; $interface = new UInterface($siteLocal); // Send report of transactions that need to be resolved manually: foreach ($report as $driver => $cnt) { if ($cnt) { $settings = getExtraConfigArray("VoyagerRestful_{$driver}"); if (!$settings || !isset($settings['OnlinePayment']['errorEmail'])) { $this->err(" Error email for expired transactions not defined for driver {$driver} ({$cnt} expired transactions)"); continue; } $email = $settings['OnlinePayment']['errorEmail']; $this->msg(" [{$driver}] Inform {$cnt} expired transactions for driver {$driver} to {$email}"); $mailer = new VuFindMailer(); $subject = "Finna: ilmoitus tietokannan {$driver} epäonnistuneista verkkomaksuista"; $interface->assign('driver', $driver); $interface->assign('cnt', $cnt); $msg = $interface->fetch('Emails/online-payment-error.tpl'); if (!($result = $mailer->send($email, $this->fromEmail, $subject, $msg))) { $this->err(" Failed to send error email to customer: {$email}"); } } } $this->msg("OnlinePayment monitor completed"); $this->reportErrors(); }
/** * Delete suppressed records. * * @return void * @access public */ public function deleteSuppressed() { global $interface; ini_set('memory_limit', '50M'); ini_set('max_execution_time', '3600'); // Make ILS Connection $catalog = ConnectionManager::connectToCatalog(); /* // Display Progress Page $interface->display('loading.tpl'); ob_flush(); flush(); */ // Get Suppressed Records and Delete from index $deletes = array(); if ($catalog && $catalog->status) { $result = $catalog->getSuppressedRecords(); if (!PEAR::isError($result)) { $status = $this->_db->deleteRecords($result); foreach ($result as $current) { $deletes[] = array('id' => $current); } $this->_db->commit(); $this->_db->optimize(); } } else { PEAR::raiseError(new PEAR_Error('Cannot connect to ILS')); } $interface->assign('resultList', $deletes); $interface->setTemplate('grid.tpl'); $interface->setPageTitle('Delete Suppressed'); $interface->display('layout-admin.tpl'); }
/** * Attempt to log in the user to the ILS, and save credentials if it works. * * @param string $username Catalog username * @param string $password Catalog password * * @return bool True on successful login, false on error. */ public static function processCatalogLogin($username, $password) { global $user; $catalog = ConnectionManager::connectToCatalog(); $result = $catalog->patronLogin($username, $password); if ($result && !PEAR::isError($result)) { $user->cat_username = $username; $user->cat_password = $password; $user->update(); self::verifyAccountInList($user); self::updateSession($user); return true; } return false; }
/** * Get a link for placing a title level hold. * * @param array $patron An array of patron data * * @return mixed A url if a hold is possible, boolean false if not * @access protected */ protected function getRealTimeTitleHold($patron = false) { global $configArray; $biblioLevel = $this->getBibliographicLevel(); if ("monograph" == strtolower($biblioLevel) || stristr("part", $biblioLevel)) { $titleHoldEnabled = CatalogConnection::getTitleHoldsMode(); if ($titleHoldEnabled != "disabled") { include_once 'sys/HoldLogicTitle.php'; // Get ID and connect to catalog $id = $this->getUniqueID(); $catalog = ConnectionManager::connectToCatalog(); $holdLogic = new HoldLogicTitle($catalog); return $holdLogic->getHold($id, $patron); } } return false; }
/** * Assign necessary Smarty variables and return a template name for the current * view to load in order to display a summary of the item suitable for use in * search results. * * @param string $view The current view. * * @return string Name of Smarty template file to display. * @access public */ public function getSearchResult($view = 'list') { global $configArray; global $interface; $interface->assign('summId', $this->getUniqueID()); $interface->assign('summFormats', $this->getFormats()); $interface->assign('summHighlightedTitle', $this->getHighlightedTitle()); $interface->assign('summTitle', $this->getTitle()); $interface->assign('summHighlightedAuthor', $this->getHighlightedAuthor()); $interface->assign('summAuthor', $this->getPrimaryAuthor()); $interface->assign('summAuthorForSearch', $this->getPrimaryAuthorForSearch()); $interface->assign('summBuilding', $this->getBuilding()); $interface->assign('summDate', $this->getPublicationDates()); $interface->assign('summISBN', $this->getCleanISBN()); $interface->assign('summThumb', $this->getThumbnail()); $interface->assign('summThumbLarge', $this->getThumbnail('large')); $issn = $this->getCleanISSN(); $interface->assign('summISSN', $issn); $interface->assign('summLCCN', $this->getLCCN()); $interface->assign('summOCLC', $this->getOCLC()); $interface->assign('summCallNo', $this->getCallNumber()); $interface->assign('summClassifications', $this->getClassifications()); $interface->assign('summContainerTitle', $this->getContainerTitle()); $interface->assign('summContainerReference', $this->getContainerReference()); $interface->assign('summDateSpan', $this->getDateSpan()); $interface->assign('summHierarchyParentId', $this->getHierarchyParentId()); $interface->assign('summHierarchyParentTitle', $this->getHierarchyParentTitle()); $interface->assign('summHierarchyTopId', $this->getHierarchyTopId()); $interface->assign('summHierarchyTopTitle', $this->getHierarchyTopTitle()); $interface->assign('summInstitutions', $this->getInstitutions()); $interface->assign('summOnlineURLs', $this->getOnlineURLs()); $interface->assign('summNonPresenterAuthors', $this->getNonPresenterAuthors()); //collection module only if (isset($configArray['Collections']['collections']) && $configArray['Collections']['collections'] == true) { $this->_assignSearchResultCollectionData(); } // Obtain and assign snippet information: $snippet = $this->getHighlightedSnippet(); $interface->assign('summSnippetCaption', $snippet ? $snippet['caption'] : false); $interface->assign('summSnippet', $snippet ? $snippet['snippet'] : false); // Only display OpenURL link if the option is turned on and we have // an ISSN. We may eventually want to make this rule more flexible, // but for now the ISSN restriction is designed to be consistent with // the way we display items on the search results list. Actually, // display OpenURL link for records with ISBNs too. $hasOpenURL = $this->openURLActive('results') && ($issn || $this->getCleanISBN()); $openURL = $this->getOpenURL(); $interface->assign('summOpenUrl', $hasOpenURL ? $openURL : false); // Always provide an OpenURL for COinS purposes: $interface->assign('summCOinS', $openURL); // Display regular URLs unless OpenURL is present and configured to // replace them: if (!isset($configArray['OpenURL']['replace_other_urls']) || !$configArray['OpenURL']['replace_other_urls'] || !$hasOpenURL) { $interface->assign('summURLs', $this->getURLs()); } else { $interface->assign('summURLs', array()); } $interface->assign('summHierarchy', $this->hasHierarchyTree()); // By default, do not display AJAX status; we won't assume that all // records exist in the ILS. Child classes can override this setting // to turn on AJAX as needed: $interface->assign('summAjaxStatus', false); // Display institutions and links to deduplicated records. $interface->assign('summDedupData', $this->getDedupData()); // Publication end date $interface->assign('summPublicationEndDate', $this->getPublicationEndDate()); // All images $interface->assign('summImages', $this->getAllImages()); // Record driver $id = $this->getUniqueID(); $catalog = ConnectionManager::connectToCatalog(); $driver = ''; if ($catalog && $catalog->status) { if (is_callable(array($catalog, 'getSourceDriver'))) { $driver = $catalog->getSourceDriver($id); } } $interface->assign('driver', $driver); // Send back the template to display: return 'RecordDrivers/Index/result-' . $view . '.tpl'; }
/** * Get Item Statuses * * This is responsible for printing the holdings information for a * collection of records in JSON format. * * @return void * @access public * @author Chris Delis <*****@*****.**> * @author Tuan Nguyen <*****@*****.**> */ public function getItemStatuses() { global $interface; global $configArray; $catalog = ConnectionManager::connectToCatalog(); if (!$catalog || !$catalog->status) { $this->output(translate('An error has occurred'), JSON::STATUS_ERROR); } $printIds = array(); $econtentIds = array(); $allIds = array(); foreach ($_GET['id'] as $id) { if (preg_match('/econtentRecord(\\d+)$/i', $id, $matches)) { $econtentIds[] = $matches[1]; } else { $printIds[] = $id; } } $allIds = array_merge($printIds, $econtentIds); $results = array(); if (count($printIds) > 0) { $results = $catalog->getStatuses($printIds); if (PEAR_Singleton::isError($results)) { $this->output($results->getMessage(), JSON::STATUS_ERROR); } else { if (!is_array($results)) { // If getStatuses returned garbage, let's turn it into an empty array // to avoid triggering a notice in the foreach loop below. $results = array(); } } } // In order to detect IDs missing from the status response, create an // array with a key for every requested ID. We will clear keys as we // encounter IDs in the response -- anything left will be problems that // need special handling. $missingIds = array_flip($printIds); // Load messages for response: $messages = array('available' => $interface->fetch('AJAX/status-available.tpl'), 'unavailable' => $interface->fetch('AJAX/status-unavailable.tpl')); // Load callnumber and location settings: $callnumberSetting = isset($configArray['Item_Status']['multiple_call_nos']) ? $configArray['Item_Status']['multiple_call_nos'] : 'msg'; $locationSetting = isset($configArray['Item_Status']['multiple_locations']) ? $configArray['Item_Status']['multiple_locations'] : 'msg'; // Loop through all the status information that came back $statuses = array(); foreach ($results as $record) { // Skip errors and empty records: if (!PEAR_Singleton::isError($record) && count($record)) { if ($locationSetting == "group") { $current = $this->_getItemStatusGroup($record, $messages, $callnumberSetting); } else { $current = $this->_getItemStatus($record, $messages, $locationSetting, $callnumberSetting); } $statuses[] = $current; // The current ID is not missing -- remove it from the missing list. unset($missingIds[$current['id']]); } } // If any IDs were missing, send back appropriate dummy data foreach ($missingIds as $missingId => $junk) { $statuses[] = array('id' => $missingId, 'availability' => 'false', 'availability_message' => $messages['unavailable'], 'location' => translate('Unknown'), 'locationList' => false, 'reserve' => 'false', 'reserve_message' => translate('Not On Reserve'), 'callnumber' => ''); } if (count($econtentIds) > 0) { require_once ROOT_DIR . '/Drivers/EContentDriver.php'; $econtentDriver = new EContentDriver(); $econtentResults = $econtentDriver->getStatuses($econtentIds); foreach ($econtentResults as $result) { $available = $result['available']; $interface->assign('status', $result['status']); if ($available) { $message = $interface->fetch('AJAX/status-available.tpl'); } else { $message = $interface->fetch('AJAX/status-unavailable.tpl'); } $statuses[] = array('id' => $result['id'], 'shortId' => $result['id'], 'availability' => $available ? 'true' : 'false', 'availability_message' => $message, 'location' => translate('Unknown'), 'locationList' => false, 'reserve' => 'false', 'reserve_message' => translate('Not On Reserve'), 'callnumber' => ''); } } // Done $this->output($statuses, JSON::STATUS_OK); }