facetapi_luceneapi.module in Facet API 6
The Search Lucene API module's implementation of the the Facet API.
File
contrib/facetapi_luceneapi/facetapi_luceneapi.moduleView source
<?php
/**
* @file
* The Search Lucene API module's implementation of the the Facet API.
*/
// Loads term frequency cache.
module_load_include('inc', 'facetapi_luceneapi', 'facetapi_luceneapi.cache');
/**
* Implementation of hook_menu().
*/
function facetapi_luceneapi_menu() {
$items = array();
// Iterates over all searchable modules, adds menu items.
foreach (luceneapi_searchable_module_list() as $searcher => $name) {
$items['admin/settings/' . $searcher . '/facetapi'] = array(
'title' => 'Facets',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'facetapi_admin_settings_form',
$searcher,
),
'access arguments' => array(
'administer search',
),
'type' => MENU_LOCAL_TASK,
'file' => 'facetapi.admin.inc',
'file path' => drupal_get_path('module', 'facetapi'),
'weight' => 10,
);
}
return $items;
}
/**
* Implementation of hook_form_FORM_ID_alter().
*/
function facetapi_luceneapi_form_facetapi_admin_settings_form_alter(&$form, $form_state) {
if ('luceneapi_node' == $form['storage']['#value']['searcher']) {
$form['storage']['#value']['enabled'] = facetapi_enabled_facets_get($form['storage']['#value']['searcher']);
$form['#submit'][] = 'facetapi_luceneapi_form_facetapi_admin_settings_form';
}
}
/**
* Processes facetapi_admin_settings_form form submissions.
*/
function facetapi_luceneapi_form_facetapi_admin_settings_form(&$form, &$form_state) {
$searcher = $form['storage']['#value']['searcher'];
// Gets the newly enabled facets.
$enabled_facets = array_diff_key(facetapi_enabled_facets_get($searcher, NULL, TRUE), $form['storage']['#value']['enabled']);
// If facets have been enabled, re-populates termFreqs cache.
if (!empty($enabled_facets)) {
$batch = array(
'operations' => array(),
'title' => t('Rebuilding termFreqs cache'),
'init_message' => t('Populating ...'),
'progress_message' => t('Batch @current out of @total'),
'error_message' => t('An error occurred populating the cache.'),
);
// Iterates over facets, adds batch process to populate termFreqs cache.
foreach ($enabled_facets as $facet) {
$variable = 'facetapi:termfreqs_cached:' . $searcher . ':::' . $facet['field'];
variable_set($variable, TRUE);
$batch['operations'][] = array(
'facetapi_luceneapi_termfreqs_populate',
array(
$searcher,
$facet['field'],
),
);
}
// Let the batch begin!
batch_set($batch);
drupal_set_message(t('The termFreqs cache has been rebuilt.'));
}
}
/**
* Implementation of hook_facetapi_facet_info_alter().
*/
function facetapi_luceneapi_facetapi_facet_info_alter(array &$facets, $searcher, $type) {
if ('luceneapi_node' == $searcher) {
foreach ($facets as &$facet) {
if (preg_match('/^vocabulary_(\\d+)$/', $facet['name'], $matches)) {
$facet['field'] = 'category_' . $matches[1];
$facet['field alias'] = 'category';
}
}
unset($facet);
}
}
/**
* Implementation of hook_facetapi_facets_alter().
*
* Re-implements the logic in facetapi_facetapi_facets_alter() because
* Search Lucene API uses a different name for the general taxonomy field.
*
* @see facetapi_facetapi_facets_alter()
*/
function facetapi_luceneapi_facetapi_facet_alter(&$built, $adapter, $realm) {
/*
if ('fieldset' == $realm_name && 'node' == $type && isset($built['category'])) {
$built['category']['#title'] = t('Only in the category(s)');
$built['category']['#type'] = 'select';
$built['category']['#multiple'] = TRUE;
$built['category']['#description'] = '';
if (isset($built['category']['#weight']) && is_array($built['category']['#weight'])) {
$built['category']['#weight'] = min($built['category']['#weight']);
}
}
*/
}
/**
* Implementation of hook_facetapi_adapter_info().
*/
function facetapi_luceneapi_facetapi_adapter_info() {
$adapters = array();
// Iterates over searchable Search Lucene API modules, builds adapter information.
foreach (luceneapi_searchable_module_list() as $searcher => $name) {
$adapters[$searcher] = array(
'class' => 'FacetapiLuceneapiAdapter',
'type' => luceneapi_index_type_get($searcher),
'file' => 'facetapi_luceneapi.adapter.inc',
);
}
return $adapters;
}
/**
* Converts all timestamps in an array to dates in ISO 8601 format.
*
* @param &$value
* An integer containing the timestamp.
* @param $key
* An integer containing the array key.
* @param $gap
* A string containing the gap, see FACETAPI_DATE_* constants for valid
* values. Defaults to FACETAPI_DATE_SECOND.
*/
function facetapi_luceneapi_timestamp_convert(&$value, $key, $gap) {
$value = facetapi_isodate($value, $gap);
}
/**
* Implementation of hook_apachesolr_prepare_query().
*/
function facetapi_luceneapi_luceneapi_query_alter(Zend_Search_Lucene_Search_Query $query, $module, $type = NULL) {
facetapi_query_type_hooks_invoke($module, $query);
}
/**
* Implementation of hook_facetapi_query_TYPE_process().
*/
function facetapi_luceneapi_facetapi_query_term_process(FacetapiAdapter $adapter, array $facet, Zend_Search_Lucene_Search_Query $query) {
$values = $adapter
->getActiveFacets($facet['field alias']);
if (empty($values)) {
return;
}
try {
if (!($multiterm = luceneapi_query_get('multiterm'))) {
throw new LuceneAPI_Exception(t('Error instantiating multiterm query.'));
}
// Gets the operator.
$operator = facetapi_setting_get('operator', $adapter
->getSearcher(), '', $facet['name']);
$sign = FACETAPI_OPERATOR_OR != $operator ? 'required' : 'neither';
foreach ($values as $value => $filter_string) {
$term = luceneapi_term_get((string) $value, $facet['field'], TRUE);
luceneapi_term_add($multiterm, $term, $sign, TRUE);
}
// If there are terms, appends subquery.
if (count($multiterm
->getTerms())) {
$multiterm
->setBoost(LUCENEAPI_IRRELEVANT);
luceneapi_subquery_add($query, $multiterm, 'required', TRUE);
}
} catch (LuceneAPI_Exception $e) {
luceneapi_throw_error($e, WATCHDOG_ERROR, 'facetapi_luceneapi');
}
}
/**
* Implementation of hook_facetapi_query_TYPE_process().
*/
function facetapi_luceneapi_facetapi_query_date_process(FacetapiAdapter $adapter, array $facet, Zend_Search_Lucene_Search_Query $query) {
$values = $adapter
->getActiveFacets($facet['field alias']);
if (empty($values)) {
return;
}
try {
// Gets the facet's operator.
if (!($boolean = luceneapi_query_get('boolean'))) {
throw new Exception(t('Error instantiating boolean query.'));
}
foreach ($values as $value => $filter_string) {
$range = explode(' TO ', trim($value, '{[]}'));
// Adds subquery if ranges were extracted.
if (2 == count($range)) {
$range = array_map('strtotime', $range);
if ($subquery = luceneapi_query_get('range', $range[0], $range[1], FALSE, $facet['field'])) {
luceneapi_subquery_add($boolean, $subquery, 'required', TRUE);
}
}
}
// Makes query irrelevant in scoring, appends subquery.
$boolean
->setBoost(LUCENEAPI_IRRELEVANT);
luceneapi_subquery_add($query, $boolean, 'required');
} catch (Exception $e) {
luceneapi_throw_error($e, WATCHDOG_ERROR, 'facetapi_luceneapi');
}
}
/**
* Implementation of hook_luceneapi_document_alter().
*/
function facetapi_luceneapi_luceneapi_document_alter(Zend_Search_Lucene_Document $doc, $node, $module, $type = NULL) {
static $fields;
if ('luceneapi_node' == $module) {
// Maintains taxonomy ancestry for hierarchical browsing. Parent term counts
// should also include child terms counts.
$terms = array();
if (isset($node->taxonomy) && is_array($node->taxonomy)) {
foreach ($node->taxonomy as $term) {
$ancestors = taxonomy_get_parents_all($term->tid);
foreach ($ancestors as $ancestor) {
$terms[$ancestor->vid][$ancestor->tid] = $ancestor->tid;
}
}
}
// Changes the field definition for categories, rebuilds the field's value
// with all parent and child terms.
foreach ($terms as $vid => $tids) {
try {
$field = $doc
->getField('category_' . $vid);
$field->isStored = FALSE;
$field->isIndexed = TRUE;
$field->isTokenized = TRUE;
$field->value = join(' ', $tids);
} catch (Exception $e) {
luceneapi_throw_error($e, WATCHDOG_ERROR, 'facetapi_luceneapi');
}
}
// @todo This is nasty. We need a better way to do this. Unfortunately, we
// have to wait until this functionality is integrated into the core Search
// Lucene API module.
if (NULL === $fields) {
$fields = array();
foreach (facetapi_enabled_facets_get($module) as $facet) {
$fields[] = $facet['field'];
}
}
foreach ($fields as $field) {
$variable = 'facetapi:termfreqs_cached:' . $module . ':::' . $field;
variable_del($variable);
}
}
}
/**
* Implementation of hook_form_FORM_ID_alter().
*/
function facetapi_luceneapi_form_facetapi_facet_settings_form_alter(&$form, &$form_state) {
$arg = arg(2);
$modules = luceneapi_searchable_module_list();
if (isset($modules[$arg])) {
$breadcrumb = drupal_get_breadcrumb();
$breadcrumb[] = l($modules[$arg], "admin/settings/{$arg}");
$breadcrumb[] = l(t('Facets'), "admin/settings/{$arg}/facetapi");
drupal_set_breadcrumb($breadcrumb);
}
}