'Apache Solr search',
'description' => 'Administer Apache Solr.',
'page callback' => 'drupal_get_form',
'page arguments' => array('apachesolr_settings'),
'access callback' => 'user_access',
'access arguments' => array('administer site configuration'),
);
$items['admin/settings/apachesolr/index'] = array(
'title' => 'Apache Solr search index',
'page callback' => 'apachesolr_index_page',
'access callback' => 'user_access',
'access arguments' => array('administer site configuration'),
);
return $items;
}
function apachesolr_settings() {
$form = array();
$form['apachesolr_host'] = array(
'#type' => 'textfield',
'#title' => t('Solr host name'),
'#default_value' => variable_get('apachesolr_host', 'localhost'),
'#description' => t('Host name of your Solr server, e.g. localhost
or example.com
.'),
);
$form['apachesolr_port'] = array(
'#type' => 'textfield',
'#title' => t('Solr port'),
'#default_value' => variable_get('apachesolr_port', '8983'),
'#description' => t('Port on which the Solr server listens. Tomcat is 8080 by default.'),
);
$form['apachesolr_path'] = array(
'#type' => 'textfield',
'#title' => t('Solr path'),
'#default_value' => variable_get('apachesolr_path', '/solr'),
'#description' => t('Path that identifies the Solr request handler to be used. Leave this as /solr for now.'),
);
$options = array();
foreach (array(5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100) as $option) {
$options[$option] = $option;
}
$form['apachesolr_rows'] = array(
'#type' => 'select',
'#title' => t('Results per page'),
'#default_value' => variable_get('apachesolr_rows', 10),
'#options' => $options,
'#description' => t('The number of results that will be shown per page.'),
);
return system_settings_form($form);
}
/**
* Implementation of hook_requirements().
*/
function apachesolr_requirements($phase) {
// Ensure translations don't break at install time
$t = get_t();
if ($phase == 'runtime') {
$host = variable_get('apachesolr_host', 'localhost');
$port = variable_get('apachesolr_port', 8983);
$path = variable_get('apachesolr_path', '/solr');
$ping = FALSE;
try {
$solr =& apachesolr_get_solr($host, $port, $path);
$ping = $solr->ping();
// If there is no $solr object, there is no server available, so don't continue.
if (!$ping) {
throw new Exception(t('No Solr instance available during indexing'));
}
}
catch (Exception $e) {
watchdog('Apache Solr', $e->getMessage(), WATCHDOG_ERROR);
}
$value = $ping ? $t('Solr can be pinged.') : $t('No Solr instance is available.');
$severity = $ping ? REQUIREMENT_OK: REQUIREMENT_ERROR;
$description = theme('item_list', array($t('Host: %host', array('%host' => $host)),
$t('Port: %port', array('%port' => $port)),
$t('Path: %path', array('%path' => $path))));
$requirements['apachesolr'] = array(
'title' => $t('ApacheSolr'),
'value' => $value,
'description' => $description,
'severity' => $severity,
);
return $requirements;
}
}
function apachesolr_index_page() {
//TODO: Should we be generating the dynamic blocks based on what is indexed?
// Or should we be using things like node_field.type to get this list?
$response = drupal_http_request(apachesolr_base_url() ."/admin/luke?numTerms=0");
if ($response->code == '200') {
$xml_response = simplexml_load_string($response->data);
$fields = $xml_response->xpath("//lst[@name='fields']/lst");
$rows = array();
foreach ((array)$fields as $field) {
$field_name = $field['name'];
$field_type = $field->xpath('./str');
$rows[] = array(
$field_name,
$field_type[0],
);
}
}
return theme('table', array(t('Field name'), t('Field index type')), $rows);
}
/**
* The point of this class is to manage the update index needs of multiple
* search modules. Each one needs to track its own list of nodes that need
* updating.
*/
class ApacheSolrUpdate {
public static $_namespaces = array();
static function reset($namespace) {
variable_del($namespace . '_last_change');
variable_del($namespace . '_last_id');
}
static function get_change($namespace) {
$var = variable_get($namespace . '_last_change', 0);
return $var;
}
static function get_last($namespace) {
$var = variable_get($namespace . '_last_id', 0);
return $var;
}
/**
* Function to generically handle the fetching of nodes that need indexing on a cron run.
* It takes a namespace which needs to be unique to the calling module and manages
* all of the global variables and the shutdown function so that every search
* implementation can have its own without needing to duplicate the query.
* Returns a db_query $result.
* Modules need to then call apache_update_success after each node is successfully
* indexed.
*/
static function getNodesToIndex($namespace) {
register_shutdown_function('apachesolr_shutdown');
$cron_change = self::get_change($namespace);
$cron_last = self::get_last($namespace);
$cron_limit = variable_get('search_cron_limit', 100);
$result = db_query_range('SELECT GREATEST(IF(c.last_comment_timestamp IS NULL, 0, c.last_comment_timestamp), n.changed) as last_change, n.nid '.
'FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid '.
'WHERE n.status = 1 '.
' AND ((GREATEST(n.changed, c.last_comment_timestamp) = %d AND n.nid > %d) OR (n.changed > %d OR c.last_comment_timestamp > %d)) '.
'ORDER BY GREATEST(n.changed, c.last_comment_timestamp) ASC, n.nid ASC', $cron_change, $cron_last, $cron_change, $cron_change, $cron_change, 0, $cron_limit);
return $result;
}
static function success($namespace, $last_change, $last_id) {
self::$_namespaces[$namespace] = array('last_change' => $last_change, 'last_id' => $last_id);
}
static function update_index($namespace) {
$solr = FALSE;
try {
// Get the $solr object
$solr =& apachesolr_get_solr(variable_get('apachesolr_host', 'localhost'), variable_get('apachesolr_port', 8983), variable_get('apachesolr_path', '/solr'));
// If there is no $solr object, there is no server available, so don't continue.
if (!$solr->ping()) {
throw new Exception(t('No Solr instance available during indexing'));
}
}
catch (Exception $e) {
watchdog('Apache Solr', $e->getMessage(), WATCHDOG_ERROR);
return;
}
// Get CCK fields list
$cck_fields = apachesolr_cck_fields();
$result = self::getNodesToIndex($namespace);
$count = 0;
$documents = array();
while ($row = db_fetch_object($result)) {
// Variables to track the last item changed.
$solr_last_change = $row->last_change;
$solr_last_id = $row->nid;
$node = node_load($row->nid);
if ($node->nid) {
// Build the node body.
$node = node_build_content($node, FALSE, FALSE);
$node->body = drupal_render($node->content);
$text = check_plain($node->title) . $node->body;
// Fetch extra data normally not visible
$extra = node_invoke_nodeapi($node, 'update index');
foreach ($extra as $t) {
$text .= $t;
}
// Update solr index.
try {
$document = new Apache_Solr_Document();
// Let modules add to the document
module_invoke_all('apachesolr_update_index', &$document, $node);
$fields = array('title', 'body', 'type', 'uid', 'changed', 'nid', 'comment_count', 'name', 'language');
foreach ((array)$node as $key => $value) {
if (in_array($key, $fields)) {
$document->$key = $value;
}
if ($cck_fields && strpos($key, 'field_') === 0) {
// Got a CCK field. See if it is to be indexed.
if (in_array($key, array_keys($cck_fields))) {
$function = $cck_fields[$key]['callback'];
if ($cck_fields[$key]['callback'] && function_exists($function)) {
$dynamic_fields = call_user_func_array($function, array($node, $key));
}
else {
$dynamic_fields = $node->$key;
}
if (is_array($dynamic_fields) && count($dynamic_fields) > 0) {
foreach ($dynamic_fields as $field) {
if (!empty($field['view'])) {
$index_key = apachesolr_index_key($cck_fields[$key]);
if ($cck_fields[$key]['multiple']) {
$document->setMultiValue($index_key, $field['view']);
}
else {
$document->$index_key = $field['view'];
}
}
}
}
}
}
}
if (is_array($node->taxonomy)) {
foreach ($node->taxonomy as $term) {
$document->setMultiValue('tid', $term->tid);
$document->setMultiValue('vid', $term->vid);
$document->setMultiValue('taxonomy_name', $term->name);
}
}
$document->text = $text;
$documents[] = $document;
if ($count++ % 50 == 49) {
watchdog('Apache Solr', t("Adding @count documents", array('@count' => count($documents))));
$solr->addDocuments($documents);
$count = 0;
$documents = array();
}
}
catch (Exception $e) {
watchdog('Apache Solr', $e->getMessage(), WATCHDOG_ERROR);
}
}
self::success('apachesolr', $solr_last_change, $solr_last_id);
}
if (is_object($solr)) {
// remaining documents
try {
watchdog('Apache Solr', "Adding " . count($documents) ." documents in cleanup");
$solr->addDocuments($documents);
$solr->commit();
$solr->optimize(FALSE, FALSE);
}
catch (Exception $e) {
watchdog('Apache Solr', $e->getMessage(), WATCHDOG_ERROR);
}
}
}
}
/**
* Registered shutdown function.
*/
function apachesolr_shutdown() {
foreach (ApacheSolrUpdate::$_namespaces as $namespace => $vars) {
extract($vars);
if ($last_change && $last_id) {
variable_set("{$namespace}_last_change", $last_change);
variable_set("{$namespace}_last_id", $last_id);
}
}
}
/**
* Implementation of hook_nodeapi().
*/
function apachesolr_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
switch ($op) {
case 'delete':
try {
$solr =& apachesolr_get_solr(variable_get('apachesolr_host', 'localhost'), variable_get('apachesolr_port', 8983), variable_get('apachesolr_path', '/solr'));
$solr->deleteById($node->nid);
$solr->commit();
}
catch (Exception $e) {
watchdog('Apache Solr', $e->getMessage(), WATCHDOG_ERROR);
}
break;
}
}
/**
* Implementation of hook_block().
*/
function apachesolr_block($op = 'list', $delta = 0, $edit = array()) {
$term_title = t('ApacheSolr: Filter by term');
$type_title = t('ApacheSolr: Filter by type');
$author_title = t('ApacheSolr: Filter by author');
switch ($op) {
case 'list':
if (module_exists('taxonomy')) {
$vocabs = taxonomy_get_vocabularies();
foreach ($vocabs as $vid => $vocab) {
$blocks['vocabulary-'. $vid] = array('info' => t('ApacheSolr: Filter by @name', array('@name' => $vocab->name)));
}
}
$blocks['type'] = array('info' => $type_title);
$blocks['author'] = array('info' => $author_title);
if ($fields = apachesolr_cck_fields()) {
foreach ($fields as $name => $field) {
$index_key = apachesolr_index_key($field);
$label = db_result(db_query("SELECT label FROM {node_field_instance} WHERE field_name = '%s'", $name));
$blocks[$index_key] = array('info' => t('ApacheSolr: Filter by @field', array('@field' => $label)));
}
}
// Sorting block
$blocks['sort'] = array('info' => t('ApacheSolr: Sorting'));
return $blocks;
case 'view':
if (apachesolr_has_searched()) {
// Get the query and response. Without these no blocks make sense.
$response =& apachesolr_static_response_cache();
if (empty($response)) {
return;
}
$query =& apachesolr_drupal_query();
// Get information needed by the rest of the blocks about limits.
$facet_limits = variable_get('apachesolr_facet_limits', array());
if ((strpos($delta, 'vocabulary-') === 0) && module_exists('taxonomy')) {
// On first time through here build all the terms. Static caching
// will make them available for other vocabulary blocks.
static $terms;
if (empty($terms)) {
if (is_array($response->facets->tid)) {
$contains_active = FALSE;
foreach ($response->facets->tid as $tid => $count) {
$unclick_link = '';
unset($active);
$term = taxonomy_get_term($tid);
$new_query = clone $query;
if ($active = $query->has_field('tid', $tid)) {
$contains_active = TRUE;
$new_query->remove_field('tid', $term->tid);
$path = 'search/' . arg(1) . '/' . $new_query->get_query();
$unclick_link = theme('apachesolr_unclick_link', $path);
}
else {
$new_query->add_field('tid', $term->tid);
$path = 'search/' . arg(1) . '/' . $new_query->get_query();
}
$countsort = $count == 0 ? '' : 1 / $count;
// if numdocs == 1 and !active, don't add.
if ($response->numFound == 1 && !$active) {
// skip
}
else {
$terms[$term->vid][$active ? $countsort . $term->name : 1 + $countsort . $term->name] =
theme('apachesolr_facet_item', $term->name, $count, $path, $active, $unclick_link);
}
}
}
}
$vid = substr($delta, 11, 1);
$vocab = taxonomy_vocabulary_load($vid);
if (is_numeric($vid) && is_array($terms) && isset($terms[$vid]) && is_array($terms[$vid])) {
ksort($terms[$vid]);
$facet_limit = isset($facet_limits[$delta]) ? $facet_limits[$delta] : 10;
$terms[$vid] = array_slice($terms[$vid], 0, $facet_limit);
return array('subject' => t('Filter by @name', array('@name' => $vocab->name)),
'content' => theme('apachesolr_facet_list', $terms[$vid]));
}
else {
return;
}
}
switch ($delta) {
case 'sort':
$sorts = array(
'title' => array('name' => t('Title'), 'default' => 'asc'),
'type' => array('name' => t('Type'), 'default' => 'asc'),
'name' => array('name' => t('Author'), 'default' => 'asc'),
'changed' => array('name' => t('Date'), 'default' => 'desc'),
);
$solrsorts = array();
$sort_parameter = isset($_GET['solrsort']) ? check_plain($_GET['solrsort']) : FALSE;
foreach(explode(',', $sort_parameter) as $solrsort) {
$parts = explode(' ', $solrsort);
if (!empty($parts[0]) && !empty($parts[1])) {
$solrsorts[$parts[0]] = $parts[1];
}
}
$sort_links = array();
$path = 'search/'. arg(1). '/'. $query->get_query();
foreach ($sorts as $type => $sort) {
$new_sort = isset($solrsorts[$type]) ? $solrsorts[$type] == 'asc' ? 'desc' : 'asc' : $sort['default'];
$sort_links[] = theme('apachesolr_sort_link', $sort['name'], $path, "solrsort={$type} {$new_sort}", isset($solrsorts[$type]) ? $solrsorts[$type] : '');
}
return array('subject' => t('Sort by') . ':',
'content' => theme('apachesolr_sort_list', $sort_links));
case 'type':
if (is_array($response->facets->type)) {
$contains_active = FALSE;
$types = array();
foreach ($response->facets->type as $t => $count) {
$unclick_link = '';
unset($active);
$type = node_get_types('name', $t);
$new_query = clone $query;
if ($active = $query->has_field('type', $t)) {
$contains_active = TRUE;
$new_query->remove_field('type', $t);
$path = 'search/'. arg(1) .'/'. $new_query->get_query();
$unclick_link = theme('apachesolr_unclick_link', $path);
}
else {
$new_query->add_field('type', $t);
$path = 'search/'. arg(1) .'/'. $new_query->get_query();
}
$countsort = $count == 0 ? '' : 1 / $count;
// if numdocs == 1 and !active, don't add.
if ($response->numFound == 1 && !$active) {
// skip
}
else {
$types[$active ? $countsort . $type : 1 + $countsort . $type] = theme('apachesolr_facet_item', $type, $count, $path, $active, $unclick_link);
}
}
if (count($types) > 0) {
ksort($types);
$facet_limit = isset($facet_limits[$delta]) ? $facet_limits[$delta] : 10;
$types = array_slice($types, 0, $facet_limit);
$output = theme('apachesolr_facet_list', $types);
return array('subject' => $type_title, 'content' => $output);
}
}
break;
case 'author':
if (is_array($response->facets->uid)) {
$contains_active = FALSE;
foreach ($response->facets->uid as $uid => $count) {
$unclick_link = '';
unset($active);
$name = db_result(db_query("SELECT name FROM {users} WHERE uid = %d", $uid));
$new_query = clone $query;
if ($active = $query->has_field('uid', $uid)) {
$contains_active = TRUE;
$new_query->remove_field('uid', $uid);
$path = 'search/'. arg(1) .'/'. $new_query->get_query();
$unclick_link = theme('apachesolr_unclick_link', $path);
}
else {
$new_query->add_field('uid', $uid);
$path = 'search/'. arg(1) .'/'. $new_query->get_query();
}
$countsort = $count == 0 ? '' : 1 / $count;
// if numdocs == 1 and !active, don't add.
if ($response->numFound == 1 && !$active) {
// skip
}
else {
$users[$active ? $countsort . $name : 1 + $countsort . $name] = theme('apachesolr_facet_item', $name, $count, $path, $active, $unclick_link);
}
}
if (is_array($users)) {
ksort($users);
$facet_limit = isset($facet_limits[$delta]) ? $facet_limits[$delta] : 10;
$users = array_slice($users, 0, $facet_limit);
$output = theme('apachesolr_facet_list', $users);
return array('subject' => $author_title, 'content' => $output);
}
}
break;
default:
if ($fields = apachesolr_cck_fields()) {
foreach ($fields as $name => $field) {
$index_key = apachesolr_index_key($field);
if ($index_key == $delta) {
if (is_array($response->facets->$index_key)) {
$contains_active = FALSE;
foreach ($response->facets->$index_key as $facet => $count) {
$unclick_link = '';
unset($active);
$new_query = clone $query;
if ($active = $query->has_field($index_key, $facet)) {
$contains_active = TRUE;
$new_query->remove_field($index_key, $facet);
$path = 'search/'. arg(1) .'/'. $new_query->get_query();
$unclick_link = theme('apachesolr_unclick_link', $path);
}
else {
$new_query->add_field($index_key, $facet);
$path = 'search/'. arg(1) .'/'. $new_query->get_query();
}
$countsort = $count == 0 ? '' : 1 / $count;
// if numdocs == 1 and !active, don't add.
if ($response->numFound == 1 && !$active) {
// skip
}
else {
$facets[$active ? $countsort . $facet : 1 + $countsort . $facet] = theme('apachesolr_facet_item', $facet, $count, $path, $active, $unclick_link);
}
}
if (is_array($facets)) {
ksort($facets);
$facet_limit = isset($facet_limits[$delta]) ? $facet_limits[$delta] : 10;
$facets = array_slice($facets, 0, $facet_limit);
$output = theme('apachesolr_facet_list', $facets);
$label = db_result(db_query("SELECT label FROM {node_field_instance} WHERE field_name = '%s'", $name));
return array('subject' => t('Filter by @field', array('@field' => $label)),
'content' => $output);
}
}
}
}
}
}
break;
}
break;
case 'configure':
if ($delta != 'sort') {
$facet_limits = variable_get('apachesolr_facet_limits', array());
// If the block is not 'sort' (and therefore is a facet block),
// display facet limit option.
return array('facet_limit' => array(
'#type' => 'textfield',
'#title' => t('Facet Limit'),
'#required' => TRUE,
'#description' => t('Enter a number 1 or greater that is the maximum number of facets to display in this block.'),
'#default_value' => isset($facet_limits[$delta]) ? $facet_limits[$delta] : 10,
),
// TODO: Get this to work.
'#validate' => array('_apachesolr_facet_limit_validate'),
);
}
break;
case 'save':
if ($delta != 'sort') {
$val = intval($edit['facet_limit']);
// Save the new facet limit for this facet
$facet_limits = variable_get('apachesolr_facet_limits', array());
$facet_limits[$delta] = $val;
variable_set('apachesolr_facet_limits', $facet_limits);
}
break;
}
}
/*
* Validates a facet limit input. Must be a positive integer.
*/
function apachesolr_facet_limit_validate($form, &$form_state) {
if ($form_state['values']['facet_limit'] < 1) {
form_set_error('facet_limit', t('Please enter a number greater than 1 for the facet limit.'));
return FALSE;
}
}
/**
* Implementation of hook_form_alter().
*/
function apachesolr_form_alter(&$form, $form_state, $form_id) {
$arg = arg(1);
$alias = drupal_lookup_path('alias', "search/{$arg}");
// Ok, this really sucks. I want a way to know whether the action of the form
// is supposed to be handled by an ApacheSolr module or not. I manually
// exclude node and user here, but there are many other hook_search implementations
// in the wild and this code will potentially interfere with them. It also
// creates a Solr instance wasting resources.
if ($arg != 'node' && $arg != 'user' && (
preg_match("&/search/{$arg}&", $form['#action']) ||
preg_match("&/{$alias}&", $form['#action']) ||
strpos($form['#action'], $alias))) {
if (!isset($_POST['form_id'])) {
// Set up our validation function
$form['#validate']['apachesolr_search_validate'] = array();
// if no keys, there's nothing to do.
if (empty($form['basic']['inline']['keys']['#default_value'])) {
return;
}
// The $query is the true source for search key information
if ($query =& apachesolr_drupal_query()) {
$form['basic']['inline']['keys']['#default_value'] = $query->get_query_basic();
}
}
}
}
/**
* Semaphore that indicates whether a search has been done. Blocks use this
* later to decide whether they should load or not.
*
* @param $searched
* A boolean indicating whether a search has been executed.
*
* @return
* TRUE if a search has been executed.
* FALSE otherwise.
*/
function apachesolr_has_searched($searched = NULL) {
static $_searched = FALSE;
if (is_bool($searched)) {
$_searched = $searched;
}
return $_searched;
}
/**
* Factory method for solr singleton object. Structure allows for an arbitrary
* number of solr objects to be used based on the host, port, path combination.
* Get an instance like this:
* $solr =& apachesolr_get_solr();
*/
function &apachesolr_get_solr($host = 'localhost', $port = 8983, $path = '/solr') {
static $solr_cache;
if (empty($solr_cache[$host][$port][$path])) {
$include_path = get_include_path();
set_include_path('./'. drupal_get_path('module', 'apachesolr') .'/SolrPhpClient/');
include_once('Apache/Solr/Service.php');
set_include_path($include_path);
$solr_cache[$host][$port][$path] = new Apache_Solr_Service($host, $port, $path);
}
return $solr_cache[$host][$port][$path];
}
/**
* It is important to hold on to the Solr response object for the duration of the
* page request so that we can use it for things like building facet blocks.
*/
function &apachesolr_static_response_cache($response = NULL) {
static $_response;
if (!empty($response)) {
$_response = drupal_clone($response);
}
return $_response;
}
/*
* The query object is built from the keys. If you want to build queries
* programmatically you can pass in different keys. If you don't pass in
* any keys, search_get_keys() is used instead.
*/
function &apachesolr_drupal_query($keys = NULL, $reset = FALSE) {
static $_queries;
if ($reset) {
unset($_queries);
}
if (empty($keys)) {
$keys = search_get_keys();
}
if (empty($_queries) || empty($_queries[$keys])) {
include_once drupal_get_path('module', 'apachesolr') .'/Solr_Base_Query.php';
$_queries[$keys] = new Solr_Base_Query($keys);
}
return $_queries[$keys];
}
function apachesolr_base_url() {
return "http://" . variable_get('apachesolr_host', 'localhost') .':'. variable_get('apachesolr_port', '8983') . variable_get('apachesolr_path', '/solr');
}
/**
* array('index_type' => 'integer',
* 'multiple' => TRUE,
* ),
*/
function apachesolr_index_key($field) {
switch ($field['index_type']) {
case 'text':
$type_prefix = 't';
break;
case 'string':
$type_prefix = 's';
break;
case 'integer':
$type_prefix = 'i';
break;
case 'double':
$type_prefix = 'p'; // reserve d for date
break;
case 'boolean':
$type_prefix = 'b';
break;
case 'date':
$type_prefix = 'd';
break;
default:
$type_prefix = 's';
}
$sm = $field['multiple'] ? 'm' : 's';
return $type_prefix . $sm . $field['name'];
}
/**
* This invokes the hook_apachesolr_cck_field_mappings to find out how to handle
* CCK fields.
*/
function apachesolr_cck_fields() {
static $_fields;
// If CCK isn't enabled, do nothing.
if (module_exists('content')) {
$mappings = module_invoke_all('apachesolr_cck_field_mappings');
if (is_null($_fields)) {
$_fields = array();
$result = db_query("SELECT i.field_name, f.multiple, f.type, i.widget_type FROM {content_node_field_instance} i INNER JOIN {content_node_field} f ON i.field_name = f.field_name;");
while ($row = db_fetch_object($result)) {
// Only deal with fields that have options widgets (facets don't make sense otherwise), or fields that have specific mappings.
if (($row->type == 'text' && in_array($row->widget_type, array('options_select', 'options_buttons'))) || in_array($row->type, array_keys($mappings))) {
$_fields[$row->field_name] = array(
'name' => $row->field_name,
'multiple' => $row->multiple ? TRUE : FALSE,
'field_type' => $row->type,
'index_type' => empty($mappings) ? 'string' : $mappings[$row->type]['index_type'],
'callback' => empty($mappings[$row->type]['callback']) ? NULL : $mappings[$row->type]['callback'],
);
}
}
}
return $_fields;
}
else {
return FALSE;
}
}
/**
* Implementation of hook_theme().
*/
function apachesolr_theme() {
return array(
'apachesolr_facet_item' => array(
'arguments' => array('name' => NULL, 'count' => NULL, 'path' => NULL, 'active' => FALSE, 'unclick_link' => NULL),
),
'apachesolr_unclick_link' => array(
'arguments' => array('url' => NULL),
),
'apachesolr_facet_list' => array(
'arguments' => array('items' => NULL),
),
'apachesolr_sort_list' => array(
'arguments' => array('items' => NULL),
),
'apachesolr_sort_link' => array(
'arguments' => array('text' => NULL, 'path' => NULL, 'query' => NULL, 'direction' => NULL),
),
'apachesolr_breadcrumb_type' => array(
'arguments' => array('type' => NULL),
),
'content_apachesolr_breadcrumb_uid' => array(
'arguments' => array('uid' => NULL),
),
'apachesolr_breadcrumb_tid' => array(
'arguments' => array('tid' => NULL),
),
);
}
function theme_apachesolr_facet_item($name, $count, $path, $active = FALSE, $unclick_link = NULL) {
$attributes = array();
if ($active) {
$attributes['class'] = 'active';
}
if ($unclick_link) {
return $unclick_link . " $name";
}
else {
return l($name . " ($count)", $path, array('attributes' => $attributes));
}
}
function theme_apachesolr_unclick_link($path) {
return l("(-)", $path);
}
function theme_apachesolr_sort_link($text, $path, $query, $direction = NULL) {
$icon = '';
if ($direction) {
$icon = theme('tablesort_indicator', $direction);
}
return $icon . ' ' . l($text, $path, array('query' => $query));
}
function theme_apachesolr_facet_list($items) {
return theme('item_list', $items);
}
function theme_apachesolr_sort_list($items) {
return theme('item_list', $items);
}
/**
* Return the human readable text for a content type.
*/
function theme_apachesolr_breadcrumb_type($type) {
return node_get_types('name', $type);
}
/**
* Return the username from $uid
*/
function theme_apachesolr_breadcrumb_uid($uid) {
$user = user_load(array('uid' => $uid));
return $user->name;
}
/**
* Return the term name from $tid.
*/
function theme_apachesolr_breadcrumb_tid($tid) {
$term = taxonomy_get_term($tid);
return $term->name;
}