diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 2fa5ea7..83d21af 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,7 +1,8 @@ -Apache Solr Search Integration 6.x-1.0-XXX, xxxx-xx-xx +Apache Solr Search Integration 7.x-1.0-XXX, xxxx-xx-xx ------------------------------ +#1006994 by wmostrey: Initial Drupal 7 port. Apache Solr Search Integration 6.x-1.0-RC1, xxxx-xx-xx ------------------------------ diff --git a/apachesolr_multisitesearch.admin.inc b/apachesolr_multisitesearch.admin.inc index a801f40..3eccc60 100644 --- a/apachesolr_multisitesearch.admin.inc +++ b/apachesolr_multisitesearch.admin.inc @@ -1,196 +1,18 @@ id = apachesolr_document_id(0, 'multisite_metadata'); - $document->site = url(NULL, array('absolute' => TRUE)); - $document->hash = apachesolr_site_hash(); - $document->entity = 'multisite_meta'; - $document->ss_multisite_meta_sitename = variable_get('site_name', 'Drupal'); - module_load_include('inc', 'apachesolr', 'apachesolr.index'); - if (module_exists('taxonomy')) { - $vocabs = taxonomy_get_vocabularies(); - foreach ($vocabs as $vid => $vocab) { - // We index each name as a string for cross-site faceting - // using the vocab name rather than vid in field construction. - $document->setMultiValue('sm_multisite_meta_taxonomy', apachesolr_vocab_name($vid)); - } - } - drupal_alter('apachesolr_multisitesearch_metadata', $document); - return $document; -} - -function apachesolr_multisitesearch_update_metadata() { - try { - // Get the $solr object - $solr = apachesolr_get_solr(); - $metadata_doc = apachesolr_multisitesearch_metadata(); - $solr->addDocuments(array($metadata_doc)); - watchdog('Apache Solr Multisite', 'Updated site meta data'); - return TRUE; - } - catch (Exception $e) { - watchdog('Apache Solr Multisite', 'Indexing failed for meta data
!message', - array('!message' => nl2br(strip_tags($e->getMessage()))), WATCHDOG_ERROR); - } - return FALSE; -} - -function apachesolr_multisitesearch_get_metadata() { - try { - // Get the $solr object - $solr = apachesolr_get_solr(); - $solr->setCollapseSingleValueArrays(FALSE); - $params['qt'] = 'standard'; - $params['fl'] = '*'; - $response = $solr->search('entity:multisite_meta', 0, 1000, $params); - foreach ($response->response->docs as $doc) { - // Convert doc into a simple array. - if (isset($doc->hash)) { - foreach ($doc as $k => $v) { - $data[$doc->hash][$k] = $v; - } - if (empty($data[$doc->hash]['sm_multisite_meta_taxonomy'])) { - $data[$doc->hash]['sm_multisite_meta_taxonomy'] = array(); - } - } - } - watchdog('Apache Solr Multisite', 'Fetched site meta data'); - variable_set('apachesolr_multisitesearch_metadata', $data); - } - catch (Exception $e) { - watchdog('Apache Solr Multisite', 'Failed to fetch meta data
!message', - array('!message' => nl2br(strip_tags($e->getMessage()))), WATCHDOG_ERROR); - } -} - -function apachesolr_multisitesearch_get_site_hashes() { - try { - // Get the $solr object - $solr = apachesolr_get_solr(); - $solr->setCollapseSingleValueArrays(FALSE); - $params['qt'] = 'standard'; - $params['fl'] = ''; - $params['facet'] = 'true'; - $params['facet.field'][] = 'hash'; - $params['facet.mincount'] = 1; - $params['facet.limit'] = '1000'; - $response = $solr->search('*:*', 0, 0, $params); - $results = (array)$response->facet_counts->facet_fields->hash; - return $results; - } - catch (Exception $e) { - watchdog('Apache Solr Multisite', 'Failed to fetch hash facet count
!message', - array('!message' => nl2br(strip_tags($e->getMessage()))), WATCHDOG_ERROR); - } -} - -/** - * This is the submit handler for the active facets form. - * - * The form values for each module are array filtereed to remove non-enabled items and - * stored in the variable table with the name 'apachesolr_enabled_facets'. - * - * @see apachesolr_multisitesearch_enabled_facets_form() - */ -function apachesolr_multisitesearch_enabled_facets_form_submit($form, &$form_state) { - $enabled = array(); - foreach ($form_state['values']['apachesolr_multisitesearch_enabled_facets'] as $module => $facets) { - $enabled[$module] = array_filter($facets); - } - variable_set('apachesolr_multisitesearch_enabled_facets', $enabled); - drupal_set_message($form_state['values']['submit_message'], 'warning'); -} - -/** - * Indicates what order the specified facets should be listed in. This function is used in a usort - * invocation. - * @param $a - * The first facet. - * @param $b - * The second facet. - * @return - * A signed integer that indicates which of the specified facets should come first. - */ -function _apachesolr_multisitesearch_sort_facets($a, $b) { - return strcasecmp($a['info'], $b['info']); -} - -/** * Creates the form that allows the user to select which facets will be enabled. * * Only enabled facets are sent to solr. Fewer enabled facets can reduce the * load on the search server. Blocks are only offered for enabled facets, so * this also reduces the clutter on the blocks admin page. */ -function apachesolr_multisitesearch_enabled_facets_form() { - $form = array(); - $facets = array(); - $module_facets = array(); - $module_list = array(); - - foreach (module_implements('apachesolr_multisitesearch_facets') as $module) { - $module_facets[$module] = module_invoke($module, 'apachesolr_multisitesearch_facets', TRUE); - uasort($module_facets[$module], '_apachesolr_multisitesearch_sort_facets'); - $module_list[$module] = $module; - } - - $enabled_facets = apachesolr_multisitesearch_enabled_facets(); +function apachesolr_multisitesearch_settings() { $form = array(); - $form['apachesolr_multisitesearch_enabled_facets']['help'] = array ( - '#type' => 'item', - '#value' => t('You can use this screen to select which search filter blocks should be created by enabling the corresponding filters on this page. For performance reasons, you should only enable filters that you intend to have available to users on the search page. After selecting which filter blocks to create, you will be sent to the blocks page where you can choose which of those blocks should be enabled when your users search by placing each block in a region.'), - ); - if ($module_list) { - $placeholders = implode(', ', array_fill(0, count($module_list), "'%s'")); - $result = db_query("SELECT name, info FROM {system} WHERE name IN (". $placeholders .") AND type = 'module'", $module_list); - while ($item = db_fetch_array($result)) { - $module_list[$item['name']] = unserialize($item['info']); - } - } - foreach($module_facets as $module => $facets) { - $form['apachesolr_multisitesearch_enabled_facets'][$module] = array( - '#type' => 'fieldset', - '#title' => check_plain($module_list[$module]['name']), - '#collapsible' => TRUE, - '#collapsed' => FALSE, - ); - // We must use module + delta as the keys since that combination is - // guaranteed to be unique. A single module could, for example, have - // two different blocks that expose different faceting on the same - // field in the index. - foreach($facets as $delta => $data) { - $form['apachesolr_multisitesearch_enabled_facets'][$module][$delta] = array( - '#type' => 'checkbox', - '#title' => $data['info'], - '#return_value' => $data['facet_field'], - '#default_value' => isset($enabled_facets[$module][$delta]) ? $data['facet_field'] : 0, - ); - } - } - - $has_facets = (bool)$module_facets; - - $form['submit'] = array( - '#type' => 'submit', - '#value' => t('Save'), - '#access' => $has_facets, - ); - $form['no-facets-message'] = array( - '#value' => t('No filters are available from your currently enabled modules'), - '#access' => !$has_facets, - ); - - $form['#tree'] = TRUE; $form['submit_message'] = array( '#type' => 'value', - '#value' => t('The Apache Solr Multisite Search filter settings were changed. To arrange the blocks for your enabled filters, visit the blocks administration page.', array('@url' => url('admin/build/block'))), + '#value' => t('The Apache Solr Multisite Search filter settings were changed. To arrange the blocks for your enabled filters, visit the blocks administration page.', array('@url' => url('admin/structure/block'))), ); $form['admin'] = array( '#type' => 'fieldset', @@ -202,7 +24,7 @@ function apachesolr_multisitesearch_enabled_facets_form() { '#prefix' => '

