# This patch file was generated by NetBeans IDE # This patch can be applied using context Tools: Apply Diff Patch action on respective folder. # It uses platform neutral UTF-8 encoding. # Above lines and this line are ignored by the patching process. Index: contributions/modules/millennium/contrib/millennium_filter/millennium_filter.module --- contributions/modules/millennium/contrib/millennium_filter/millennium_filter.module Base (1.1.2.5) +++ contributions/modules/millennium/contrib/millennium_filter/millennium_filter.module Locally Modified (Based On 1.1.2.5) @@ -111,6 +111,13 @@ ), '#default_value' => variable_get('millennium_filter_report_errors', array('watchdog' => 'watchdog')), ); + $form['millennium_filter']['millennium_filter_default_base_url'] = array( + '#type' => 'select', + '#title' => t('Default source WebOPAC'), + '#description' => t('Select one of the enabled sources to use when only record numbers are issued.'), + '#default_value' => variable_get('millennium_filter_default_base_url', ''), + '#options' => drupal_map_assoc(array_merge(array(0 => t('')), array_keys(variable_get('millennium_sources', array())))), + ); $form['millennium_filter']['millennium_filter_remove_fields'] = array( '#type' => 'checkboxes', '#title' => t('Fields to hide in shown records'), @@ -153,7 +160,17 @@ if (!preg_match(MILLENNIUM_RECORD_PREG_NOCHECKDIGIT, $id)) { return false; } - $base_url = millennium_get_real_baseurl(); \ No newline at end of file + // Pick the OPAC to use + $base_url = variable_get('millennium_filter_default_base_url', ''); + if (!$base_url) { + // If only one source defined, use that one as default + $sources = variable_get('millennium_sources', array()); + if (sizeof($sources) == 0) { + return false; + } + // Put the index of the first (and only) element of $source into $base_url + foreach ($sources as $base_url => $dummy); + } \ No newline at end of file $recnum = $id; } Index: contributions/modules/millennium/millennium.admin.inc --- contributions/modules/millennium/millennium.admin.inc Base (1.1.2.31) +++ contributions/modules/millennium/millennium.admin.inc Locally Modified (Based On 1.1.2.31) @@ -9,8 +9,10 @@ * Callback for drupal_get_form for general settings form */ function millennium_admin_settings() { - if (variable_get('millennium_webopac_baseurl', false) === false) { - drupal_set_message(t('You have not yet set the Base URL.'), 'warning'); + $form = array(); + $sources = millennium_get_sources_count(); + if (sizeof($sources) == 0) { + drupal_set_message(t('You have not yet set any sources.'), 'warning'); } $node_types = node_get_types(); @@ -33,22 +35,6 @@ '#default_value' => variable_get('millennium_marc_node_type', 'page'), ); - $form['general']['millennium_webopac_baseurl'] = array( - '#type' => 'textfield', - '#title' => t("Base URL for WebOPAC"), - '#size' => 40, - '#default_value' => variable_get('millennium_webopac_baseurl', ''), - '#description' => t('For example: http://example.com/'), - '#prefix' => '
', - '#suffix' => '
', - '#ahah' => array( - 'path' => 'millennium_checkurl_js', - 'event' => 'change', - 'wrapper' => 'checkurl', - 'method' => 'replace', - 'effect' => 'fade', - ), - ); $form['general']['millennium_action_on_last_item_deleted'] = array( '#type' => 'radios', '#title' => t('Action when imported records are no longer found in WebOPAC'), @@ -56,7 +42,165 @@ '#default_value' => variable_get('millennium_action_on_last_item_deleted', 'unpublish'), ); - $run_cron_url = l(t('run cron'), 'admin/reports/status/run-cron', array('query' => array('destination' => MILLENNIUM_SETTINGS_PATH))); + // Sources fieldset + $form['sources'] = array( + '#type' => 'fieldset', + '#collapsible' => true, + '#title' => t('Source OPACs'), + '#description' => t('You can enter OPAC sources that will be available for batch import and other operations.'), + ); + + // Show table for existing OPAC sources + $rows = array(); + $headers = array(t('Action'), t('OPAC base URL'), t('OPAC name'), t('Import stats')); + foreach ($sources as $base_url => $source_data) { + // Element to remove this source + $remove_element = array( + '#name' => 'remove_source_' . $base_url, + '#type' => 'checkbox', + '#title' => t('Remove') + ); + // Element to edit existing source name + $edit_name_element = array( + '#name' => 'edit_name_' . $base_url, + '#type' => 'textfield', + '#value' => $source_data["name"], + '#size' => 30, + ); + // Add row to table + $rows[] = array( + drupal_render($remove_element), + l($base_url, $base_url), + drupal_render($edit_name_element), + t('@count nodes', array('@count' => $sources[$base_url]['node_count'] + 0)), + ); + } + + // Add a final table row to allow adding new sources + $add_url_element = array( + '#name' => 'add_url', + '#type' => 'textfield', + '#size' => 30, + '#required' => TRUE, + ); + $add_name_element = array( + '#name' => 'add_name', + '#type' => 'textfield', + '#size' => 30, + ); + $rows[] = array(t('Add new source:'), drupal_render($add_url_element), drupal_render($add_name_element)); + // Add the themed table to the form + $form['sources']['table'] = array( + '#type' => 'markup', + '#value' => theme('table', $headers, $rows) + ); + // Add custom validation and submission callbacks only for the table elements; + // the rest of the form is automatically handled by + // system_settings_form_submit() because of system_settings_form() call below. + $form['#validate'][] = 'millennium_admin_settings_form_validate'; + $form['#submit'][] = 'millennium_admin_settings_form_submit'; + + // Render as a system settings form. + return system_settings_form($form); +} + +/** + * Validate handler for settings form; handles special values in table + */ +function millennium_admin_settings_form_validate($form, &$form_state) { + $sources = variable_get('millennium_sources', array()); + + // Validate sources to remove + foreach ($sources as $base_url => $source_data) { + $base_url_as_index = str_replace(".", "_", $base_url); + if ($form_state['clicked_button']['#post']["remove_source_{$base_url_as_index}"]) { + // Check if there are existing records for this base_url + $count = (int)db_result(db_query("SELECT count(1) FROM {millennium_node_bib} WHERE base_url = '%s'", $base_url)); + if ($count) { + form_set_error("remove_source_{$base_url_as_index}", t('The source %url cannot be removed since nodes that depend on it still exist.', array('%url' => $new_url))); + } + } + } + + // Validate a new URL if given + $new_url = trim($form_state['clicked_button']['#post']['add_url']); + $new_name = trim($form_state['clicked_button']['#post']['add_name']); + if ($new_url) { + // Check for valid URL + if (strpos($new_url, 'http://') !== 0) { + form_set_error('add_url', t('The entered url %url is not valid.', array('%url' => $new_url))); + return; + } + + // Normalize the base url, eliminate markup or XSS + $new_url = check_plain(millennium_get_real_baseurl($new_url)); + + // Check for unique base URL + if (isset($sources[$new_url])) { + form_set_error('add_url', t('The url %url is already defined.', array('%url' => $new_url))); + return; + } + } + // All is OK, store the normalized URL for the submit function + $form_state['storage']['add_url'] = $new_url; +} + +/** + * Submit handler for settings form; handles special values that are not + */ +function millennium_admin_settings_form_submit($form, &$form_state) { + #dpm($form_state); + $sources = variable_get('millennium_sources', array()); + + // Update any changes to sources + foreach ($sources as $base_url => $source_data) { + $base_url_as_index = str_replace(".", "_", $base_url); + // Removal checked? + if ($form_state['clicked_button']['#post']["remove_source_{$base_url_as_index}"] == "1") { + drupal_set_message(t('Removed source %url', array('%url' => $base_url))); + unset($sources[$base_url]); + continue; + } + + // Name change + $sent_name = check_plain(trim($form_state['clicked_button']['#post']["edit_name_{$base_url_as_index}"])); + if ($sent_name != $source_data["name"]) { + // Update taxonomy term if mapping currently set + $opacname_vid = variable_get('millennium_opacname_vid', -1); + if ($opacname_vid != -1) { + // Find and load existing term + $tid = db_result(db_query('SELECT tid FROM {term_data} WHERE vid=%d and name="%s"', $opacname_vid, $source_data["name"])); + $term = taxonomy_get_term($tid); + $term->name = $sent_name; + // Save term's new name + $term = (array)$term; + taxonomy_save_term($term); + if ($sent_name != '') { + drupal_set_message(t('Updated taxonomy term for %opacname.', array('%opacname' => $sent_name))); + } + } + // Set name in $sources array + $sources[$base_url]["name"] = $sent_name; + } + } + + // If sent, add the new url and name to the sources + $new_url = $form_state['storage']['add_url']; + $new_name = trim($form_state['clicked_button']['#post']['add_name']); + if ($new_url) { + $sources[$new_url] = array('name' => check_plain($new_name)); + } + + // Store the new value for sources + variable_set('millennium_sources', $sources); +} + +/** + * Callback for drupal_get_form for crawl settings form. + */ +function millennium_admin_crawl() { + $form = array(); + $run_cron_url = l(t('run cron'), 'admin/reports/status/run-cron', array('query' => array('destination' => MILLENNIUM_SETTINGS_PATH . '/crawl'))); $form['crawl'] = array( '#type' => 'fieldset', '#collapsible' => true, @@ -71,6 +215,13 @@ '#description' => t('Enabling this will start (or continue) the automatic record import/update. Disabling this does not stop importing items queued manually for import.'), '#default_value' => variable_get('millennium_crawl_flag', 0), ); + $form['crawl']['millennium_crawl_baseurl'] = array( + '#type' => 'select', + '#title' => t('Source WebOPAC'), + '#description' => t('Select one of the enabled sources.'), + '#default_value' => variable_get('millennium_crawl_baseurl', ''), + '#options' => drupal_map_assoc(array_merge(array(0 => t('')), array_keys(variable_get('millennium_sources', array())))), + ); $form['crawl']['millennium_webopac_maxrecords'] = array( '#type' => 'select', '#title' => t("Items to import per cron run"), @@ -106,7 +257,6 @@ '#description' => t('WARNING: Set ONLY if you want to start over from that number onwards.'), '#default_value' => variable_get('millennium_webopac_reset', false), ); - return system_settings_form($form); } @@ -130,6 +280,13 @@ '#description' => t('WARNING: This option might slow down your page views, as availability information is fetched from the Millennium for each record (and kept in a Drupal cache for subsequent calls). Recommended setting is "Full view only".'), ); + $form['holdings']['millennium_holdings_opacname'] = array( + '#type' => 'checkbox', + '#title' => t('Show OPAC name in record holdings table'), + '#description' => t('Enabling this will show the OPAC name entered in the Sources tab next to each item in the holdings table.'), + '#default_value' => variable_get('millennium_holdings_opacname', 1), + ); + $form['holdings']['millennium_preferred_locations'] = array( '#type' => 'textfield', '#title' => '('. t('Optional') .') '. t('Locations to show in teaser view availability (comma-separated)'), @@ -194,18 +351,18 @@ '#value' => t('If you want to browse your imported records via taxonomy, you must assign a mapping here.') . '', ); - $form['vids'] = array( + $form['marc'] = array( '#type' => 'fieldset', '#title' => t("MARC to taxonomy mappings"), '#collapsible' => false, // DUE to problems http://drupal.org/node/152431 ); - $form['vids']['millennium_taxonomy_language'] = array( + $form['marc']['millennium_taxonomy_language'] = array( '#type' => 'radios', '#title' => t('Language used to create taxonomy terms and other additional information'), '#options' => array( @@ -221,7 +378,7 @@ // Issue warning when no applicable vocabularies are available if (sizeof($v_options) == 1) { - $form['vids']['warning'] = array( + $form['marc']['warning'] = array( '#type' => 'markup', '#prefix' => '
', '#suffix' => '
', @@ -260,17 +417,31 @@ foreach ($vocs as $code => $voc_name) { $name = "millennium_marc_vid_$code"; - $form['vids'][$name] = array( + $form['marc'][$name] = array( '#type' => 'select', - '#prefix' => '' . $voc_name . '
'. $descs[$code].'
' . t("into") . '', + '#prefix' => '' . $voc_name . '
'. $descs[$code].'
' . t("into") . '', '#suffix' => '', '#options' => $v_options, '#default_value' => variable_get($name, -1) ); } + // Fieldset for OPAC Name + $form['opacname'] = array( + '#prefix' => '', + '#type' => 'fieldset', + '#title' => t("OPAC name to taxonomy mapping"), + '#collapsible' => false, + '#description' => t("These settings map the originating OPAC's name (defined in the !sourceslink tab) into a taxonomy vocabulary.", array('!sourceslink' => l(t('sources'), 'admin/settings/millennium'))), + ); + $form['opacname']['millennium_opacname_vid'] = array( + '#type' => 'select', + '#title' => t('Map originating OPAC name into'), + '#options' => $v_options, + '#default_value' => variable_get('millennium_opacname_vid', -1) + ); + $form['availability'] = array( - '#prefix' => '', '#type' => 'fieldset', '#title' => t("Holdings locations to taxonomy mapping"), '#collapsible' => false, @@ -322,20 +493,14 @@ if ($tot_queued_items > 0) { $form['source']['#options']['queued'] = t('All records awaiting cron (@num items). Note: this will empty the cron queue!', array("@num" => $tot_queued_items)); } - $form['millennium_webopac_baseurl'] = array( - '#type' => 'textfield', - '#title' => t('Base URL for WebOPAC'), - '#description' => t('For example: http://example.com/'), - '#default_value' => variable_get('millennium_import_form_baseurl', variable_get('millennium_webopac_baseurl', '')), - '#prefix' => '
', - '#suffix' => '
', - '#ahah' => array( - 'path' => 'millennium_checkurl_js', - 'event' => 'change', - 'wrapper' => 'checkurl', - 'method' => 'replace', - 'effect' => 'fade', - ), + $form['millennium_import_form_baseurl'] = array( + '#prefix' => '
', + '#suffix' => '
', + '#type' => 'select', + '#title' => t('Source WebOPAC'), + '#description' => t('Select one of the enabled sources.'), + '#default_value' => variable_get('millennium_import_form_baseurl', ''), + '#options' => drupal_map_assoc(array_merge(array(0 => t('')), array_keys(variable_get('millennium_sources', array())))), ); $form['list'] = array( '#type' => 'fieldset', @@ -458,9 +623,9 @@ if ($form_state["values"]["source"] == "range" || $form_state["values"]["source"] == "list" || $form_state["values"]["source"] == "query") { - $base_url = $form_state['values']['millennium_webopac_baseurl']; + $base_url = millennium_get_real_baseurl($form_state['values']['millennium_import_form_baseurl']); if (!$base_url) { - form_set_error('millennium_webopac_baseurl', t("Not a valid base URL.")); + form_set_error('millennium_import_form_baseurl', t("Not a valid base URL.")); } } if ($form_state["values"]["source"] == "range") { @@ -537,7 +702,7 @@ // Store some values for later variable_set('millennium_import_form_source', $form_state["values"]["source"]); - variable_set('millennium_import_form_baseurl', $form_state["values"]["millennium_webopac_baseurl"]); + variable_set('millennium_import_form_baseurl', $form_state["values"]["millennium_import_form_baseurl"]); variable_set('millennium_import_form_force_update', $form_state["values"]["force_update"]); variable_set('millennium_list_form_checkdigit', $form_state["values"]["ignore_checkdigit"]); variable_set('millennium_range_form_type', $form_state["values"]["type"]); @@ -546,6 +711,8 @@ variable_set('millennium_import_form_kw', $form_state["values"]["kw"]); variable_set('millennium_import_form_url', $form_state["values"]["url"]); + $base_url = millennium_get_real_baseurl($form_state['values']['millennium_import_form_baseurl']); + if ($form_state["clicked_button"]["#value"] == t("Process these records during cron runs")) { // When? Cron runs @@ -570,7 +737,7 @@ $recnum, $form_state['values']['priority'], $form_state['values']['force_update'], - $form_state['values']['millennium_webopac_baseurl']); + $base_url); if ($ok) $queued++; } @@ -587,7 +754,7 @@ $type . $num, $form_state['values']['priority'], $form_state['values']['force_update'], - $form_state['values']['millennium_webopac_baseurl']); + $base_url); if ($ok) { $queued++; } @@ -631,7 +798,7 @@ if ($form_state["values"]["ignore_checkdigit"] == true) { $recnum = drupal_substr($recnum, 0, drupal_strlen($recnum)-1); } - $records_to_crawl[$form_state['values']['millennium_webopac_baseurl']][$recnum] = $recnum; + $records_to_crawl[$base_url][$recnum] = $recnum; } } } @@ -641,7 +808,6 @@ $type = $form_state["values"]["type"]; $start = $form_state["values"]["start"]; $end = $form_state["values"]["end"]; - $base_url = millennium_get_real_baseurl($form_state['values']['millennium_webopac_baseurl']); for ($num = $start; $num <= $end; $num++) { $records_to_crawl[$base_url]["{$type}{$num}"] = "{$type}{$num}"; } @@ -650,7 +816,6 @@ if ($form_state["values"]["source"] == "query") { require_once 'millennium.import.inc'; variable_set('millennium_import_form_num_items', $form_state["values"]["num_items"]); - $base_url = $form_state['values']['millennium_webopac_baseurl']; $records = millennium_query_scrape( $form_state["values"]["kw"], $base_url, Index: contributions/modules/millennium/millennium.cron.inc --- contributions/modules/millennium/millennium.cron.inc Base (1.1.2.9) +++ contributions/modules/millennium/millennium.cron.inc Locally Modified (Based On 1.1.2.9) @@ -11,11 +11,11 @@ $start_time = microtime(true); // Is URL set? - if (($base_url = millennium_get_real_baseurl()) === false) { + if (($base_url = variable_get('millennium_crawl_baseurl', false)) === false) { return; } if (!millennium_ping($base_url)) { - watchdog("Millennium", "Cron run aborted because WebOPAC at @url not responding", array("@url" => $base_url)); + watchdog("Millennium", "Cron run aborted because WebOPAC at @url not responding", array("@url" => $base_url), WATCHDOG_ERROR); return; } @@ -143,7 +143,7 @@ // Chunk array into groups of 50 (maximum number allowed by bookcart) $recnums_chunks = array_chunk($recnums, 50); foreach ($recnums_chunks as $recnums_chunk) { - $fetched = millennium_fetch_records_via_bookcart($recnums_chunk); + $fetched = millennium_fetch_records_via_bookcart($recnums_chunk, false, $base_url); #dpm($fetched); foreach ($fetched['found'] as $data) { $result = millennium_process_record($data); @@ -206,8 +206,8 @@ $elapsed_time = microtime(true) - $start_time; millennium_time_history($elapsed_time, $tot_attempted, $tot_notfound, $tot_imported, $tot_fail); - watchdog("Millennium", "Cron import finished: @attempted attempted, @notfound not found on WebOpac, @imported imported ok, @failed could not import, in @time seconds (@time2 items per second)", - array("@attempted" => $tot_attempted, "@notfound" => $tot_notfound, "@imported" => $tot_imported, "@failed" => $tot_fail+0, "@time" => sprintf("%2.1f", $elapsed_time), "@time2" => sprintf("%2.1f", $tot_attempted / $elapsed_time)) \ No newline at end of file + watchdog("Millennium", "Cron import finished: @url: @attempted attempted, @notfound not found on WebOpac, @imported imported ok, @failed could not import, in @time seconds (@time2 items per second)", + array("@url" => $base_url, "@attempted" => $tot_attempted, "@notfound" => $tot_notfound, "@imported" => $tot_imported, "@failed" => $tot_fail+0, "@time" => sprintf("%2.1f", $elapsed_time), "@time2" => sprintf("%2.1f", $tot_attempted / $elapsed_time)) \ No newline at end of file ); } } Index: contributions/modules/millennium/millennium.import.inc --- contributions/modules/millennium/millennium.import.inc Base (1.1.2.20) +++ contributions/modules/millennium/millennium.import.inc Locally Modified (Based On 1.1.2.20) @@ -71,12 +71,7 @@ * @param $limit * Maximum number of records to return. */ -function millennium_query_scrape($query, $base_url = false, $limit = 100) { - if ($base_url == false) { - $base_url = millennium_get_real_baseurl(); - } else { - $base_url = millennium_get_real_baseurl($base_url); - } +function millennium_query_scrape($query, $base_url, $limit = 100) { // Build query URL $url = "{$base_url}/search/X?" . drupal_urlencode($query); // Get records @@ -90,7 +85,7 @@ * @param $base_url * The base url of the WebOPAC to process. */ -function millennium_mass_fetch($recnums, $base_url = false) { +function millennium_mass_fetch($recnums, $base_url) { // This seems to be the limit for WebOPACs, do not change =) $max_records_for_bookcart = 40; @@ -163,19 +158,13 @@ * 'not_found' => array('i100000', 'i100005', [...]) * ); */ -function millennium_fetch_records_via_bookcart($recnums, $complete_holdings = false, $base_url = false) { +function millennium_fetch_records_via_bookcart($recnums, $complete_holdings = false, $base_url) { // Set the following to true for lots and lots of debugging info =) $debug = false; // Start timer to measure average performance timer_start("millennium_fetch_records_via_bookcart"); - if ($base_url == false) { - $base_url = millennium_get_real_baseurl(); - } else { - $base_url = millennium_get_real_baseurl($base_url); - } - $found_items = array(); $not_found_items = array(); @@ -344,11 +333,11 @@ // volume/copy" button? Do we want to check for complete holdings? if ($match[3] != "" && $complete_holdings == true) { // Yes. Issue additional request to OPAC to get holdings information for item. - $found_items[$current_recnum]['holdings'] = millennium_get_holdings_info($this_bib_recnum, null, $base_url); + $found_items[$current_recnum]['holdings'] = millennium_get_holdings_info($this_bib_recnum, $base_url); } else { // No. Convert whatever holdings info (might be incomplete) we got along // with the MARC export and add it to the item array. - $found_items[$current_recnum]['holdings'] = millennium_get_holdings_info($this_bib_recnum, $match[2], $base_url); \ No newline at end of file + $found_items[$current_recnum]['holdings'] = millennium_get_holdings_info($this_bib_recnum, $base_url, $match[2]); \ No newline at end of file } $found_items_index++; } Index: contributions/modules/millennium/millennium.install --- contributions/modules/millennium/millennium.install Base (1.1.2.5.2.1.2.10) +++ contributions/modules/millennium/millennium.install Locally Modified (Based On 1.1.2.5.2.1.2.10) @@ -23,6 +23,8 @@ if ($phase == 'runtime') { $msg = array(); + /* TODO: Decide if we will still check if a single OPAC (or multiple OPACs?) + * are responding. $base_url = millennium_get_real_baseurl(); if (!$base_url) { $msg[] = $t("You must configure a base URL; please go to the !configurationpage", array("!configurationpage" => l($t("configuration page"), MILLENNIUM_SETTINGS_PATH))); @@ -44,6 +46,7 @@ 'description' => $description, 'severity' => $severity, ); + */ } return $requirements; } @@ -261,8 +264,10 @@ db_query("DELETE FROM {variable} WHERE name LIKE 'millennium_marc_vid_%'"); variable_del('millennium_action_on_last_item_deleted'); + variable_del('millennium_sources'); variable_del('millennium_crawl_flag'); variable_del('millennium_crawl_type'); + variable_del('millennium_crawl_baseurl'); variable_del('millennium_preferred_locations'); variable_del('millennium_coverimage_baseurl'); variable_del('millennium_time_history'); @@ -273,6 +278,9 @@ variable_del('millennium_googlebooks_covers'); variable_del('millennium_googlebooks_widget'); variable_del('millennium_availability_vid'); + variable_del('millennium_map_available_only'); + variable_del('millennium_availability_strings'); + variable_del('millennium_opacname_vid'); } /** @@ -341,3 +349,23 @@ ); return $ret; } + +function millennium_update_6005() { + $ret = array(); + $sources = variable_get('millennium_sources', array()); + // Move millennium_webopac_baseurl variable into the new sources variable + $base_url = variable_get('millennium_webopac_baseurl', ''); + if ($base_url && !isset($sources[$base_url])) { + $sources[$base_url] = array('name' => ''); + } + // Add sources from all currently-imported records + $result = db_query("SELECT DISTINCT(base_url) FROM {millennium_node_bib}"); + while ($data = db_fetch_object($result)) { + if (!isset($sources[$data->base_url])) { + $sources[$data->base_url] = array('name' => ''); + } + } + // Update/create sources variable + variable_set('millennium_sources', $sources); + return $ret; +} \ No newline at end of file Index: contributions/modules/millennium/millennium.module --- contributions/modules/millennium/millennium.module Base (1.13.2.33.2.2.2.86) +++ contributions/modules/millennium/millennium.module Locally Modified (Based On 1.13.2.33.2.2.2.86) @@ -583,6 +583,16 @@ 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); + $items[MILLENNIUM_SETTINGS_PATH . '/crawl'] = array( + 'title' => 'Automatic crawl', + 'description' => 'Configure automatic crawl settings.', + 'type' => MENU_LOCAL_TASK, + 'page callback' => 'drupal_get_form', + 'page arguments' => array('millennium_admin_crawl'), + 'access callback' => 'user_access', + 'access arguments' => array('administer millennium'), + 'file' => 'millennium.admin.inc', + ); $items[MILLENNIUM_SETTINGS_PATH . '/map'] = array( 'title' => 'Taxonomy mapping', 'description' => 'Configure MARC import mapping settings.', @@ -623,6 +633,7 @@ 'type' => MENU_CALLBACK, 'file' => 'millennium.pages.inc', ); + /* TODO: make this work with a URL at the end $items['millennium/preview/%'] = array( 'title' => 'Millennium node import preview', 'page callback' => 'millennium_preview_import' , @@ -632,6 +643,7 @@ 'type' => MENU_CALLBACK, 'file' => 'millennium.pages.inc', ); + */ $items['admin/reports/millennium'] = array( 'title' => 'Millennium import statistics', @@ -647,12 +659,19 @@ 'access arguments' => array('access content'), 'file' => 'millennium.pages.inc', ); - $items['millennium_checkurl_js'] = array( + $items['millennium_checkurl_js/%'] = array( 'page callback' => 'millennium_checkurl_js', + 'page arguments' => array(1), 'type' => MENU_CALLBACK, 'access arguments' => array('administer millennium'), 'file' => 'millennium.pages.inc', ); + $items['millennium_autocomplete_js'] = array( + 'page callback' => 'millennium_autocomplete_js', + 'type' => MENU_CALLBACK, + 'access arguments' => array('administer millennium'), + 'file' => 'millennium.pages.inc', + ); $items['node/%node/millennium'] = array( 'title' => 'Millennium Tools', @@ -1111,7 +1130,7 @@ if ($data['base_url']) { $base_url = $data['base_url']; } else { - $base_url = millennium_get_real_baseurl(); + return array("success" => false, "error" => "No base_url in item #" . $data['item_recnum']); } // Had we already imported this item record? @@ -1184,7 +1203,7 @@ function millennium_process_item_record_new_import($data, $nid) { // Link item to bib, node $record = array('nid' => $nid, 'bib_recnum' => $data['bib_recnum'], 'item_recnum' => $data['item_recnum'], - 'updated' => date("Y-m-d H:i:s"), 'created' => date("Y-m-d H:i:s"), 'base_url' => millennium_get_real_baseurl()); + 'updated' => date("Y-m-d H:i:s"), 'created' => date("Y-m-d H:i:s"), 'base_url' => $data['base_url']); $result = drupal_write_record('millennium_bib_item', $record); if (!$result) { drupal_set_message("millennium_process_item_record_new_import: drupal_write_record('millennium_bib_item') returned false"); @@ -1277,7 +1296,7 @@ if ($data['base_url']) { $base_url = millennium_get_real_baseurl($data['base_url']); } else { - $base_url = millennium_get_real_baseurl(); + return array("success" => false, "error" => "Could not get bib_recnum for bib #" . $data['bib_recnum']); } $bib_import_history = db_fetch_object(db_query("SELECT * FROM {millennium_node_bib} WHERE bib_recnum='%s' AND base_url = '%s'", $data['bib_recnum'], $base_url)); @@ -1313,7 +1332,7 @@ } // Re-create a nodeobject from the MARC record - $new_node = millennium_record_to_nodeobject($data['bib_recnum'], $data['marc'], $base_url); + $new_node = millennium_record_to_nodeobject($data['bib_recnum'], $base_url, $data['marc']); if ($new_node->success === false) { #drupal_set_message("millennium_process_bib_record(): millennium_record_to_nodeobject() returned error ". $result["error"]); return array("success" => false, "error" => $new_node->error); @@ -1373,7 +1392,7 @@ if ($data['base_url']) { $base_url = $data['base_url']; } else { - $base_url = millennium_get_real_baseurl(); + return; } // Get bibrecord number and erase any existing node-item relationships @@ -1418,7 +1437,7 @@ if ($data['base_url']) { $base_url = $data['base_url']; } else { - $base_url = millennium_get_real_baseurl(); + return; } db_query("DELETE FROM {millennium_bib_item} WHERE bib_recnum='%s' AND base_url = '%s'", $data['bib_recnum'], $base_url); @@ -1448,9 +1467,8 @@ * @param recnum Millennium record number (b123456, i123456) to fetch * @param string $marc_text An optional MARC record to import from. */ -function millennium_record_to_nodeobject($recnum, $marc_text = null, $base_url = false) { +function millennium_record_to_nodeobject($recnum, $base_url, $marc_text = null) { $result = new stdClass(); - $base_url = millennium_get_real_baseurl($base_url); if ($marc_text == null) { $marc_text = millennium_fetch_marc($recnum, $base_url); if (!$marc_text) { @@ -1522,12 +1540,15 @@ // Return the node $nodeobject = (object)$node; - // Add taxonomy + // Add marc info to node's taxonomy millennium_add_taxonomy_to_node($nodeobject, $parsed_marc); - // Add availability info + // Add availability info to node's taxonomy millennium_add_availability_to_node($nodeobject, $recnum, $base_url); + // Add OPAC name to node's taxonomy + millennium_add_taxonomy_opacname_to_node($nodeobject, $base_url); + if (!$nodeobject) { $result->success = false; $result->error = "Could not create node object from parsed MARC for $recnum"; @@ -1540,14 +1561,11 @@ /** * Returns the user-defined base URL for the Millennium server (e.g. http://example.com/) */ -function millennium_get_real_baseurl($base_url = false) { - if ($base_url === false) { - $base_url = variable_get('millennium_webopac_baseurl', ''); - } - if ($base_url == '') { +function millennium_get_real_baseurl($base_url) { + if ($base_url === false || $base_url == '') { return false; } - $parts = @parse_url($base_url); + $parts = @parse_url(trim($base_url)); if (!$parts['host']) { return false; } @@ -1563,7 +1581,7 @@ * @param recnum Millennium record number (b123456, i123456) to fetch * @param mode String specifying type of view: plain, marc, items, xml */ -function millennium_fetch_recordpage($recnum, $mode = "plain", $base_url = false) { +function millennium_fetch_recordpage($recnum, $mode = "plain", $base_url) { // TODO Fix argument order global $millennium_fetch_recordpage_cache; $key = $recnum . $mode . $base_url; #drupal_set_message("millennium_fetch_recordpage($recnum, $mode): key = $key"); @@ -1590,15 +1608,7 @@ /** * Returns a URL for a certain item record view in Millennium */ -function millennium_permalink($recnum, $mode = 'plain', $base_url = false) { - if ($base_url === false) { - $base_url = millennium_get_real_baseurl(); - } - if ($base_url == false) { - return false; - } else { - $base_url = millennium_get_real_baseurl($base_url); - } +function millennium_permalink($recnum, $mode = 'plain', $base_url) { // TODO fix argument order // Determine if record is for an item or bib $recnum_type = substr($recnum, 0, 1); @@ -1613,7 +1623,7 @@ case "hold": case "items": if ($recnum_type == "i") { - $bib_recnum = db_result(db_query("SELECT bib_recnum FROM {millennium_bib_item} WHERE item_recnum='%s' AND base_url = '%s'", $recnum, millennium_get_real_baseurl())); + $bib_recnum = db_result(db_query("SELECT bib_recnum FROM {millennium_bib_item} WHERE item_recnum='%s' AND base_url = '%s'", $recnum, $base_url)); $item_recnum = $recnum; } else { $bib_recnum = $recnum; @@ -1911,7 +1921,7 @@ return; } $locations_available = array(); - $holdings = millennium_get_holdings_info($recnum, null, $base_url); + $holdings = millennium_get_holdings_info($recnum, $base_url); foreach ($holdings as $item) { if ( !variable_get('millennium_map_available_only', FALSE) @@ -1927,6 +1937,16 @@ millennium_add_node_taxonomy_terms($nodeobject, variable_get('millennium_availability_vid', -1) , $location_names); } +function millennium_add_taxonomy_opacname_to_node(&$nodeobject, $base_url) { + if (variable_get('millennium_opacname_vid', -1) == -1) { + return; + } + $sources = variable_get('millennium_sources', array()); + if (isset($sources[$base_url]) && $sources[$base_url]['name']) { + millennium_add_node_taxonomy_terms($nodeobject, variable_get('millennium_opacname_vid', -1) , array($sources[$base_url]['name'])); + } +} + /** * Helper function that eliminates trailing (nonessential) characters from MARC data */ @@ -2107,9 +2127,9 @@ // Load vocabularies if ($vocabs_vid_nodetype === FALSE) { $vocabs = taxonomy_get_vocabularies(); - foreach ($vocabs as $vid => $vocab) { - foreach ($vocab->nodes as $type) { - $vocabs_vid_nodetype[$vid][$type] = TRUE; + foreach ($vocabs as $loop_vid => $loop_vocab) { + foreach ($loop_vocab->nodes as $type) { + $vocabs_vid_nodetype[$loop_vid][$type] = TRUE; } } } @@ -2132,8 +2152,6 @@ return; } - $nid = $nodeobject->nid; - if (isset($nodeobject->taxonomy["tags"][$vid])) { $tags_this_vid = $nodeobject->taxonomy["tags"][$vid]; } else { @@ -2442,13 +2460,10 @@ * @return array * A holdings array. */ -function millennium_get_holdings_info($recnum, $fetched_html = null, $base_url = false) { +function millennium_get_holdings_info($recnum, $base_url, $fetched_html = null) { static $cache; $items = array(); - if ($base_url === false) { - $base_url = millennium_get_real_baseurl(); - } if ($fetched_html == null) { // Build a cache id @@ -2815,3 +2830,22 @@ return $result; } + +/** + * Returns a sources array populated with an extra 'node_count' element per each + * source. + * + * @return array + * A sources array derived from the millennium_sources Drupal variable + */ +function millennium_get_sources_count() { + $sources = variable_get("millennium_sources", array()); + if (sizeof($sources) > 0) { + // Build a counting query + $result = db_query('SELECT count(1) n, base_url FROM {millennium_node_bib} GROUP BY base_url'); + while ($data = db_fetch_object($result)) { + $sources[$data->base_url]['node_count'] = $data->n; + } + } + return $sources; +} \ No newline at end of file Index: contributions/modules/millennium/millennium.pages.inc --- contributions/modules/millennium/millennium.pages.inc Base (1.1.2.5) +++ contributions/modules/millennium/millennium.pages.inc Locally Modified (Based On 1.1.2.5) @@ -49,12 +49,13 @@ /** * Callback function from hook_menu to show how an millennium record would be imported */ -function millennium_preview_import($recnum) { - $output = t("You can also !link", array('!link' => l(t("import this record now"), "millennium/import/$recnum"))); - $output .= "
"; - $output .= _millennium_show_conversion($recnum); - return $output; -} +//DISABLED. See millennium_menu() callback to this function. +//function millennium_preview_import($recnum) { +// $output = t("You can also !link", array('!link' => l(t("import this record now"), "millennium/import/$recnum"))); +// $output .= "
"; +// $output .= _millennium_show_conversion($recnum); +// return $output; +//} /** * Callback function from hook_menu that shows import and conversion information for node $nid @@ -84,7 +85,7 @@ $output .= "

