updated and repatched search_api module
please check this thread : Decide on strategy for language aware search https://www.drupal.org/node/1393058
This commit is contained in:
@@ -193,6 +193,12 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
|
||||
return isset($a) ? min($a, $b) : $b;
|
||||
case 'first':
|
||||
return isset($a) ? $a : $b;
|
||||
case 'list':
|
||||
if (!isset($a)) {
|
||||
$a = array();
|
||||
}
|
||||
$a[] = $b;
|
||||
return $a;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,6 +267,7 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
|
||||
'max' => t('Maximum'),
|
||||
'min' => t('Minimum'),
|
||||
'first' => t('First'),
|
||||
'list' => t('List'),
|
||||
);
|
||||
case 'type':
|
||||
return array(
|
||||
@@ -270,6 +277,7 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
|
||||
'max' => 'integer',
|
||||
'min' => 'integer',
|
||||
'first' => 'string',
|
||||
'list' => 'list<string>',
|
||||
);
|
||||
case 'description':
|
||||
return array(
|
||||
@@ -279,6 +287,7 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
|
||||
'max' => t('The Maximum aggregation computes the numerically largest contained field value.'),
|
||||
'min' => t('The Minimum aggregation computes the numerically smallest contained field value.'),
|
||||
'first' => t('The First aggregation will simply keep the first encountered field value. This is helpful foremost when you know that a list field will only have a single value.'),
|
||||
'list' => t('The List aggregation collects all field values into a multi-valued field containing all values.'),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -289,6 +298,8 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
|
||||
public function formButtonSubmit(array $form, array &$form_state) {
|
||||
$button_name = $form_state['triggering_element']['#name'];
|
||||
if ($button_name == 'op') {
|
||||
// Increment $i until the corresponding field is not set, then create the
|
||||
// field with that number as suffix.
|
||||
for ($i = 1; isset($this->options['fields']['search_api_aggregation_' . $i]); ++$i) {
|
||||
}
|
||||
$this->options['fields']['search_api_aggregation_' . $i] = array(
|
||||
|
@@ -172,20 +172,25 @@ class SearchApiIndex extends Entity {
|
||||
/**
|
||||
* Constructor as a helper to the parent constructor.
|
||||
*/
|
||||
public function __construct(array $values = array()) {
|
||||
parent::__construct($values, 'search_api_index');
|
||||
public function __construct(array $values = array(), $entity_type = 'search_api_index') {
|
||||
parent::__construct($values, $entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute necessary tasks for a newly created index.
|
||||
*/
|
||||
public function postCreate() {
|
||||
if ($this->enabled) {
|
||||
$this->queueItems();
|
||||
try {
|
||||
if ($server = $this->server()) {
|
||||
// Tell the server about the new index.
|
||||
$server->addIndex($this);
|
||||
if ($this->enabled) {
|
||||
$this->queueItems();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($server = $this->server()) {
|
||||
// Tell the server about the new index.
|
||||
$server->addIndex($this);
|
||||
catch (SearchApiException $e) {
|
||||
watchdog_exception('search_api', $e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,8 +198,13 @@ class SearchApiIndex extends Entity {
|
||||
* Execute necessary tasks when the index is removed from the database.
|
||||
*/
|
||||
public function postDelete() {
|
||||
if ($server = $this->server()) {
|
||||
$server->removeIndex($this);
|
||||
try {
|
||||
if ($server = $this->server()) {
|
||||
$server->removeIndex($this);
|
||||
}
|
||||
}
|
||||
catch (SearchApiException $e) {
|
||||
watchdog_exception('search_api', $e);
|
||||
}
|
||||
|
||||
// Stop tracking entities for indexing.
|
||||
@@ -206,7 +216,12 @@ class SearchApiIndex extends Entity {
|
||||
*/
|
||||
public function queueItems() {
|
||||
if (!$this->read_only) {
|
||||
$this->datasource()->startTracking(array($this));
|
||||
try {
|
||||
$this->datasource()->startTracking(array($this));
|
||||
}
|
||||
catch (SearchApiException $e) {
|
||||
watchdog_exception('search_api', $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +229,12 @@ class SearchApiIndex extends Entity {
|
||||
* Remove all records of entities to index.
|
||||
*/
|
||||
public function dequeueItems() {
|
||||
$this->datasource()->stopTracking(array($this));
|
||||
try {
|
||||
$this->datasource()->stopTracking(array($this));
|
||||
}
|
||||
catch (SearchApiException $e) {
|
||||
watchdog_exception('search_api', $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,16 +251,25 @@ class SearchApiIndex extends Entity {
|
||||
if (empty($this->description)) {
|
||||
$this->description = NULL;
|
||||
}
|
||||
if (empty($this->server)) {
|
||||
$server = FALSE;
|
||||
if (!empty($this->server)) {
|
||||
$server = search_api_server_load($this->server);
|
||||
if (!$server) {
|
||||
$vars['%server'] = $this->server;
|
||||
$vars['%index'] = $this->name;
|
||||
watchdog('search_api', 'Unknown server %server specified for index %index.', $vars, WATCHDOG_ERROR);
|
||||
}
|
||||
}
|
||||
if (!$server) {
|
||||
$this->server = NULL;
|
||||
$this->enabled = FALSE;
|
||||
}
|
||||
// This will also throw an exception if the server doesn't exist – which is good.
|
||||
elseif (!$this->server(TRUE)->enabled) {
|
||||
$this->enabled = FALSE;
|
||||
$this->server = NULL;
|
||||
if (!empty($this->options['fields'])) {
|
||||
ksort($this->options['fields']);
|
||||
}
|
||||
|
||||
$this->resetCaches();
|
||||
|
||||
return parent::save();
|
||||
}
|
||||
|
||||
@@ -305,7 +334,12 @@ class SearchApiIndex extends Entity {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
$this->server()->deleteItems('all', $this);
|
||||
try {
|
||||
$this->server()->deleteItems('all', $this);
|
||||
}
|
||||
catch (SearchApiException $e) {
|
||||
watchdog_exception('search_api', $e);
|
||||
}
|
||||
|
||||
_search_api_index_reindex($this);
|
||||
module_invoke_all('search_api_index_reindex', $this, TRUE);
|
||||
@@ -350,7 +384,12 @@ class SearchApiIndex extends Entity {
|
||||
* otherwise.
|
||||
*/
|
||||
public function getEntityType() {
|
||||
return $this->datasource()->getEntityType();
|
||||
try {
|
||||
return $this->datasource()->getEntityType();
|
||||
}
|
||||
catch (SearchApiException $e) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -385,7 +424,7 @@ class SearchApiIndex extends Entity {
|
||||
* SearchApiQueryInterface::__construct().
|
||||
*
|
||||
* @throws SearchApiException
|
||||
* If the index is currently disabled.
|
||||
* If the index is currently disabled or its server doesn't exist.
|
||||
*
|
||||
* @return SearchApiQueryInterface
|
||||
* A query object for searching this index.
|
||||
@@ -399,15 +438,20 @@ class SearchApiIndex extends Entity {
|
||||
|
||||
|
||||
/**
|
||||
* Indexes items on this index. Will return an array of IDs of items that
|
||||
* should be marked as indexed – i.e., items that were either rejected by a
|
||||
* data-alter callback or were successfully indexed.
|
||||
* Indexes items on this index.
|
||||
*
|
||||
* Will return an array of IDs of items that should be marked as indexed –
|
||||
* i.e., items that were either rejected by a data-alter callback or were
|
||||
* successfully indexed.
|
||||
*
|
||||
* @param array $items
|
||||
* An array of items to index.
|
||||
* An array of items to index, of this index's item type.
|
||||
*
|
||||
* @return array
|
||||
* An array of the IDs of all items that should be marked as indexed.
|
||||
*
|
||||
* @throws SearchApiException
|
||||
* If an error occurred during indexing.
|
||||
*/
|
||||
public function index(array $items) {
|
||||
if ($this->read_only) {
|
||||
@@ -925,12 +969,18 @@ class SearchApiIndex extends Entity {
|
||||
* @return EntityMetadataWrapper
|
||||
* A wrapper for the item type of this index, optionally loaded with the
|
||||
* given data and having additional fields according to the data alterations
|
||||
* of this index.
|
||||
* of this index (if $alter wasn't set to FALSE).
|
||||
*/
|
||||
public function entityWrapper($item = NULL, $alter = TRUE) {
|
||||
$info['property info alter'] = $alter ? array($this, 'propertyInfoAlter') : '_search_api_wrapper_add_all_properties';
|
||||
$info['property defaults']['property info alter'] = '_search_api_wrapper_add_all_properties';
|
||||
return $this->datasource()->getMetadataWrapper($item, $info);
|
||||
try {
|
||||
$info['property info alter'] = $alter ? array($this, 'propertyInfoAlter') : '_search_api_wrapper_add_all_properties';
|
||||
$info['property defaults']['property info alter'] = '_search_api_wrapper_add_all_properties';
|
||||
return $this->datasource()->getMetadataWrapper($item, $info);
|
||||
}
|
||||
catch (SearchApiException $e) {
|
||||
watchdog_exception('search_api', $e);
|
||||
return entity_metadata_wrapper($this->item_type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -945,16 +995,24 @@ class SearchApiIndex extends Entity {
|
||||
* @see SearchApiDataSourceControllerInterface::loadItems()
|
||||
*/
|
||||
public function loadItems(array $ids) {
|
||||
return $this->datasource()->loadItems($ids);
|
||||
try {
|
||||
return $this->datasource()->loadItems($ids);
|
||||
}
|
||||
catch (SearchApiException $e) {
|
||||
watchdog_exception('search_api', $e);
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset internal static caches.
|
||||
* Reset internal caches.
|
||||
*
|
||||
* Should be used when things like fields or data alterations change to avoid
|
||||
* using stale data.
|
||||
*/
|
||||
public function resetCaches() {
|
||||
cache_clear_all($this->getCacheId(''), 'cache', TRUE);
|
||||
|
||||
$this->datasource = NULL;
|
||||
$this->server_object = NULL;
|
||||
$this->callbacks = NULL;
|
||||
|
@@ -22,8 +22,6 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
/**
|
||||
* PREG regular expression for splitting words.
|
||||
*
|
||||
* We highlight around non-indexable or CJK characters.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $split;
|
||||
@@ -40,7 +38,7 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
'\x{F900}-\x{FAFF}\x{FF21}-\x{FF3A}\x{FF41}-\x{FF5A}\x{FF66}-\x{FFDC}' .
|
||||
'\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}';
|
||||
self::$boundary = '(?:(?<=[' . PREG_CLASS_UNICODE_WORD_BOUNDARY . $cjk . '])|(?=[' . PREG_CLASS_UNICODE_WORD_BOUNDARY . $cjk . ']))';
|
||||
self::$split = '/[' . PREG_CLASS_UNICODE_WORD_BOUNDARY . $cjk . ']+/iu';
|
||||
self::$split = '/[' . PREG_CLASS_UNICODE_WORD_BOUNDARY . ']+/iu';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,6 +51,7 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
'excerpt' => TRUE,
|
||||
'excerpt_length' => 256,
|
||||
'highlight' => 'always',
|
||||
'exclude_fields' => array(),
|
||||
);
|
||||
|
||||
$form['prefix'] = array(
|
||||
@@ -87,6 +86,22 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
),
|
||||
),
|
||||
);
|
||||
// Exclude certain fulltextfields
|
||||
$fields = $this->index->getFields();
|
||||
$fulltext_fields = array();
|
||||
foreach ($this->index->getFulltextFields() as $field) {
|
||||
if (isset($fields[$field])) {
|
||||
$fulltext_fields[$field] = $fields[$field]['name'] . ' (' . $field . ')';
|
||||
}
|
||||
}
|
||||
$form['exclude_fields'] = array(
|
||||
'#type' => 'checkboxes',
|
||||
'#title' => t('Exclude fields from excerpt'),
|
||||
'#description' => t('Exclude certain fulltext fields from being displayed in the excerpt.'),
|
||||
'#options' => $fulltext_fields,
|
||||
'#default_value' => $this->options['exclude_fields'],
|
||||
'#attributes' => array('class' => array('search-api-checkboxes-list')),
|
||||
);
|
||||
$form['highlight'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Highlight returned field data'),
|
||||
@@ -106,21 +121,29 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function configurationFormValidate(array $form, array &$values, array &$form_state) {
|
||||
// Overridden so $form['fields'] is not checked.
|
||||
$values['exclude_fields'] = array_filter($values['exclude_fields']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postprocessSearchResults(array &$response, SearchApiQuery $query) {
|
||||
if (!$response['result count'] || !($keys = $this->getKeywords($query))) {
|
||||
if (empty($response['results']) || !($keys = $this->getKeywords($query))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fulltext_fields = $this->index->getFulltextFields();
|
||||
if (!empty($this->options['exclude_fields'])) {
|
||||
$fulltext_fields = drupal_map_assoc($fulltext_fields);
|
||||
foreach ($this->options['exclude_fields'] as $field) {
|
||||
unset($fulltext_fields[$field]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($response['results'] as $id => &$result) {
|
||||
if ($this->options['excerpt']) {
|
||||
$text = array();
|
||||
$fields = $this->getFulltextFields($response['results'], $id);
|
||||
$fields = $this->getFulltextFields($response['results'], $id, $fulltext_fields);
|
||||
foreach ($fields as $data) {
|
||||
if (is_array($data)) {
|
||||
$text = array_merge($text, $data);
|
||||
@@ -129,10 +152,11 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
$text[] = $data;
|
||||
}
|
||||
}
|
||||
$result['excerpt'] = $this->createExcerpt(implode("\n\n", $text), $keys);
|
||||
|
||||
$result['excerpt'] = $this->createExcerpt($this->flattenArrayValues($text), $keys);
|
||||
}
|
||||
if ($this->options['highlight'] != 'never') {
|
||||
$fields = $this->getFulltextFields($response['results'], $id, $this->options['highlight'] == 'always');
|
||||
$fields = $this->getFulltextFields($response['results'], $id, $fulltext_fields, $this->options['highlight'] == 'always');
|
||||
foreach ($fields as $field => $data) {
|
||||
if (is_array($data)) {
|
||||
foreach ($data as $i => $text) {
|
||||
@@ -155,6 +179,8 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
* @param int|string $i
|
||||
* The index in the results array of the result whose data should be
|
||||
* returned.
|
||||
* @param array $fulltext_fields
|
||||
* The fulltext fields from which the excerpt should be created.
|
||||
* @param bool $load
|
||||
* TRUE if the item should be loaded if necessary, FALSE if only fields
|
||||
* already returned in the results should be used.
|
||||
@@ -163,7 +189,7 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
* An array containing fulltext field names mapped to the text data
|
||||
* contained in them for the given result.
|
||||
*/
|
||||
protected function getFulltextFields(array &$results, $i, $load = TRUE) {
|
||||
protected function getFulltextFields(array &$results, $i, array $fulltext_fields, $load = TRUE) {
|
||||
global $language;
|
||||
$data = array();
|
||||
|
||||
@@ -171,7 +197,6 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
// Act as if $load is TRUE if we have a loaded item.
|
||||
$load |= !empty($result['entity']);
|
||||
$result += array('fields' => array());
|
||||
$fulltext_fields = $this->index->getFulltextFields();
|
||||
// We only need detailed fields data if $load is TRUE.
|
||||
$fields = $load ? $this->index->getFields() : array();
|
||||
$needs_extraction = array();
|
||||
@@ -309,7 +334,7 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
// Locate a keyword (position $p, always >0 because $text starts with a
|
||||
// space).
|
||||
$p = 0;
|
||||
if (preg_match('/' . self::$boundary . $key . self::$boundary . '/iu', $text, $match, PREG_OFFSET_CAPTURE, $included[$key])) {
|
||||
if (preg_match('/' . self::$boundary . preg_quote($key, '/') . self::$boundary . '/iu', $text, $match, PREG_OFFSET_CAPTURE, $included[$key])) {
|
||||
$p = $match[0][1];
|
||||
}
|
||||
// Now locate a space in front (position $q) and behind it (position $s),
|
||||
@@ -379,7 +404,9 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
$text = (isset($newranges[0]) ? '' : $dots[0]) . implode($dots[1], $out) . $dots[2];
|
||||
$text = check_plain($text);
|
||||
|
||||
return $this->highlightField($text, $keys);
|
||||
// Since we stripped the tags at the beginning, highlighting doesn't need to
|
||||
// handle HTML anymore.
|
||||
return $this->highlightField($text, $keys, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,15 +416,55 @@ class SearchApiHighlight extends SearchApiAbstractProcessor {
|
||||
* The text of the field.
|
||||
* @param array $keys
|
||||
* Search keywords entered by the user.
|
||||
* @param bool $html
|
||||
* Whether the text can contain HTML tags or not. In the former case, text
|
||||
* inside tags (i.e., tag names and attributes) won't be highlighted.
|
||||
*
|
||||
* @return string
|
||||
* The field's text with all occurrences of search keywords highlighted.
|
||||
*/
|
||||
protected function highlightField($text, array $keys) {
|
||||
protected function highlightField($text, array $keys, $html = TRUE) {
|
||||
if (is_array($text)) {
|
||||
$text = $this->flattenArrayValues($text);
|
||||
}
|
||||
|
||||
if ($html) {
|
||||
$texts = preg_split('#((?:</?[[:alpha:]](?:[^>"\']*|"[^"]*"|\'[^\']\')*>)+)#i', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
for ($i = 0; $i < count($texts); $i += 2) {
|
||||
$texts[$i] = $this->highlightField($texts[$i], $keys, FALSE);
|
||||
}
|
||||
return implode('', $texts);
|
||||
}
|
||||
$replace = $this->options['prefix'] . '\0' . $this->options['suffix'];
|
||||
$keys = implode('|', array_map('preg_quote', $keys));
|
||||
|
||||
$keys = implode('|', array_map('preg_quote', $keys, array_fill(0, count($keys), '/')));
|
||||
$text = preg_replace('/' . self::$boundary . '(' . $keys . ')' . self::$boundary . '/iu', $replace, ' ' . $text . ' ');
|
||||
return substr($text, 1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens a (possibly multidimensional) array into a string.
|
||||
*
|
||||
* @param array $array
|
||||
* The array to flatten.
|
||||
* @param string $glue
|
||||
* The separator to insert between individual array items.
|
||||
*
|
||||
* @return string
|
||||
* The glued string.
|
||||
*/
|
||||
protected function flattenArrayValues(array $array, $glue = "\n\n") {
|
||||
$ret = array();
|
||||
foreach ($array as $item) {
|
||||
if (is_array($item)) {
|
||||
$ret[] = $this->flattenArrayValues($item, $glue);
|
||||
}
|
||||
else {
|
||||
$ret[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return implode($glue, $ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -102,6 +102,8 @@ class SearchApiHtmlFilter extends SearchApiAbstractProcessor {
|
||||
}
|
||||
else {
|
||||
$value = strip_tags($text);
|
||||
// Remove any multiple or leading/trailing spaces we might have introduced.
|
||||
$value = preg_replace('/\s\s+/', ' ', trim($value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,8 +111,11 @@ class SearchApiHtmlFilter extends SearchApiAbstractProcessor {
|
||||
$ret = array();
|
||||
while (($pos = strpos($text, '<')) !== FALSE) {
|
||||
if ($boost && $pos > 0) {
|
||||
$token = html_entity_decode(substr($text, 0, $pos), ENT_QUOTES, 'UTF-8');
|
||||
// Remove any multiple or leading/trailing spaces we might have introduced.
|
||||
$token = preg_replace('/\s\s+/', ' ', trim($token));
|
||||
$ret[] = array(
|
||||
'value' => html_entity_decode(substr($text, 0, $pos), ENT_QUOTES, 'UTF-8'),
|
||||
'value' => $token,
|
||||
'score' => $boost,
|
||||
);
|
||||
}
|
||||
@@ -130,8 +135,11 @@ class SearchApiHtmlFilter extends SearchApiAbstractProcessor {
|
||||
}
|
||||
}
|
||||
if ($text) {
|
||||
$token = html_entity_decode($text, ENT_QUOTES, 'UTF-8');
|
||||
// Remove any multiple or leading/trailing spaces we might have introduced.
|
||||
$token = preg_replace('/\s\s+/', ' ', trim($token));
|
||||
$ret[] = array(
|
||||
'value' => html_entity_decode($text, ENT_QUOTES, 'UTF-8'),
|
||||
'value' => $token,
|
||||
'score' => $boost,
|
||||
);
|
||||
$text = '';
|
||||
|
@@ -226,6 +226,9 @@ interface SearchApiQueryInterface {
|
||||
*
|
||||
* This method should always be called by execute() and contain all necessary
|
||||
* operations before the query is passed to the server's search() method.
|
||||
*
|
||||
* @throws SearchApiException
|
||||
* If any error occurred during the preparation of the query.
|
||||
*/
|
||||
public function preExecute();
|
||||
|
||||
@@ -366,7 +369,7 @@ class SearchApiQuery implements SearchApiQueryInterface {
|
||||
/**
|
||||
* The index's machine name.
|
||||
*
|
||||
* used during serialization to avoid serializing the whole index object.
|
||||
* Used during serialization to avoid serializing the whole index object.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
@@ -811,6 +814,31 @@ class SearchApiQuery implements SearchApiQueryInterface {
|
||||
$this->filter = clone $this->filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the magic __toString() method to simplify debugging.
|
||||
*/
|
||||
public function __toString() {
|
||||
$ret = 'Index: ' . $this->index->machine_name . "\n";
|
||||
$ret .= 'Keys: ' . str_replace("\n", "\n ", var_export($this->orig_keys, TRUE)) . "\n";
|
||||
if (isset($this->keys)) {
|
||||
$ret .= 'Parsed keys: ' . str_replace("\n", "\n ", var_export($this->keys, TRUE)) . "\n";
|
||||
$ret .= 'Searched fields: ' . (isset($this->fields) ? implode(', ', $this->fields) : '[ALL]') . "\n";
|
||||
}
|
||||
if ($filter = (string) $this->filter) {
|
||||
$filter = str_replace("\n", "\n ", $filter);
|
||||
$ret .= "Filters:\n $filter\n";
|
||||
}
|
||||
if ($this->sort) {
|
||||
$sort = array();
|
||||
foreach ($this->sort as $field => $order) {
|
||||
$sort[] = "$field $order";
|
||||
}
|
||||
$ret .= 'Sorting: ' . implode(', ', $sort) . "\n";
|
||||
}
|
||||
$ret .= 'Options: ' . str_replace("\n", "\n ", var_export($this->options, TRUE)) . "\n";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -890,8 +918,11 @@ interface SearchApiQueryFilterInterface {
|
||||
* Return all conditions and nested filters contained in this filter.
|
||||
*
|
||||
* @return array
|
||||
* An array containing this filter's subfilters. Each of these is either an
|
||||
* array (field, value, operator), or another SearchApiFilter object.
|
||||
* An array containing this filter's subfilters. Each of these is either a
|
||||
* condition, represented as a numerically indexed array with the arguments
|
||||
* of a previous SearchApiQueryFilterInterface::condition() call (field,
|
||||
* value, operator); or a nested filter, represented by a
|
||||
* SearchApiQueryFilterInterface filter object.
|
||||
*/
|
||||
public function &getFilters();
|
||||
|
||||
@@ -1010,4 +1041,24 @@ class SearchApiQueryFilter implements SearchApiQueryFilterInterface {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the magic __toString() method to simplify debugging.
|
||||
*/
|
||||
public function __toString() {
|
||||
// Special case for a single, nested filter:
|
||||
if (count($this->filters) == 1 && is_object($this->filters[0])) {
|
||||
return (string) $this->filters[0];
|
||||
}
|
||||
$ret = array();
|
||||
foreach ($this->filters as $filter) {
|
||||
if (is_object($filter)) {
|
||||
$ret[] = "[\n " . str_replace("\n", "\n ", (string) $filter) . "\n ]";
|
||||
}
|
||||
else {
|
||||
$ret[] = "$filter[0] $filter[2] " . str_replace("\n", "\n ", var_export($filter[1], TRUE));
|
||||
}
|
||||
}
|
||||
return $ret ? ' ' . implode("\n{$this->conjunction}\n ", $ret) : '';
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -74,8 +74,8 @@ class SearchApiServer extends Entity {
|
||||
/**
|
||||
* Constructor as a helper to the parent constructor.
|
||||
*/
|
||||
public function __construct(array $values = array()) {
|
||||
parent::__construct($values, 'search_api_server');
|
||||
public function __construct(array $values = array(), $entity_type = 'search_api_server') {
|
||||
parent::__construct($values, $entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user