' . t('Multisite metadata is used to communicate between all of the sites in a multisite setup. If site names are not showing properly in the search results and facet blocks try refreshing the metadata. Metadata is also refreshed periodically on cron runs.') . '

', '#submit' => array('apachesolr_multisitesearch_refresh_metadata_now'), ); - + // Use the metadata and a list of all the hashes in the index // to build up checkboxes for deleting site indexes. // This is only necessary because sometimes hashes get @@ -210,6 +32,7 @@ function apachesolr_multisitesearch_enabled_facets_form() { // admin screen doesn't rectify the problem. $metadata = variable_get('apachesolr_multisitesearch_metadata', array()); $hashes = apachesolr_multisitesearch_get_site_hashes(); + $options = array(); foreach ($hashes as $hash => $count) { if ($hash == apachesolr_site_hash()) { $options[$hash] = t('This site (!site, !count documents)', array('!site' => variable_get('site_name', 'Drupal'), '!count' => $count)); @@ -221,7 +44,7 @@ function apachesolr_multisitesearch_enabled_facets_form() { $options[$hash] = $hash . ' ' . t('(!count documents)', array('!count' => $count)); } } - + if (count($options) > 0) { $form['admin']['delete']['hashes'] = array( '#type' => 'checkboxes', @@ -244,20 +67,20 @@ function apachesolr_multisitesearch_enabled_facets_form() { function apachesolr_multisitesearch_delete_indexes($form, &$form_state) { // Instantiate a new Solr object. $solr = apachesolr_get_solr(); + $env_id = apachesolr_default_environment(); foreach ($form_state['values']['admin']['delete']['hashes'] as $hash) { if ($hash) { $query = "hash:$hash"; $solr->deleteByQuery($query); drupal_set_message(t('The index for !hash has been deleted.', array('!hash' => $hash))); if (apachesolr_site_hash() == $hash) { - // Rebuild our node-tracking table. - apachesolr_rebuild_index_table(); - apachesolr_index_updated(time()); + //Todo : we might want to execute apachesolr_node_check_index_table(); + apachesolr_set_last_index_updated($env_id, time()); } } } $solr->commit(); - apachesolr_multisitesearch_get_metadata(); + apachesolr_multisitesearch_retrieve_metadata(); } /** @@ -268,75 +91,4 @@ function apachesolr_multisitesearch_refresh_metadata_now() { variable_del('apachesolr_multisitesearch_last_metadata_fetch'); apachesolr_multisitesearch_refresh_metadata(); drupal_set_message(t('The metadata has been refreshed.')); -} - -function apachesolr_multisitesearch_rebuild_facets() { - $facets = array(); - - $facets['type'] = array( - 'info' => t('Apache Solr Multisite Search: Filter by content type'), - 'facet_field' => 'type', - ); - - $facets['sname'] = array( - 'info' => t('Apache Solr Multisite Search: Filter by author'), - 'facet_field' => 'sname', - ); - - $facets['changed'] = array( - 'info' => t('Apache Solr Multisite Search: Filter by updated date'), - 'facet_field' => 'changed', - ); - $facets['created'] = array( - 'info' => t('Apache Solr Multisite Search: Filter by post date'), - 'facet_field' => 'created', - ); - $facets['hash'] = array( - 'info' => t('Apache Solr Multisite Search: Filter by site'), - 'facet_field' => 'hash', - ); - $this_site_hash = apachesolr_site_hash(); - // Get taxonomy vocabulary facets. - // @todo - use meta data also/instead. - if (module_exists('taxonomy')) { - module_load_include('inc', 'apachesolr', 'apachesolr.index'); - $data = variable_get('apachesolr_multisitesearch_metadata', array()); - $taxo = array(); - foreach ($data as $hash => $site) { - if ($hash == $this_site_hash) { - continue; - } - foreach ($site['sm_multisite_meta_taxonomy'] as $name) { - $delta = 'sm_vid_'. $name; - $taxo[$delta]['name'] = $name; - $taxo[$delta]['sites'][] = $site['ss_multisite_meta_sitename']; - } - } - $vocabs = taxonomy_get_vocabularies(); - foreach ($vocabs as $vid => $vocab) { - // In this case the delta and facet field are the same. - $delta = 'sm_vid_'. apachesolr_vocab_name($vid); - $name = $vocab->name; - if (isset($taxo[$delta])) { - $name .= t(' (this site and !sites)', array('!sites' => implode(', ', $taxo[$delta]['sites']))); - unset($taxo[$delta]); - } - $facets[$delta] = array( - 'info' => t('Apache Solr Multisite Search: Filter by taxonomy @name', array('@name' => $name)), - 'facet_field' => $delta, - ); - } - if (variable_get('apachesolr_multisitesearch_include_remote_taxonomies', TRUE)) { - // Handle taxonomies only present at other sites. - foreach ($taxo as $delta => $data) { - $name = $data['name'] . ' (' . implode(', ', $data['sites']) . ')'; - $facets[$delta] = array( - 'info' => t('Apache Solr Multisite Search: Filter by taxonomy @name', array('@name' => $name)), - 'facet_field' => $delta, - ); - } - } - } - cache_set('apachesolr_multisitesearch:facets', $facets, 'cache_apachesolr'); - return $facets; -} +} \ No newline at end of file diff --git a/apachesolr_multisitesearch.info b/apachesolr_multisitesearch.info index 30629c7..773d02c 100644 --- a/apachesolr_multisitesearch.info +++ b/apachesolr_multisitesearch.info @@ -2,5 +2,5 @@ name = Apache Solr Multisite Search description = Search across multiple sites with Solr dependencies[] = apachesolr dependencies[] = apachesolr_search -package = Apache Solr -core = "6.x" +package = Search Toolkit +core = "6.x" \ No newline at end of file diff --git a/apachesolr_multisitesearch.module b/apachesolr_multisitesearch.module index b075b3b..d177d5f 100644 --- a/apachesolr_multisitesearch.module +++ b/apachesolr_multisitesearch.module @@ -6,412 +6,284 @@ */ /** - * Implementation of hook_menu(). + * Implements hook_menu(). */ function apachesolr_multisitesearch_menu() { $items = array(); $items['admin/settings/apachesolr/multisite-filters'] = array( - 'title' => 'Multisite filters', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('apachesolr_multisitesearch_enabled_facets_form'), - 'weight' => -6, - 'access arguments' => array('administer search'), - 'file' => 'apachesolr_multisitesearch.admin.inc', - 'type' => MENU_LOCAL_TASK, + 'title' => 'Multisite', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('apachesolr_multisitesearch_settings'), + 'weight' => -8, + 'access arguments' => array('administer search'), + 'file' => 'apachesolr_multisitesearch.admin.inc', + 'type' => MENU_LOCAL_TASK, ); return $items; } /** - * Implementation of hook_menu_alter(). + * Implements hook_form_FROM_ID_alter(). */ -function apachesolr_multisitesearch_menu_alter(&$menu) { - if (isset($menu['search/apachesolr_multisitesearch/%menu_tail'])) { - $menu['search/apachesolr_multisitesearch/%menu_tail']['page callback'] = 'apachesolr_search_view'; - } +function apachesolr_multisitesearch_form_apachesolr_environment_edit_form_alter(&$form, &$form_state) { + + $environment = $form['#parameters'][2]; + $is_multisite = apachesolr_environment_variable_get($environment['env_id'], 'multisitesearch'); + $form['make_multisite'] = array( + '#type' => 'checkbox', + '#title' => t('Make this Solr search environment multisite capable'), + '#default_value' => $is_multisite, + '#weight' => 1, + ); + $form['actions']['#weight'] = 2; + $form['actions']['save']['#submit'][] = 'apachesolr_multisitesearch_environment_edit_submit'; } /** - * Implementation of hook_cron(). + * Submit callback for saving an environment to make it multisite capabe */ -function apachesolr_multisitesearch_cron() { - apachesolr_multisitesearch_refresh_metadata(); +function apachesolr_multisitesearch_environment_edit_submit($form, &$form_state) { + // Enable or disable multisite + apachesolr_environment_variable_set($form_state['values']['env_id'], 'multisitesearch', $form_state['values']['make_multisite']); } -function apachesolr_multisitesearch_refresh_metadata() { - // Update meta data 1x per hour max. - // Fetch meta data 1x per 5 minutes max. - // TODO - make these intervals controllable. - $last_update = variable_get('apachesolr_multisitesearch_last_metadata_update', 0); - $last_fetch = variable_get('apachesolr_multisitesearch_last_metadata_fetch', 0); - $time = time(); - module_load_include('inc', 'apachesolr_multisitesearch', 'apachesolr_multisitesearch.admin'); - if ($time - $last_update > 60*60) { - if (apachesolr_multisitesearch_update_metadata()) { - variable_set('apachesolr_multisitesearch_last_metadata_update', $time); - } - } - if ($time - $last_fetch > 60*5) { - apachesolr_multisitesearch_get_metadata(); - } - apachesolr_index_updated($time); -} /** - * Implementation of hook_search() + * Implements hook_facetapi_facet_info(). + * + * @param type $searcher_info + * @return type */ -function apachesolr_multisitesearch_search($op = 'search', $keys = NULL) { - - switch ($op) { - case 'name': - return t('Multi-site search'); - - case 'reset': - return; +function apachesolr_multisitesearch_facetapi_facet_info($searcher_info) { + $facets = array(); + $facets['hash'] = array( + 'label' => t('Site'), + 'description' => t('Filter by Site.'), + 'field' => 'hash', + 'map callback' => 'apachesolr_multisitesearch_map_hash', + ); + return $facets; +} - case 'status': - return; +function apachesolr_multisitesearch_map_hash() { + $data = variable_get('apachesolr_multisitesearch_metadata', array()); + foreach ($data as $key => $value) { + $data[$key] = $value['ss_multisite_meta_sitename']; + } + return $data; +} - case 'search': - $filters = isset($_GET['filters']) ? $_GET['filters'] : ''; - $solrsort = isset($_GET['solrsort']) ? $_GET['solrsort'] : ''; - $page = isset($_GET['page']) ? $_GET['page'] : 0; - try { - $results = apachesolr_multisitesearch_execute($keys, $filters, $solrsort, 'search/' . arg(1), $page); - return $results; - } - catch (Exception $e) { - watchdog('Apache Solr Multisite', nl2br(check_plain($e->getMessage())), NULL, WATCHDOG_ERROR); - } - break; - } // switch +function apachesolr_multisitesearch_apachesolr_process_results(&$results, DrupalSolrQueryInterface $query) { + $env_id = $query->solr('getId'); + if (apachesolr_environment_variable_get($env_id, 'multisitesearch')) { + foreach ($results as $id => $result) { + $results[$id]['extra']['hash'] = theme('apachesolr_multisitesearch_breadcrumb_hash', array('hash' => $results[$id]['fields']['hash'])); + $results[$id]['link'] = $results[$id]['fields']['url']; + } + } } -/** - * Implementation of hook_apachesolr_process_results() - */ -function apachesolr_multisitesearch_apachesolr_process_results(&$results, $namespace = FALSE) { - if ($namespace == 'apachesolr_multisitesearch') { - foreach ($results as $key => $result) { - $results[$key]['extra'][] = theme('apachesolr_breadcrumb_hash', $result['node']->hash); +function apachesolr_multisitesearch_apachesolr_query_alter(DrupalSolrQueryInterface $query) { + if (empty($query->multisite)) { + $env_id = $query->solr('getId'); + $multisite = apachesolr_environment_variable_get($env_id, 'multisitesearch'); + if (empty($multisite)) { + // Limit single site searchs via the site hash. + $query->addFilter('hash', apachesolr_site_hash()); + //'url', 'is_uid', 'tos_name', 'site', 'hash' } } } /** - * Execute a search results based on keyword, filter, and sort strings. + * Allows a module to modify the delete query. * - * @throws Exception + * @param string $query + * Defaults to *:* */ -function apachesolr_multisitesearch_execute($keys, $filters, $solrsort, $base_path = '', $page = 0, $caller = 'apachesolr_multisitesearch') { - - $params = array(); - // This is the object that knows about the query coming from the user. - $query = apachesolr_drupal_query($keys, $filters, $solrsort, $base_path); - if (empty($query)) { - throw new Exception(t('Could not construct a Solr query in function apachesolr_search_search()')); - } - $query->multisite = TRUE; - // This is the object that does the communication with the solr server. - $solr = apachesolr_get_solr(); - $params += apachesolr_multisitesearch_basic_params($query); - if ($keys) { - $params += apachesolr_search_highlighting_params($query); - $params += apachesolr_search_spellcheck_params($query); +function hook_apachesolr_delete_by_query_alter($query) { + // use the site hash so that you only delete this site's content + if ($query == '*:*') { + $query = 'hash:' . apachesolr_site_hash(); } else { - // No highlighting, use the teaser as a snippet. - $params['fl'] .= ',teaser'; - } - apachesolr_multisitesearch_add_facet_params($params, $query); - apachesolr_search_add_boost_params($params, $query, $solr); - - // Allow modules to alter the query prior to statically caching it. - // This can e.g. be used to add available sorts. - foreach (module_implements('apachesolr_prepare_query') as $module) { - $function_name = $module . '_apachesolr_prepare_query'; - $function_name($query, $params, $caller); - } - - // Cache the built query. Since all the built queries go through - // this process, all the hook_invocations will happen later - $current_query = apachesolr_current_query($query); - - // This hook allows modules to modify the query and params objects. - apachesolr_modify_query($query, $params, $caller); - $params['start'] = $page * $params['rows']; - - if (!$query) { - return array(); + $query = "($query) AND hash:" . apachesolr_site_hash(); } - - if (('' == $keys) && isset($params['fq'])) { - // Move the fq params to the q.alt for better performance. - $params['q.alt'] = implode(' ', $params['fq']); - unset($params['fq']); - } - - // We must run htmlspecialchars() here since converted entities are in the index. - // and thus bare entities &, > or < won't match. - $response = $solr->search(htmlspecialchars($query->get_query_basic(), ENT_NOQUOTES, 'UTF-8'), $params['start'], $params['rows'], $params); - // The response is cached so that it is accessible to the blocks and anything - // else that needs it beyond the initial search. - apachesolr_static_response_cache($response); - apachesolr_multisitesearch_has_searched(TRUE); - // Add search terms and filters onto the breadcrumb. - drupal_set_breadcrumb(array_merge(menu_get_active_breadcrumb(), $current_query->get_breadcrumb())); - return apachesolr_multisitesearch_process_response($response, $query, $params); } -function apachesolr_multisitesearch_add_facet_params(&$params, $query) { - $facet_query_limits = variable_get('apachesolr_facet_query_limits', array()); - $facet_missing = variable_get('apachesolr_facet_missing', array()); - foreach (apachesolr_multisitesearch_enabled_facets() as $module => $module_facets) { - if (!module_exists($module)) { - // When modules are disabled their facet settings may remain. - continue; - } - foreach($module_facets as $delta => $facet_field) { - // TODO: generalize handling of date and range facets. - if (($facet_field == 'created' || $facet_field == 'changed')) { - list($start, $end, $gap) = apachesolr_search_date_range($query, $facet_field); - if ($gap) { - $params['facet.date'][] = $facet_field; - $params['f.'. $facet_field .'.facet.date.start'] = $start; - $params['f.'. $facet_field .'.facet.date.end'] = $end; - $params['f.'. $facet_field .'.facet.date.gap'] = $gap; - } - } - else { - $params['facet.field'][] = $facet_field; - // Facet limits - if (isset($facet_query_limits[$module][$delta])) { - $params['f.' . $facet_field . '.facet.limit'] = $facet_query_limits[$module][$delta]; - } - // Facet missing - if (!empty($facet_missing[$module][$delta])) { - $params['f.' . $facet_field . '.facet.missing'] = 'true'; - } - } +function apachesolr_multisitesearch_refresh_metadata() { + // Update meta data 1x per hour max. + // Fetch meta data 1x per 5 minutes max. + // TODO - make these intervals controllable. + $last_update = variable_get('apachesolr_multisitesearch_last_metadata_update', 0); + $last_fetch = variable_get('apachesolr_multisitesearch_last_metadata_fetch', 0); + $time = time(); + if ($time - $last_update > 60*60) { + if (apachesolr_multisitesearch_update_metadata()) { + variable_set('apachesolr_multisitesearch_last_metadata_update', $time); } } - - if (!empty($params['facet.field'])) { - // Add a default limit for fields where no limit was set. - $params['facet.limit'] = variable_get('apachesolr_facet_query_limit_default', 20); + if ($time - $last_fetch > 60*5) { + apachesolr_multisitesearch_retrieve_metadata(); } + $env_id = apachesolr_default_environment(); + apachesolr_set_last_index_updated($env_id, $time); } -function apachesolr_multisitesearch_has_searched($set = NULL) { - static $searched = FALSE; - if (isset($set)) { - $searched = !empty($set); - } - return $searched; +/** + * Implements hook_cron(). + */ +function apachesolr_multisitesearch_cron() { + apachesolr_multisitesearch_refresh_metadata(); } /** - * Implementation of hook_apachesolr_modify_query(). + * Create a document to send to the index that contains useful information + * regarding the website. + * @return ApacheSolrDocument */ -function apachesolr_multisitesearch_apachesolr_modify_query(&$query, &$params, $caller) { - if (empty($query->multisite)) { - // Limit single site searchs via the site hash. - $query->add_filter('hash', apachesolr_site_hash()); +function apachesolr_multisitesearch_generate_metadata() { + $document = new ApacheSolrDocument(); + $document->id = apachesolr_document_id(1, 'multisite.metadata'); + $document->site = url(NULL, array('absolute' => TRUE)); + $document->hash = apachesolr_site_hash(); + $document->entity_id = 1; + $document->entity_type = 'multisite.meta'; + $document->ss_multisite_meta_sitename = variable_get('site_name', 'Drupal'); + + // Only refresh for the default environment + $env_id = apachesolr_default_environment(); + + // Add bundle information to our metadata + // We index each name as a string for cross-site faceting + foreach (content_types() as $bundle => $bundle_info) { + if (!empty($bundle_info['extra']['apachesolr']['index'])) { + $document->setMultiValue('sm_multisite_meta_bundles', $bundle_info['name']); + } } -} -function apachesolr_multisitesearch_basic_params($query) { - $params = array( - 'fl' => 'id,nid,title,comment_count,type,type_name,entity,created,changed,score,url,uid,name,site,hash', - 'rows' => variable_get('apachesolr_rows', 10), - 'facet' => 'true', - 'facet.mincount' => 1, - 'facet.sort' => 'true' - ); - return $params; + // Add taxonomy to our metadata + if (module_exists('taxonomy')) { + module_load_include('inc', 'apachesolr', 'apachesolr.index'); + $vocabs = taxonomy_get_vocabularies(); + foreach ($vocabs as $vid => $vocab) { + // We index each name as a string for cross-site faceting + // using the vocab name rather than vid in field construction. + $document->setMultiValue('sm_multisite_meta_taxonomy', apachesolr_vocab_name($vid)); + } + } + // Allow alterations to this meta data + drupal_alter('apachesolr_multisitesearch_metadata', $document); + return $document; } -function apachesolr_multisitesearch_process_response($response, $query, $params) { - $results = array(); - // We default to getting snippets from the body. - $hl_fl = is_null($params['hl.fl']) ? 'body' : $params['hl.fl']; - $total = $response->response->numFound; - apachesolr_pager_init($total, $params['rows']); - if ($total > 0) { +function apachesolr_multisitesearch_retrieve_metadata() { + try { + // Get the $solr object + $solr = apachesolr_get_solr(); + $params['qt'] = 'standard'; + $params['fl'] = '*'; + $response = $solr->search('entity_type:multisite.meta', $params); foreach ($response->response->docs as $doc) { - $extra = array(); - - // Find the nicest available snippet. - if (isset($response->highlighting->{$doc->id}->$hl_fl)) { - $snippet = theme('apachesolr_search_snippets', $doc, $response->highlighting->{$doc->id}->$hl_fl); - } - elseif (isset($doc->teaser)) { - $snippet = theme('apachesolr_search_snippets', $doc, array(truncate_utf8($doc->teaser, 256, TRUE))); - } - else { - $snippet = ''; - } - - if (!isset($doc->body)) { - $doc->body = $snippet; + // Convert doc into a simple array. + if (isset($doc->hash)) { + foreach ($doc as $k => $v) { + $data[$doc->hash][$k] = $v; + } + if (empty($data[$doc->hash]['sm_multisite_meta_taxonomy'])) { + $data[$doc->hash]['sm_multisite_meta_taxonomy'] = array(); + } + if (empty($data[$doc->hash]['sm_multisite_meta_bundles'])) { + $data[$doc->hash]['sm_multisite_meta_bundles'] = array(); + } } - $doc->created = strtotime($doc->created); - $doc->changed = strtotime($doc->changed); - // Allow modules to alter each document. - drupal_alter('apachesolr_search_result', $doc); - // Copy code from comment_nodeapi(). - $extra[] = format_plural($doc->comment_count, '1 comment', '@count comments'); - $results[] = array( - 'link' => $doc->url, - 'type' => $doc->type_name, - // template_preprocess_search_result() runs check_plain() on the title - // again. Decode to correct the display. - 'title' => htmlspecialchars_decode($doc->title, ENT_QUOTES), - 'user' => theme('apachesolr_multisitesearch_username', $doc), - 'date' => $doc->created, - 'node' => $doc, - 'extra' => $extra, - 'score' => $doc->score, - 'snippet' => $snippet, - ); - } - - // Hook to allow modifications of the retrieved results - foreach (module_implements('apachesolr_process_results') as $module) { - $function = $module .'_apachesolr_process_results'; - // 2nd param is a namespace for those modules which might use it. - $function($results, 'apachesolr_multisitesearch'); } + watchdog('Apache Solr Multisite', 'Fetched site meta data'); + variable_set('apachesolr_multisitesearch_metadata', $data); + } + catch (Exception $e) { + watchdog('Apache Solr Multisite', 'Failed to fetch meta data
!message', + array('!message' => nl2br(strip_tags($e->getMessage()))), WATCHDOG_ERROR); } - return $results; } /** - * Implementation of hook_block(). + * Creation of update of the metadata + * @return type */ -function apachesolr_multisitesearch_block($op = 'list', $delta = 0, $edit = array()) { - switch ($op) { - case 'list': - $enabled_facets = apachesolr_multisitesearch_enabled_facets('apachesolr_multisitesearch'); - $facets = apachesolr_multisitesearch_apachesolr_multisitesearch_facets(); - // Add the blocks - $blocks = array(); - foreach ($enabled_facets as $delta => $facet_field) { - if (isset($facets[$delta])) { - $blocks[$delta] = $facets[$delta] + array('cache' => BLOCK_CACHE_PER_PAGE,); - } - } - $blocks['currentsearch'] = array( - 'info' => t('Apache Solr Multisite Search: Current search'), - 'cache' => BLOCK_CACHE_PER_PAGE, - ); - return $blocks; - - case 'view': - if (apachesolr_multisitesearch_has_searched()) { - // Get the query and response. Without these no blocks make sense. - $response = apachesolr_static_response_cache(); - if (empty($response)) { - return; - } - $query = apachesolr_current_query(); - switch ($delta) { - case 'currentsearch': - return apachesolr_multisitesearch_currentsearch($response, $query); - case 'sname': - return apachesolr_facet_block($response, $query, 'apachesolr_multisitesearch', $delta, $delta, t('Filter by author')); - case 'type': - return apachesolr_facet_block($response, $query, 'apachesolr_multisitesearch', $delta, $delta, t('Filter by type'), 'apachesolr_search_get_type'); - case 'changed': - return apachesolr_date_facet_block($response, $query, 'apachesolr_multisitesearch', $delta, $delta, t('Filter by modification date')); - case 'created': - return apachesolr_date_facet_block($response, $query, 'apachesolr_multisitesearch', $delta, $delta, t('Filter by post date')); - case 'hash': - return apachesolr_facet_block($response, $query, 'apachesolr_multisitesearch', $delta, $delta, t('Filter by site'), 'theme_apachesolr_breadcrumb_hash'); - } - } - break; - - case 'configure': - if ($delta != 'currentsearch') { - return apachesolr_facetcount_form('apachesolr_multisitesearch', $delta); - } - break; - - case 'save': - if ($delta != 'currentsearch') { - apachesolr_facetcount_save($edit); - } - break; +function apachesolr_multisitesearch_update_metadata() { + try { + // Get the $solr object + $solr = apachesolr_get_solr(); + $metadata_doc = apachesolr_multisitesearch_generate_metadata(); + $solr->addDocuments(array($metadata_doc)); + $solr->commit(); + watchdog('Apache Solr Multisite', 'Updated site meta data'); + return TRUE; } + catch (Exception $e) { + watchdog('Apache Solr Multisite', 'Indexing failed for meta data
!message', + array('!message' => nl2br(strip_tags($e->getMessage()))), WATCHDOG_ERROR); + } + return FALSE; } -function apachesolr_multisitesearch_currentsearch($response, $query) { - $fields = $query->get_filters(); - $path = $query->get_path(); - $options = array(); - if (!$fields) { - $options['attributes']['class'] = 'active'; +function apachesolr_multisitesearch_delete_metadata($hash = NULL) { + try { + // Get the $solr object + $solr = apachesolr_get_solr(); + if (empty($hash)) { + $query = "entity_type:multisite.meta"; } - $links[] = apachesolr_l($query->get_query_basic(), $path, $options); - foreach($fields as $field) { - if ($field['#name']) { - $new_query = clone $query; - $new_query->remove_filter($field['#name'], $field['#value']); - $options['query'] = $new_query->get_url_queryvalues(); - $fielddisplay = theme("apachesolr_breadcrumb_". $field['#name'], $field['#value']); - if (!$fielddisplay) { - $fielddisplay = $field['#value']; - } - $links[] = theme('apachesolr_unclick_link', $fielddisplay, $new_query->get_path(), $options); - } + else { + $query = "hash:$hash AND entity_type:multisite.meta"; } - $content = theme('apachesolr_currentsearch', $response->response->numFound, $links); - return array('subject' => t('Current search'), 'content' => $content); -} - -function apachesolr_multisitesearch_enabled_facets($module = NULL) { - $facets = variable_get('apachesolr_multisitesearch_enabled_facets', array('apachesolr_multisitesearch' => array())); - if (isset($module)) { - return isset($facets[$module]) ? $facets[$module] : array(); + $solr->deleteByQuery($query); + watchdog('Apache Solr Multisite', 'Removed meta data from the index'); + return TRUE; } - return $facets; + catch (Exception $e) { + watchdog('Apache Solr Multisite', 'Removing meta data failed.
!message', + array('!message' => nl2br(strip_tags($e->getMessage()))), WATCHDOG_ERROR); + } + return FALSE; } -/** - * Implementation of hook_apachesolr_multisitesearch_facets(). - * - * Returns an array keyed by block delta. - */ -function apachesolr_multisitesearch_apachesolr_multisitesearch_facets($rebuild = FALSE) { - if (!$rebuild) { - $cache = cache_get('apachesolr_multisitesearch:facets', 'cache_apachesolr'); - if (isset($cache->data)) { - return $cache->data; - } +function apachesolr_multisitesearch_get_site_hashes() { + try { + // Get the $solr object + $solr = apachesolr_get_solr(); + $params['qt'] = 'standard'; + $params['fl'] = '*'; + $params['facet'] = 'true'; + $params['facet.field'][] = 'hash'; + $params['facet.mincount'] = 1; + $params['facet.limit'] = '1000'; + $response = $solr->search('*:*', $params); + $results = (array)$response->facet_counts->facet_fields->hash; + return $results; + } + catch (Exception $e) { + watchdog('Apache Solr Multisite', 'Failed to fetch hash facet count
!message', + array('!message' => nl2br(strip_tags($e->getMessage()))), WATCHDOG_ERROR); } - module_load_include('inc', 'apachesolr_multisitesearch', 'apachesolr_multisitesearch.admin'); - return apachesolr_multisitesearch_rebuild_facets(); } - /** - * Implementation of hook_theme(). + * Implements hook_theme(). */ function apachesolr_multisitesearch_theme() { return array( - 'apachesolr_multisitesearch_username' => array( - 'arguments' => array('doc' => NULL), - ), - 'apachesolr_breadcrumb_hash' => array( - 'arguments' => array('hash' => NULL, 'exclude' => FALSE), + 'apachesolr_multisitesearch_breadcrumb_hash' => array( + 'variables' => array('hash' => NULL, 'exclude' => FALSE), ), ); } -function theme_apachesolr_breadcrumb_hash($hash, $exclude = FALSE) { +function theme_apachesolr_multisitesearch_breadcrumb_hash($variables) { + $hash = $variables['hash']; static $meta; if (!isset($meta)) { $meta = variable_get('apachesolr_multisitesearch_metadata', array()); @@ -424,42 +296,3 @@ function theme_apachesolr_breadcrumb_hash($hash, $exclude = FALSE) { } return $hash; } - -/** - * Modified username theme function. - * - * @see theme_username() - */ -function theme_apachesolr_multisitesearch_username($doc) { - - if ($doc->name) { - // Shorten the name when it is too long or it will break many tables. - if (drupal_strlen($doc->name) > 20) { - $name = drupal_substr($doc->name, 0, 15) .'...'; - } - else { - $name = $doc->name; - } - - // Only make links for local users. - if ($doc->uid && apachesolr_site_hash() == $doc->hash && user_access('access user profiles')) { - $output = l($name, 'user/'. $doc->uid, array('attributes' => array('title' => t('View user profile.')))); - } - else { - $output = check_plain($name); - } - } - else { - $output = check_plain(variable_get('anonymous', t('Anonymous'))); - } - - return $output; -} - -/** - * Implementation of hook_apachesolr_delete_index_alter() - */ -function apachesolr_multisitesearch_apachesolr_delete_index_alter(&$query) { - // Limit to the current site. - $query = "($query) AND hash:" . apachesolr_site_hash(); -}