View source
<?php
class SarniaSolrService extends SearchApiSolrService {
protected $disabled_features = array();
public function disableFeature($feature) {
$this->disabled_features[$feature] = $feature;
}
public function unDisableFeature($feature) {
unset($this->disabled_features[$feature]);
}
public function configurationForm(array $form, array &$form_state) {
$form = parent::configurationForm($form, $form_state);
$options = $this->options + array(
'sarnia_request_handler' => '',
'sarnia_default_query' => '*:*',
);
$form['advanced']['sarnia_request_handler'] = array(
'#type' => 'textfield',
'#title' => t('Sarnia request handler'),
'#description' => t("Enter the name of a requestHandler from the core's solrconfig.xml file. This should only be necessary if you need to specify a handler to use other than the default."),
'#default_value' => $options['sarnia_request_handler'],
);
$form['advanced']['sarnia_default_query'] = array(
'#type' => 'textfield',
'#title' => t('Sarnia default query'),
'#description' => t("Enter a default query parameter. This may only be necessary if a default query cannot be specified in the solrconfig.xml."),
'#default_value' => $options['sarnia_default_query'],
);
return $form;
}
public function configurationFormValidate(array $form, array &$values, array &$form_state) {
parent::configurationFormValidate($form, $values, $form_state);
}
public function supportsFeature($feature) {
if (isset($this->disabled_features[$feature])) {
return FALSE;
}
return parent::supportsFeature($feature);
}
public function getFieldNames(SearchApiIndex $index, $reset = FALSE) {
$ret = array();
$sarnia_entity_info = sarnia_entity_type_load_by_index($index->machine_name);
if (!empty($index->options['fields'])) {
foreach (array_keys($index->options['fields']) as $f) {
$ret[$f] = $f;
}
}
$ret = array_merge($ret, array(
'search_api_id' => $sarnia_entity_info['id_field'],
'search_api_relevance' => 'score',
'search_api_item_id' => $sarnia_entity_info['id_field'],
'search_api_random' => 'random_' . rand(1, 200),
));
drupal_alter('search_api_solr_field_mapping', $index, $ret);
return $ret;
}
protected function preQuery(array &$call_args, SearchApiQueryInterface $query) {
if (!isset($call_args['query']) || empty($call_args['query'])) {
$call_args['query'] = $this->options['sarnia_default_query'];
}
foreach ($call_args['params']['fq'] as $index => $value) {
list($filter, $val) = explode(':', $value);
if (in_array($filter, array(
'hash',
'index_id',
))) {
unset($call_args['params']['fq'][$index]);
}
}
$call_args['params']['fq'] = array_values($call_args['params']['fq']);
$call_args['params']['fl'] = array(
'*,score',
);
if (!empty($this->options['sarnia_request_handler'])) {
$call_args['params']['qt'] = $this->options['sarnia_request_handler'];
}
}
protected function postQuery(array &$results, SearchApiQueryInterface $query, $response) {
parent::postQuery($results, $query, $response);
$sarnia_entity_type = sarnia_entity_server_name_load($this->server->machine_name);
entity_get_controller($sarnia_entity_type)
->stash($results['results']);
}
protected function getFacetField($field) {
return $field;
}
public function getRemoteFields($reset = FALSE) {
$cid = 'search_api_solr:fields:' . $this->server->machine_name;
if (!isset($this->fields) && !$reset) {
$cache = cache_get($cid);
if (isset($cache->data)) {
$this->fields = $cache->data;
}
}
if (!isset($this->fields) || $reset) {
$this
->connect();
$this->fields = array();
try {
foreach ($this->solr
->getFields() as $name => $info) {
$this->fields[$name] = new SarniaSearchApiSolrField($info, $name);
}
cache_set($cid, $this->fields);
} catch (Exception $e) {
watchdog('sarnia', 'Could not connect to server %server, %message', array(
'%server' => $this->server->machine_name,
'%message' => $e
->getMessage(),
), WATCHDOG_ERROR);
}
}
return $this->fields;
}
function getFulltextFields($reset = FALSE) {
$fields = $this
->getFilteredFields('fulltext', $reset);
return $fields;
}
function getSortFields($reset = FALSE) {
return $this
->getFilteredFields('sort', $reset);
}
function getDisplayFields($reset = FALSE) {
return $this
->getFilteredFields('display', $reset);
}
function getFilterFields($reset = FALSE) {
return $this
->getFilteredFields('filter', $reset);
}
var $filteredFields;
protected function getFilteredFields($filter, $reset = FALSE) {
$cid = "search_api_solr:fields:{$this->server->machine_name}:{$filter}";
if (!isset($this->filteredFields[$filter]) && !$reset) {
$cache = cache_get($cid);
if (isset($cache->data)) {
$this->filteredFields[$filter] = $cache->data;
}
}
if (!isset($this->filteredFields[$filter]) || $reset) {
$this->filteredFields[$filter] = $this
->_getFilteredFields($filter, $reset);
$this
->schemaApplyRules($this->filteredFields[$filter], $filter);
drupal_alter('sarnia_solr_service_filter_fields', $this->filteredFields[$filter], $filter, $this);
cache_set($cid, $this->filteredFields[$filter]);
}
return $this->filteredFields[$filter];
}
function _getFilteredFields($filter, $reset = FALSE) {
$fields = array();
$filter_method = $this
->getFieldFilterMethod($filter);
if ($filter_method) {
foreach ($this
->getRemoteFields($reset) as $name => $field) {
if ($field
->{$filter_method}()) {
$fields[$name] = $field;
}
}
}
return $fields;
}
protected function getFieldFilterMethod($filter) {
$methods = array(
'fulltext' => 'isFulltextSearchable',
'sort' => 'isSortable',
'display' => 'isStored',
'filter' => 'isFilterable',
);
return $methods[$filter];
}
var $schema;
function schemaApplyRules(&$fields, $filter) {
$result_fields = array();
$all_fields = $this
->getRemoteFields();
foreach ($fields as $name => $field) {
$result_fields[$name] = $field;
if ($rule = $this
->schemaGetRule($field, $filter)) {
if ($rule->effect == 'disable') {
unset($result_fields[$name]);
}
elseif ($rule->effect == 'replace' && isset($rule->replacement)) {
$replacement = NULL;
if ($rule->match_type == 'name') {
$replacement = $rule->replacement;
}
elseif ($rule->match_type == 'dynamicBase') {
$replacement = str_replace(trim($rule->match_value, '*'), trim($rule->replacement, '*'), $name);
}
if ($replacement && is_object($all_fields[$replacement])) {
$result_fields[$replacement] = $field;
unset($result_fields[$name]);
}
}
}
}
ksort($result_fields);
$fields = $result_fields;
}
function schemaGetRule($field, $filter) {
if (!isset($this->schema)) {
$this
->schemaInit();
}
if (isset($this->schema[$filter])) {
foreach ($this->schema[$filter] as $rule) {
if ((!$rule->search_api_server || $rule->search_api_server == $this->server->machine_name) && ($rule->match_type == 'name' && $rule->match_value == $field
->getName() || $rule->match_type == 'dynamicBase' && $rule->match_value == $field
->getDynamicBase() || $rule->match_type == 'type' && $rule->match_value == $field
->getType())) {
return $rule;
}
}
}
return FALSE;
}
function schemaInit() {
$this->schema = array();
$conditions = array(
'search_api_server' => array(
'',
$this->server->machine_name,
),
'enabled' => TRUE,
);
$rules = module_invoke_all('sarnia_solr_service_schema', $conditions);
drupal_alter('sarnia_solr_service_schema', $rules);
foreach ($rules as $rule) {
$this->schema[$rule->behavior][] = $rule;
}
}
protected function createFilterQuery($field, $value, $operator, $field_info) {
$filter = parent::createFilterQuery($field, $value, $operator, $field_info);
return "({$filter})";
}
protected function formatFilterValue($value, $type) {
switch ($type) {
case 'boolean':
$value = $value ? 'true' : 'false';
break;
case 'date':
$value = is_numeric($value) ? (int) $value : strtotime($value);
if ($value === FALSE) {
return 0;
}
$value = format_date($value, 'custom', self::SOLR_DATE_FORMAT, 'UTC');
break;
}
return SarniaSolrService::phrase($value);
}
public static function phrase($value) {
$value = str_replace('\\', '\\\\', $value);
$value = preg_replace('/[:(){}\\[\\]]/', '\\\\\\0', $value);
$value = preg_replace('/^(AND|OR|NOT|\\*|[+-])/', '\\\\\\0', $value);
if (substr_count($value, '"') % 2 != 0) {
$value = str_replace('"', '\\"', $value);
}
return $value;
}
protected function extractResults(SearchApiQueryInterface $query, $response) {
$index = $query
->getIndex();
$fields = $this
->getFieldNames($index);
$field_options = $index->options['fields'];
$version = $this->solr
->getSolrVersion();
$results = array();
$results['results'] = array();
$results['search_api_solr_response'] = $response;
if (!isset($response->response) && !isset($response->grouped)) {
$results['result count'] = 0;
return $results;
}
$grouping = $query
->getOption('search_api_grouping');
if (!empty($grouping['use_grouping']) && !empty($response->grouped)) {
$docs = array();
$results['result count'] = 0;
foreach ($grouping['fields'] as $field) {
if (!empty($response->grouped->{$field})) {
$results['result count'] += $response->grouped->{$field}->ngroups;
foreach ($response->grouped->{$field}->groups as $group) {
foreach ($group->doclist->docs as $doc) {
$docs[] = $doc;
}
}
}
}
}
else {
$results['result count'] = $response->response->numFound;
$docs = $response->response->docs;
}
$spatials = $query
->getOption('search_api_location');
foreach ($docs as $doc) {
$result = array(
'id' => NULL,
'score' => NULL,
'fields' => array(),
);
foreach ($fields as $search_api_property => $solr_property) {
if (isset($doc->{$solr_property})) {
$result['fields'][$search_api_property] = $doc->{$solr_property};
if (isset($field_options[$search_api_property]['type']) && $field_options[$search_api_property]['type'] == 'date') {
if (!is_array($result['fields'][$search_api_property])) {
if (preg_match('/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/', $result['fields'][$search_api_property])) {
$result['fields'][$search_api_property] = strtotime($result['fields'][$search_api_property]);
}
}
else {
$date_values = array_values($result['fields'][$search_api_property]);
for ($i = 0; $i < count($date_values); $i++) {
if (preg_match('/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/', $date_values[$i])) {
$result['fields'][$search_api_property][$i] = strtotime($date_values[$i]);
}
}
}
}
}
}
$result['id'] = $result['fields']['search_api_id'];
$result['score'] = $result['fields']['search_api_relevance'];
if ($spatials) {
foreach ($spatials as $spatial) {
if (isset($spatial['field']) && !empty($spatial['distance'])) {
if ($version >= 4) {
$doc_field = '_' . $fields[$spatial['field']] . '_distance_';
if (!empty($doc->{$doc_field})) {
$results['search_api_location'][$spatial['field']][$result['id']]['distance'] = $doc->{$doc_field};
}
}
}
}
}
$excerpt = $this
->getExcerpt($response, $result['fields']['id'], $result['fields'], $fields, $query
->getFields());
if ($excerpt) {
$result['excerpt'] = $excerpt;
}
if ($result['id']) {
$results['results'][$result['id']] = $result;
}
}
if (module_exists('search_api_spellcheck') && $query
->getOption('search_api_spellcheck')) {
$results['search_api_spellcheck'] = new SearchApiSpellcheckSolr($response);
}
return $results;
}
}