"; $output .= "

". t('MARC record and conversion') ."

"; - $output .= _millennium_show_conversion($bib_recnum, $node->millennium_biblio_data["marc"], $data->base_url); + $output .= _millennium_show_conversion($bib_recnum, $data->base_url, $node->millennium_biblio_data["marc"]); return $output; } @@ -139,7 +140,7 @@ else { $bib_recnum = millennium_bib_recnum_from_node($nid); $base_url = db_result(db_query("SELECT base_url FROM {millennium_node_bib} WHERE nid=%d", $nid)); - $holdings = millennium_get_holdings_info($bib_recnum, NULL, $base_url); + $holdings = millennium_get_holdings_info($bib_recnum, $base_url); $output = theme('millennium_holdings', $nid, $holdings, $page); cache_set($cid, serialize($output), 'cache', time() + 900); // 15 minutes } @@ -263,7 +264,7 @@ /** * Diagnostics to show conversion of MARC into fields for node object */ -function _millennium_show_conversion($recnum, $marc_text = false, $base_url = false) { +function _millennium_show_conversion($recnum, $base_url, $marc_text = false) { $output = ""; $base_url = millennium_get_real_baseurl($base_url); if ($base_url == false) { @@ -277,7 +278,7 @@ $marc_text_msg = t('This MARC record was just fetched from the WebOPAC.'); } - $tmp_node = millennium_record_to_nodeobject($recnum, $marc_text, $base_url); + $tmp_node = millennium_record_to_nodeobject($recnum, $base_url, $marc_text); if (!$tmp_node || !$tmp_node->millennium_biblio_data) { return t("Millennium data in node has errors and can not be displayed."); } @@ -313,11 +314,29 @@ /** * Callback function for URL checker */ -function millennium_checkurl_js() { +function millennium_checkurl_js($var_name = false) { $form_state = array('values' => $_POST); - $base_url = millennium_get_real_baseurl($form_state['values']['millennium_webopac_baseurl']); + $base_url = millennium_get_real_baseurl($form_state['values'][check_plain($var_name)]); $ok = millennium_ping($base_url); $output = $ok ? t("WebOPAC is responding normally.") : t("Not a valid WebOPAC."); $class = $ok ? "status" : "error"; drupal_json(array('status' => TRUE, 'data' => "
{$output}
")); } + +/** + * Callback function for base_url autocomplete form elements + */ +function millennium_autocomplete_js() { + $suggestions = array(); + $search_parts = explode('/', trim($_GET['q'])); + $search_string = implode('/', array_slice($search_parts, 1)); + $sources = variable_get("millennium_sources", array()); + // Look for $search_string in all sources + foreach ($sources as $base_url => $source_data) { + if (strpos($base_url, $search_string) === 0) { + $suggestions[$base_url] = $base_url; + } + } + drupal_json($suggestions); + exit; +} \ No newline at end of file Index: contributions/modules/millennium/millennium.theme.inc --- contributions/modules/millennium/millennium.theme.inc Base (1.1.2.3) +++ contributions/modules/millennium/millennium.theme.inc Locally Modified (Based On 1.1.2.3) @@ -12,6 +12,8 @@ function theme_millennium_holdings($nid, $holdings, $page = true) { static $re; + $biblio_data = millennium_get_biblio_data($nid); + // Preferred locations if (empty($re)) { $tmp = variable_get('millennium_preferred_locations', ''); @@ -61,9 +63,11 @@ } } - // Style differently + // Style differently if items are "available" according to status and + // millennium_availability_strings variable $class = "notavailable"; - if ($item['status'] == "DISPONIBLE" || $item['status'] == "AVAILABLE") { + $availability_strings = explode(',', variable_get('millennium_availability_strings', MILLENNIUM_ITEM_AVAILABLE_STRINGS)); + if (in_array($item['status'], $availability_strings)) { $class = "available"; } $shown ++; @@ -74,10 +78,20 @@ if ($item['copy']) { $classnumber_volume_copy .= ($classnumber_volume_copy ? " " : "") . $item['copy']; } + // Location + $location = $item['location']; + if (variable_get('millennium_holdings_opacname', 1)) { + // Add opacname prefix to $location + $sources = variable_get('millennium_sources', array()); + $source = $sources[$biblio_data["base_url"]]; + if ($source && $source['name']) { + $location = $source['name'] . ": " . $location; + } + } $rows[] = array( 'data' => array( array('data' => $item['status']), - array('data' => $item['location']), \ No newline at end of file + array('data' => $location), \ No newline at end of file array('data' => $classnumber_volume_copy), //array('data' => $item['message']), ), Index: contributions/modules/millennium/millennium_auth.module --- contributions/modules/millennium/millennium_auth.module Base (1.1.2.6) +++ contributions/modules/millennium/millennium_auth.module Locally Modified (Based On 1.1.2.6) @@ -2,6 +2,8 @@ // $Id: millennium_auth.module,v 1.1.2.6 2009/10/30 21:47:16 janusman Exp $ module_load_include('inc', 'millennium_auth', 'patroninfo'); +define('MILLENNIUM_AUTH_DEFAULT_PIN_MSG', 'The PIN used for renewals and other library services.'); +define('MILLENNIUM_AUTH_DEFAULT_ID_MSG', 'Enter your library card barcode.'); /** * Implementation of hook_help @@ -14,6 +16,53 @@ } /** + * Implementation of hook_menu() + */ +function millennium_auth_menu() { + $items = array(); + $items[MILLENNIUM_SETTINGS_PATH . '/authentication'] = array( + 'title' => 'Authentication', + 'description' => 'Configure authentication settings.', + 'type' => MENU_LOCAL_TASK, + 'page callback' => 'drupal_get_form', + 'page arguments' => array('millennium_auth_settings_form'), + 'access callback' => 'user_access', + 'access arguments' => array('administer millennium'), + ); + return $items; +} + +function millennium_auth_settings_form() { + $form = array(); + $form['millennium_auth_default_base_url'] = array( + '#type' => 'select', + '#title' => t('WebOPAC source to use for authentication'), + '#description' => t('Select one of the enabled sources.'), + '#default_value' => variable_get('millennium_auth_default_base_url', ''), + '#options' => drupal_map_assoc(array_merge(array(0 => t('')), array_keys(variable_get('millennium_sources', array())))), + ); + $form['millennium_auth_use_https'] = array( + '#type' => 'checkbox', + '#title' => t('Use HTTPs connection for authentication'), + '#description' => t('Note: your OPAC must have the appropriate configuration in place for this to work.'), + '#default_value' => variable_get('millennium_auth_use_https', FALSE), + ); + $form['login']['millennium_auth_id_message'] = array( + '#type' => 'textfield', + '#title' => t('Library ID field help message'), + '#description' => t('This is shown below the login form.'), + '#default_value' => variable_get('millennium_auth_id_message', t(MILLENNIUM_AUTH_DEFAULT_ID_MSG)), + ); + $form['login']['millennium_auth_pin_message'] = array( + '#type' => 'textfield', + '#title' => t('PIN field help message'), + '#description' => t('This is shown below the login form.'), + '#default_value' => variable_get('millennium_auth_pin_message', t(MILLENNIUM_AUTH_DEFAULT_PIN_MSG)), + ); + return system_settings_form($form); +} + +/** * Implementation of hook_user(). */ function millennium_auth_user($op, &$edit, &$account, $category = FALSE) { @@ -51,7 +100,7 @@ $list = array(); if (is_array($patroninfo_data["checkouts"])) { $msg = theme("millennium_auth_checkouts", $patroninfo_data["checkouts"]); - $msg .= ''. t('Renew your items') .''; + $msg .= ''. t('Renew your items') .''; } else { $msg = t('You have no checked out items.'); } @@ -123,7 +172,7 @@ $millennium_auth_newuser['username'], $millennium_auth_newuser['password'] ); - _millennium_auth_debug("millennium_auth_user($op....) : Saved new user's PIN and lastname"); + _millennium_auth_debug("millennium_auth_user($op....) : Saved new user's PIN and last name"); // Log new user watchdog( 'millennium auth', @@ -160,12 +209,12 @@ } foreach($items as $item) { // Has record been imported into Drupal? - $nid = db_result(db_query("SELECT nid FROM {millennium_bib_item} where item_recnum='%s' AND base_url = '%s'", $item["item_recnum"], millennium_get_real_baseurl())); + $nid = db_result(db_query("SELECT nid FROM {millennium_bib_item} where item_recnum='%s' AND base_url = '%s'", $item["item_recnum"], variable_get('millennium_auth_default_base_url', ''))); if ($nid) { $link = l($item["title"], "node/$nid"); } else { - $link = l($item["title"], millennium_get_real_baseurl() ."/record=". $item["item_recnum"]); + $link = l($item["title"], variable_get('millennium_auth_default_base_url', '') ."/record=". $item["item_recnum"]); } $item_html = $link ."
". t('Due date: @date', array("@date" => format_date($item["duedate_timestamp"], 'custom', 'D, m/d/Y'))); @@ -303,11 +352,22 @@ return $patroninfo_data; } + $millennium_baseurl = variable_get('millennium_auth_default_base_url', ''); + // Use HTTPs if settings indicate so. TODO make this automatic? + if (variable_get('millennium_auth_use_https', FALSE)) { + $millennium_baseurl = str_replace("http://", "https://", $millennium_baseurl); + } + // Connect to Millennium and get the patron's information - $patroninfo_data = patroninfo_start_session(millennium_get_real_baseurl(), $username, $lastname, $pin); + $patroninfo_data = patroninfo_start_session($millennium_baseurl, $username, $lastname, $pin); if ($patroninfo_data["success"] != true) { _millennium_auth_debug("_millennium_auth_get_patroninfo_by_pindata(): Error: ". $patroninfo_data["errormsg"]); + watchdog('millennium auth', + 'Connection error: @error', + array('@error' => $patroninfo_data["errormsg"]), + WATCHDOG_ERROR + ); return false; } @@ -321,8 +381,13 @@ * Implementation of hook_form_alter(). */ function millennium_auth_form_alter(&$form, &$form_state, $form_id) { - #drupal_set_message("millennium_auth_form_alter($form_id)"); + $base_url = variable_get('millennium_auth_default_base_url', 0); + // Make sure that settings are in place. + if ($base_url != 0) { + return; + } + // User edit form if ($form_id == 'user_edit') { // Prevent users from changing PIN (password) @@ -332,7 +397,7 @@ $form['account']['pass'] = array( '#title' => t('Change library PIN'), '#type' => 'item', - '#description' => l( t('Click on this link to change your library PIN'), millennium_get_real_baseurl() .'/patroninfo*eng'), + '#description' => l( t('Click on this link to change your library PIN'), "{$base_url}/patroninfo*eng"), ); } @@ -355,7 +420,7 @@ '#type' => 'textfield', '#title' => t('Your Library ID'), '#size' => 10, - '#description' => t('Enter your library card barcode.'), // TODO: Make configurable! + '#description' => check_plain(variable_get('millennium_auth_id_message', t(MILLENNIUM_AUTH_DEFAULT_ID_MSG))), '#default_value' => '', '#attributes' => array('tabindex' => 2), '#required' => 1, @@ -364,7 +429,7 @@ $form['pass']['#title'] = t('Library PIN'); $form['pass']['#size'] = 12; - $form['pass']['#description'] = t('The PIN used for renewals and other library services.'); + $form['pass']['#description'] = check_plain(variable_get('millennium_auth_pin_message', t(MILLENNIUM_AUTH_DEFAULT_PIN_MSG))); $form['pass']['#attributes'] = array('tabindex' => 3); // Add tabindex to "submit" button @@ -410,7 +475,7 @@ if (!millennium_auth_authenticate($form_state['values'])) { // Authentication failed - form_set_error('name', t('Your lastname, library ID or library PIN are incorrect.')); + form_set_error('name', t('Your last name, library ID or library PIN are incorrect.')); } }