'Project summary', 'description' => '', 'page callback' => 'project_solr_browse_summary_page', 'access arguments' => array('access content'), 'type' => MENU_NORMAL_ITEM, ); $items['project/%'] = array( 'title' => 'Project summary', 'description' => '', 'page callback' => 'project_solr_browse_page', 'page arguments' => array(1), 'access arguments' => array('access content'), 'type' => MENU_NORMAL_ITEM, ); return $items; } /** * Implementation of hook_theme(). */ function project_solr_theme() { return array( 'project_solr_no_count_facet_link' => array( 'arguments' => array( 'facet_text' => NULL, 'path' => '', 'options' => '', 'active' => FALSE, 'num_found' => NULL, ), ), ); } /** * Implementation of hook_nodeapi(). * * Whenever a release node is edited or submitted, if the node is now * published, reindex the project node associated with that release. */ function project_solr_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { switch ($op) { case 'update': case 'insert': if ($node->type == 'project_release' && $node->status) { apachesolr_mark_node($node->project_release['pid']); } break; } } /** * Implementation of hook_form_alter(). */ function project_solr_form_apachesolr_delete_index_form_alter(&$form, $form_state) { $form['reindex_project'] = array( '#type' => 'submit', '#value' => t('Re-index all projects'), '#submit' => array('project_solr_reindex_projects'), ); $form['reindex_project_desc'] = array( '#type' => 'item', '#description' => t('This will only re-index the project content on your site.'), ); } function project_solr_reindex_projects($form, $form_state) { db_query("UPDATE {apachesolr_search_node} SET changed = %d WHERE nid IN (SELECT nid FROM {node} WHERE type = 'project_project')", time()); drupal_set_message(t('Marked all project content to be reindexed by Apache Solr.')); } //---------------------------------------- // Solr-related hooks //---------------------------------------- /** * Implementation of hook_apachesolr_update_index(). * * This adds information about releases for the project to the Solr document * so we can facet on releases (API compatibility terms, usage, etc), along * with other project-specific metadata (e.g. shortname/uri). * * Beware that this hook is invoked for all nodes, so we should be careful in * here to check that we're really dealing with a project node before trying * to access any project-specifc data. */ function project_solr_apachesolr_update_index(&$document, $node) { if (!empty($node->project['uri'])) { $document->ss_project_uri = $node->project['uri']; } if (module_exists('project_release') && !empty($node->project_release['releases'])) { $document->is_project_has_releases = 1; $max_filetime = 0; $max_official_filetime = 0; $term_query = db_query("SELECT DISTINCT(tn.tid) FROM {node} n INNER JOIN {project_release_nodes} prn ON n.nid = prn.nid INNER JOIN {term_node} tn ON n.nid = tn.nid INNER JOIN {term_data} td ON tn.tid = td.tid WHERE prn.pid = %d AND td.vid = %d", $node->nid, _project_release_get_api_vid()); while ($term = db_fetch_object($term_query)) { $document->setMultiValue('im_project_release_api_tids', $term->tid); $latest_activity = db_fetch_object(db_query_range("SELECT f.timestamp, prn.rebuild FROM {node} n INNER JOIN {project_release_nodes} prn ON n.nid = prn.nid INNER JOIN {project_release_file} prf ON prn.nid = prf.nid INNER JOIN {term_node} tn ON prn.nid = tn.nid INNER JOIN {files} f ON prf.fid = f.fid WHERE n.status = 1 AND tn.tid = %d AND prn.pid = %d ORDER BY f.timestamp DESC", $term->tid, $node->nid, 0, 1)); $filetime = $latest_activity->timestamp; $key = 'ds_project_latest_activity_'. $term->tid; $document->$key = apachesolr_date_iso($filetime); if ($filetime > $max_filetime) { $max_filetime = $filetime; } // Now, look for the most recent official release for this API version. $key = 'ds_project_latest_release_'. $term->tid; if ($latest_activity->rebuild == 0) { // The latest activity is official, we're done. $document->$key = apachesolr_date_iso($filetime); if ($filetime > $max_official_filetime) { $max_official_filetime = $filetime; } } else { $filetime = db_result(db_query_range("SELECT f.timestamp FROM {node} n INNER JOIN {project_release_nodes} prn ON n.nid = prn.nid INNER JOIN {project_release_file} prf ON prn.nid = prf.nid INNER JOIN {term_node} tn ON prn.nid = tn.nid INNER JOIN {files} f ON prf.fid = f.fid WHERE n.status = 1 AND prn.rebuild = 0 AND tn.tid = %d AND prn.pid = %d ORDER BY f.timestamp DESC", $term->tid, $node->nid, 0, 1)); if (!empty($filetime)) { $document->$key = apachesolr_date_iso($filetime); } if ($filetime > $max_official_filetime) { $max_official_filetime = $filetime; } } } $document->ds_project_latest_activity = apachesolr_date_iso($max_filetime); if (!empty($max_official_filetime)) { $document->ds_project_latest_release = apachesolr_date_iso($max_official_filetime); } if (module_exists('project_usage')) { $weeks = variable_get('project_usage_active_weeks', array()); $week = reset($weeks); $total_usage = 0; $query = db_query("SELECT * FROM {project_usage_week_project} WHERE nid = %d AND timestamp = %d", $node->nid, $week); while ($usage = db_fetch_object($query)) { $key = 'sis_project_release_usage_'. $usage->tid; $document->$key = $usage->count; $total_usage += $usage->count; } $document->sis_project_release_usage = $total_usage; } } } //---------------------------------------- // Page callbacks //---------------------------------------- /** * Summary project browsing page. */ function project_solr_browse_summary_page() { $vid = _project_get_vid(); $tree = taxonomy_get_tree($vid, 0, -1, 1); $items = array(); foreach ($tree as $term) { $items[] = theme('project_type', $term); } drupal_set_title(t('Project types')); return theme('item_list', $items); } function project_solr_browse_page($term_name) { try { $output = ''; $parent_term = db_fetch_object(db_query("SELECT t.tid, t.name, t.description FROM {term_data} t WHERE t.vid = %d AND LOWER(t.name) = LOWER('%s')", _project_get_vid(), $term_name)); if (!$parent_term) { // XXX: this is the Drupal 5 way... return drupal_not_found(); } drupal_set_title(check_plain($parent_term->name)); if (!empty($parent_term->description)) { $output .= theme('project_type_description', $parent_term); } $text_query = isset($_GET['text']) ? $_GET['text'] : ''; $filters = isset($_GET['filters']) ? $_GET['filters'] : ''; $sort = isset($_GET['solrsort']) ? check_plain($_GET['solrsort']) : ''; // Validate sort parameter if ((!isset($sort) || !preg_match('/^([a-z0-9_]+ (asc|desc)(,)?)+$/i', $sort)) && empty($text_query)) { $sort = variable_get('project_solr_default_sort', 'sort_title asc'); } include_once drupal_get_path('module', 'project_solr') .'/ProjectSolrQuery.php'; $query = new ProjectSolrQuery(apachesolr_get_solr(), $text_query, $filters, $sort); if (is_null($query)) { throw new Exception(t('Could not construct a Solr query.')); } $query->add_field_aliases(array('im_project_release_api_tids' => 'drupal_core')); $params = array( 'fl' => 'id,nid,title,body,format,comment_count,type,created,changed,score,url,uid,name,sis_project_release_usage,ds_project_latest_release,ds_project_latest_activity', 'rows' => variable_get('apachesolr_rows', 10), 'facet' => 'true', 'facet.mincount' => 1, 'facet.sort' => 'true', 'facet.field' => array( 'im_vid_'. _project_get_vid(), 'im_project_release_api_tids', ), 'facet.limit' => 200, ); $page = isset($_GET['page']) ? $_GET['page'] : 0; $params['start'] = $page * $params['rows']; // This is the object that does the communication with the solr server. $solr = apachesolr_get_solr(); // This hook allows modules to modify the query and params objects. apachesolr_modify_query($query, $params, 'project_solr'); if (!$query) { return array(); } // Force sort to be by the corresponding core compatibility if filtered. $sort = $query->get_solrsort(); if (in_array($sort['#name'], array('ds_project_latest_release', 'ds_project_latest_activity')) && ($api_filters = $query->get_filters('im_project_release_api_tids'))) { $first_filter = reset($api_filters); $params['sort'] = $sort['#name'] .'_'. $first_filter['#value'] .' '. $sort['#direction']; } // We add 'fq' (filter query) parameters here to include all the constant // filters for the query -- project nodes of the given top-level type that // have releases (if project_release is enabled). $fq[] = 'type:project_project'; $fq[] = 'im_vid_'. _project_get_vid() .':'. $parent_term->tid; if (module_exists('project_release')) { $fq[] = 'is_project_has_releases:1'; } $params['fq'][] = '('. implode(' AND ', $fq) .')'; $response = $solr->search($query->get_query_basic(), $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. $total = $response->response->numFound; project_solr_response_cache(array($query, $response, $parent_term)); // Set breadcrumb $breadcrumb = menu_get_active_breadcrumb(); drupal_set_breadcrumb($breadcrumb); $output .= '