uid) { $user->locum_pass = substr($user->pass, 0, 7); } // Assign the various CSS Files drupal_add_css(drupal_get_path('module', 'sopac') .'/sopac.css'); } /** * Display help and module information * * @param string $path Which path of the site we're displaying help * @param array $arg Array that holds the current path as would be returned from arg() function * @return string help text for the path */ function sopac_help($path, $arg) { $output = ''; switch ($path) { case "admin/help#sopac": $output = '

'. t("The Social OPAC™ for Drupal") .'

'; break; } return $output; } /** * Valid permissions for this module * * @return array An array of valid permissions for the sopac module */ function sopac_perm() { return array('access user pages', 'administer sopac'); } /** * Generate HTML for the sopac block. * Uses the following templates: sopac_facet_block.tpl.php * * @param string $op the operation from the URL * @param int $delta offset * @return string block HTML */ function sopac_block($op='list', $delta=0) { global $locum_results_all, $locum_cfg; // listing of blocks, such as on the admin/block page switch ($op) { case 'list': $block[0] = array( 'info' => t('Catalog Facets'), 'pages' => variable_get('sopac_url_prefix', 'cat/seek') . '/search/*', ); $block[1] = array( 'info' => t('Search Tracker'), 'pages' => variable_get('sopac_url_prefix', 'cat/seek') . '/search/*', ); $block[2] = array( 'info' => t('Catalog Tags'), 'pages' => variable_get('sopac_url_prefix', 'cat/seek') . '/*', ); $block[3] = array( 'info' => t('Catalog Reviews'), 'pages' => variable_get('sopac_url_prefix', 'cat/seek') . '/*', 'weight' => 1, ); $block[4] = array( 'info' => t('Item Tags'), 'pages' => variable_get('sopac_url_prefix', 'cat/seek') . '/record/*', ); $block[5] = array( 'info' => t('Item Reviews'), 'pages' => variable_get('sopac_url_prefix', 'cat/seek') . '/record/*', 'weight' => 1, ); $block[6] = array( 'info' => t('Personal Tags'), 'pages' => 'user/*', ); $block[7] = array( 'info' => t('Personal Reviews'), 'pages' => 'user/*', 'weight' => 1, ); return $block; case 'view': switch ($delta) { case 0: if ($locum_results_all[num_hits]) { $block_content = theme('sopac_facet_block', $facet_menu, $locum_results_all, $locum_cfg); $block['subject'] = 'Facets'; $block['content'] = $block_content; } break; case 1: require_once('sopac_catalog.php'); $block['subject'] = 'Your Search'; $block_content = sopac_search_block($locum_results_all, $locum_cfg); $block['content'] = $block_content; break; case 2: // SOPAC overview block for patron tags require_once('sopac_social.php'); $block['subject'] = 'Popular Tags'; $block['content'] = theme_sopac_tag_block('overview'); break; case 3: // SOPAC overview block for patron reviews require_once('sopac_social.php'); $block['subject'] = 'New Reviews'; $block['content'] = theme_sopac_review_block('overview'); break; case 4: // SOPAC item record block for patron tags require_once('sopac_social.php'); $block['subject'] = 'Record Tags'; $block['content'] = theme_sopac_tag_block('record'); break; case 5: // SOPAC item record block for patron reviews require_once('sopac_social.php'); $block['subject'] = 'Reviews'; $block['content'] = theme_sopac_review_block('record'); break; case 6: // SOPAC personal record block for patron's own tags require_once('sopac_social.php'); $block['subject'] = 'My Top Tags'; $block['content'] = theme_sopac_tag_block('personal'); break; case 7: // SOPAC personal record block for patron's own reviews require_once('sopac_social.php'); $block['subject'] = 'My Reviews'; $block['content'] = theme_sopac_review_block('personal'); break; } return $block; } } /** * Implementation of hook_menu() * Determines what the callback is for SOPAC and returns the appropriate Drupal menu array * * @return array Drupal menu array */ function sopac_menu() { global $user; $items = array(); $items['admin/settings/sopac'] = array( 'title' => 'SOPAC settings', 'description' => 'SOPAC configuration options', 'page callback' => 'drupal_get_form', 'page arguments' => array('sopac_admin'), 'access arguments' => array('access administration pages'), 'file' => 'sopac_admin.php', 'type' => MENU_NORMAL_ITEM, ); $items['search_handler'] = array( 'title' => 'Search Handler', 'page callback' => 'theme_sopac_search_handler', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); $items[variable_get('sopac_url_prefix', 'cat/seek') . '/search'] = array( 'title' => 'Catalog Search', 'page callback' => 'sopac_catalog_search', 'access arguments' => array('access content'), 'file' => 'sopac_catalog.php', 'type' => MENU_CALLBACK, ); $items[variable_get('sopac_url_prefix', 'cat/seek') . '/savesearch'] = array( 'title' => 'Save Search', 'page callback' => 'drupal_get_form', 'page arguments' => array('sopac_savesearch_form'), 'access arguments' => array('access user pages'), 'file' => 'sopac_user.php', 'type' => MENU_CALLBACK, ); $items[variable_get('sopac_url_prefix', 'cat/seek') . '/record/%'] = array( 'title' => 'Item Record', 'page callback' => 'sopac_bib_record', 'access arguments' => array('access content'), 'file' => 'sopac_catalog.php', 'type' => MENU_CALLBACK, ); $items[variable_get('sopac_url_prefix', 'cat/seek') . '/record/%/view'] = array( 'title' => 'Item Record', 'access arguments' => array('access content'), 'weight' => -10, 'file' => 'sopac_catalog.php', 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items[variable_get('sopac_url_prefix', 'cat/seek') . '/record/%/reviews'] = array( 'title' => 'Item Reviews', 'page callback' => 'sopac_review_page', 'access arguments' => array('access content'), 'page arguments' => array('catalog'), 'file' => 'sopac_social.php', 'type' => MENU_LOCAL_TASK, ); $items[variable_get('sopac_url_prefix', 'cat/seek') . '/request'] = array( 'title' => 'Request an Item', 'page callback' => 'sopac_request_item', 'access arguments' => array('access content'), 'file' => 'sopac_catalog.php', 'type' => MENU_CALLBACK, ); $items['user/checkouts'] = array( 'title' => 'My Checkouts', 'page callback' => 'sopac_checkouts_page', 'access arguments' => array('access user pages'), 'file' => 'sopac_user.php', 'type' => MENU_NORMAL_ITEM, ); $items['user/holds'] = array( 'title' => 'My Holds', 'page callback' => 'sopac_holds_page', 'access arguments' => array('access user pages'), 'file' => 'sopac_user.php', 'type' => MENU_NORMAL_ITEM, ); $items['user/fines'] = array( 'title' => 'My Fines', 'page callback' => 'sopac_fines_page', 'access arguments' => array('access user pages'), 'file' => 'sopac_user.php', 'type' => MENU_NORMAL_ITEM, ); $items['user/fines/list'] = array( 'title' => 'List Fines', 'access arguments' => array('access user pages'), 'weight' => -10, 'file' => 'sopac_user.php', 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['user/fines/payments'] = array( 'title' => 'List Payments', 'page callback' => 'sopac_finespaid_page', 'access arguments' => array('access user pages'), 'file' => 'sopac_user.php', 'type' => MENU_LOCAL_TASK, ); $items['user/fines/pay'] = array( 'title' => 'Fines Payment', 'page callback' => 'sopac_makepayment_page', 'access arguments' => array('access user pages'), 'file' => 'sopac_user.php', 'type' => MENU_CALLBACK, ); $items['user/library'] = array( 'title' => 'My Library', 'page callback' => 'sopac_personal_overview_page', 'access arguments' => array('access user pages'), 'file' => 'sopac_social.php', 'type' => MENU_NORMAL_ITEM, ); $items['user/library/tags'] = array( 'title' => 'My Tags', 'page callback' => 'sopac_tags_page_cloud', 'access arguments' => array('access user pages'), 'file' => 'sopac_social.php', 'type' => MENU_NORMAL_ITEM, ); $items['user/library/tags/cloud'] = array( 'title' => 'Tag Cloud', 'access arguments' => array('access user pages'), 'weight' => -10, 'file' => 'sopac_social.php', 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['user/library/tags/list'] = array( 'title' => 'Tag List', 'page callback' => 'sopac_tags_page_list', 'access arguments' => array('access user pages'), 'file' => 'sopac_social.php', 'type' => MENU_LOCAL_TASK, ); $items['user/tag/edit'] = array( 'title' => 'Edit Tag', 'page callback' => 'drupal_get_form', 'page arguments' => array('sopac_user_tag_edit'), 'access arguments' => array('access user pages'), 'file' => 'sopac_social.php', 'type' => MENU_CALLBACK, ); $items['user/tag/delete'] = array( 'title' => 'Delete Tag', 'page callback' => 'drupal_get_form', 'page arguments' => array('sopac_user_tag_delete'), 'access arguments' => array('access user pages'), 'file' => 'sopac_social.php', 'type' => MENU_CALLBACK, ); $items['user/tag/show'] = array( 'title' => 'Tagged Items', 'page callback' => 'sopac_user_tag_hitlist', 'access arguments' => array('access user pages'), 'file' => 'sopac_social.php', 'type' => MENU_CALLBACK, ); $items['user/library/ratings'] = array( 'title' => 'My Ratings', 'page callback' => 'sopac_ratings_page', 'access arguments' => array('access user pages'), 'file' => 'sopac_social.php', 'type' => MENU_NORMAL_ITEM, ); $items['user/library/reviews'] = array( 'title' => 'My Reviews', 'page callback' => 'sopac_review_page', 'access arguments' => array('access user pages'), 'page arguments' => array('personal'), 'file' => 'sopac_social.php', 'type' => MENU_NORMAL_ITEM, ); $items['user/library/searches'] = array( 'title' => 'My Searches', 'page callback' => 'sopac_saved_searches_page', 'access arguments' => array('access user pages'), 'file' => 'sopac_user.php', 'type' => MENU_NORMAL_ITEM, ); $items['review/delete'] = array( 'title' => 'Delete Review', 'page callback' => 'drupal_get_form', 'page arguments' => array('sopac_delete_review_form'), 'access arguments' => array('access user pages'), 'file' => 'sopac_social.php', 'type' => MENU_CALLBACK, ); $items['review/edit'] = array( 'title' => 'Edit Review', 'page callback' => 'drupal_get_form', 'page arguments' => array('sopac_review_form'), 'access arguments' => array('access user pages'), 'file' => 'sopac_social.php', 'type' => MENU_CALLBACK, ); $items['review/view'] = array( 'title' => 'Read Review', 'page callback' => 'sopac_review_page', 'access arguments' => array('access content'), 'page arguments' => array('single'), 'file' => 'sopac_social.php', 'type' => MENU_CALLBACK, ); $items['review/user'] = array( 'title' => 'User Reviews', 'page callback' => 'sopac_review_page', 'access arguments' => array('access content'), 'page arguments' => array('user'), 'file' => 'sopac_social.php', 'type' => MENU_CALLBACK, ); return $items; } /** * Implementation of hook_theme() */ function sopac_theme() { return array( 'sopac_results' => array( 'template' => 'sopac-results', 'arguments' => array('result_info' => NULL, 'hitlist_pager' => NULL, 'hitlist_content' => NULL, 'locum_result' => NULL, 'locum_config' => NULL), ), 'sopac_results_hitlist' => array( 'template' => 'sopac-results-hitlist', 'arguments' => array('result_num' => NULL, 'cover_img_url' => NULL, 'locum_result' => NULL, 'locum_config' => NULL, 'no_circ' => NULL), ), 'sopac_results_nohits' => array( 'template' => 'sopac-results-nohits', 'arguments' => array('locum_result' => NULL, 'locum_config' => NULL), ), 'sopac_record' => array( 'template' => 'sopac-record', 'arguments' => array('item' => NULL, 'item_status' => NULL, 'locum_config' => NULL, 'no_circ' => NULL, 'locum' => NULL), ), 'sopac_review' => array( 'template' => 'sopac-review', 'arguments' => array('user' =>NULL, 'title' => NULL, 'rev_arr' => NULL, 'page_type' => NULL, 'rev_form' => NULL, 'ratings' => NULL, 'no_rev_msg' => NULL, 'bib_info' => NULL), ), 'sopac_facet_block' => array( 'template' => 'sopac-facet-block', 'arguments' => array('facet_menu' => NULL, 'locum_result' => NULL, 'locum_config' => NULL), ), 'sopac_search_block' => array( 'template' => 'sopac-search-block', 'arguments' => array('search' => NULL, 'locum_result' => NULL, 'locum_config' => NULL, 'user' => NULL), ), 'sopac_request' => array( 'template' => 'sopac-request', 'arguments' => array('request_result_msg' => NULL, 'request_error_msg' => NULL, 'item_form' => NULL, 'bnum' => NULL), ), 'sopac_fines' => array( 'template' => 'sopac-fines', 'arguments' => array('notice' => NULL, 'fine_table' => NULL, 'user' => NULL, 'payment_form' => NULL), ), 'sopac_pat_overview' => array( 'template' => 'sopac-pat-overview', 'arguments' => array('review_display' => NULL, 'ratings_chunk' => NULL, 'tag_cloud' => NULL), ), 'sopac_ratings_page' => array( 'template' => 'sopac-ratings-page', 'arguments' => array('ratings_arr' => NULL), ), 'sopac_tags_page' => array( 'template' => 'sopac-tags-page', 'arguments' => array('tags_arr' => NULL), ), ); } /** * Implementation of hook_user() */ function sopac_user($op, &$edit, &$account, $category = NULL) { require_once('sopac_user.php'); switch ($op) { case 'submit': sopac_update_locum_acct($op, $edit, $account); break; case 'view': sopac_user_view($op, $edit, $account, $category); break; case 'delete': // TODO : Clean-up break; } } /** * Checks to see if $cardnum has been verified * * @param string $cardnum Library patron barcode/card number * @return boolean True if patron has verified the barcode, False if not. */ function sopac_bcode_isverified(&$user_obj) { if (!$user_obj->profile_pref_cardnum) { profile_load_profile($user_obj); } if (!$user_obj->profile_pref_cardnum) { return FALSE; } $db_obj = db_fetch_object(db_query("SELECT COUNT(*) AS vfy FROM {sopac_card_verify} WHERE uid = %d AND cardnum = '%s' AND verified > 0", $user_obj->uid, $user_obj->profile_pref_cardnum)); if ($db_obj->vfy > 0) { return TRUE; } else { return FALSE; } } /** * Creates an external function to formulate a search form by doing the neccesary includes. * An example for using this might be calling this function from within a node. * * @param string $form_type Can be "basic", "advanced", or "both" (default) * @return string Drupal-themed and generated search form */ function sopac_search_form($form_type = 'both') { require_once('sopac_catalog.php'); switch(strtolower(trim($form_type))) { case 'basic': $search_form = drupal_get_form('sopac_search_form_basic'); break; case 'advanced': $search_form = drupal_get_form('sopac_search_form_adv'); break; case 'both': default: $search_form = drupal_get_form('sopac_search_form_basic') . drupal_get_form('sopac_search_form_adv'); break; } return $search_form; } /* * Handles the search queries & sets the the RESTful URIs. * It very well may be that this function needs to be overridden due to themeing * considerations, so it takes advantage of Drupal's hook_theme and may be defined * in template.php. */ function theme_sopac_search_handler() { $locum = new locum(); $locum_cfg = $locum->locum_config; $search_query = trim($_POST[search_query]); if (!$search_query) { $search_query = '*'; } $search_type = $_POST[search_type]; $search_type_arr = explode('_', $search_type); if ($search_type_arr[0] == 'cat') { $search_type = $search_type_arr[1]; $search_fmt = $search_type_arr[2]; $search_url = '/' . variable_get('sopac_url_prefix', 'cat/seek') . '/search/' . $search_type . '/' . $search_query; // Material / Format types if ($search_fmt) { if ($search_fmt != 'all') { $uris[search_format] = $locum->csv_parser($locum_cfg[format_groups][$search_fmt], '|'); } } else if ($_POST[search_format]) { if (is_array($_POST[search_format])) { $uris[search_format] = trim(implode('|', $_POST[search_format])); } else { $uris[search_format] = $_POST[search_format]; } } // Location selections overrule collection selections and act as // a filter if they are in a selection colection. if ($_POST[collection]) { $locations = array(); $uris[collection] = trim(implode('|', $_POST[collection])); foreach ($_POST[collection] as $collection) { $collection_arr = $locum->csv_parser($locum_cfg[collections][$collection]); if ($_POST[location]) { $valid_locs = array_intersect($_POST[location], $collection_arr); if (count($valid_locs)) { $locations = array_merge($locations, $valid_locs); } else { $locations = array_merge($locations, $collection_arr); } } else { $locations = array_merge($locations, $collection_arr); } } if ($_POST[location]) { $locations = array_merge($locations, array_diff($_POST[location], $locations)); } } else if ($_POST[location]) { $locations = $_POST[location]; } if (count($locations)) { $uris[location] = trim(implode('|', $locations)); } // Sort variable if ($_POST[sort]) { $uris[sort] = $_POST[sort]; } // Convert all our URI variables to GETs if (count($uris)) { $delimiter = '?'; foreach ($uris as $uri_key => $uri_vals) { $search_url .= $delimiter . $uri_key . '=' . $uri_vals; $delimiter = '&'; } } } else if ($search_type_arr[0] == 'web') { switch ($search_type_arr[1]) { case 'local': $search_url = '/search/node/' . utf8_urldecode($search_query); break; case 'google': $search_url = 'http://www.google.com/search?hl=en&q=' . utf8_urldecode($search_query); break; } } header('Location: ' . $search_url); } /** * A little function that strips out all the random crapola that people's browsers sometimes throw in. * * @return string cleaned-up URI. */ function utf8_urldecode($str) { $str = preg_replace("/%u([0-9a-f]{3,4})/i","&#x\\1;",urldecode($str)); return html_entity_decode($str,null,'UTF-8');; } /** * This function parses the URI to grab the elements upon which SOPAC acts. This is an * attempt at pseudo-RESTful URIs within the catalog. We'll still use some GET vars but * the major functionality if represented RESTfully. * * @return array Array of URI elements */ function sopac_parse_uri($strip_prefix = TRUE) { // Strip out everything in the URI up through SOPAC's prefix if ($strip_prefix) { $args_raw = substr($_GET[q], strlen(variable_get('sopac_url_prefix', 'cat/seek'))); } else { $args_raw = $_GET[q]; } $uri_array = explode('/', $args_raw); if ($uri_array[0] == '') { array_shift($uri_array); } foreach ($uri_array as $uri_elem) { $result[] = urldecode(trim($uri_elem)); } return $result; } /** * Returns an array of GET variables, allowing for the ability to override them * It also parses getvars with multiple values delimited by | * * @param array $override Optional override option that will override actual GET variables * @return boolean|array If there are GET vars, an array of GET vars is returned, or else FALSE */ function sopac_parse_get_vars($override = array()) { // TODO - Hard-coding this is not the best way to do it, but for now it is what it is... Revisit for 2.1? $implode = array('search_format', 'pub_year', 'location', 'collection', 'facet_series', 'facet_lang', 'facet_year'); $getvars_raw = explode('?', $_SERVER[REQUEST_URI]); if (count($getvars_raw) > 1) { $getvars = urldecode($getvars_raw[1]); } else { if (count($override)) { return $override; } else { return FALSE; } } $getvars = explode('&', trim($getvars)); foreach ($getvars as $get) { $get_arr = explode('=', $get); if (count($get_arr) > 1) { if (in_array($get_arr[0], $implode)) { $vars[$get_arr[0]] = explode('|', trim($get_arr[1])); } else { $vars[$get_arr[0]] = trim($get_arr[1]); } } } foreach ($override as $okey => $ovar) { if ($ovar) { $vars[$okey] = $ovar; } else { unset($vars[$okey]); } } return $vars; } /** * Function to automate the handling of the pager system. */ function sopac_pager_init($total, $element = 0, $limit = 10) { global $pager_page_array, $pager_total, $pager_total_items; $page = isset($_GET['page']) ? $_GET['page'] : ''; // Convert comma-separated $page to an array, used by other functions. $pager_page_array = explode(',', $page); // We calculate the total of pages as ceil(items / limit). $pager_total_items[$element] = $total; $pager_total[$element] = ceil($pager_total_items[$element] / $limit); $pager_page_array[$element] = max(0, min((int)$pager_page_array[$element], ((int)$pager_total[$element]) - 1)); } function sopac_user_block_disp_query() { global $user; $user_views = array('fines', 'library', 'holds', 'checkouts', 'tag'); $uri_arr = explode('/', $_GET[q]); if ($uri_arr[0] == 'user' && in_array($uri_arr[1], $user_views)) { return TRUE; } return $user->uid && arg(0) == 'user' && is_numeric(arg(1)) && arg(1) == $user->uid; return FALSE; }