@@ -27,7 +54,7 @@ class SearchApiViewsHandlerFilterFulltext extends SearchApiViewsHandlerFilterTex
'#title' => t('Use as'),
'#title' => t('Use as'),
'#type' => 'radios',
'#type' => 'radios',
'#options' => array(
'#options' => array(
- 'keys' => t('Search keys – multiple words will be split and the filter will influence relevance.'),
+ 'keys' => t('Search keys – multiple words will be split and the filter will influence relevance. You can change how search keys are parsed under "Advanced" > "Query settings".'),
'filter' => t("Search filter – use as a single phrase that restricts the result set but doesn't influence relevance."),
'filter' => t("Search filter – use as a single phrase that restricts the result set but doesn't influence relevance."),
),
),
'#default_value' => $this->options['mode'],
'#default_value' => $this->options['mode'],
@@ -54,6 +81,70 @@ class SearchApiViewsHandlerFilterFulltext extends SearchApiViewsHandlerFilterTex
if (isset($form['expose'])) {
if (isset($form['expose'])) {
$form['expose']['#weight'] = -5;
$form['expose']['#weight'] = -5;
}
}
+
+ $form['min_length'] = array(
+ '#title' => t('Minimum keyword length'),
+ '#description' => t('Minimum length of each word in the search keys. Leave empty to allow all words.'),
+ watchdog('search_api_views', 'Tried to sort results randomly on server %server which does not support random sorting.', $variables, WATCHDOG_WARNING);
+ }
+ }
}
}
/**
/**
* Defines the options used by this query plugin.
* Defines the options used by this query plugin.
*
*
- * Adds an option to bypass access checks.
+ * Adds some access options.
*/
*/
public function option_definition() {
public function option_definition() {
return parent::option_definition() + array(
return parent::option_definition() + array(
'search_api_bypass_access' => array(
'search_api_bypass_access' => array(
'default' => FALSE,
'default' => FALSE,
),
),
+ 'entity_access' => array(
+ 'default' => FALSE,
+ ),
+ 'parse_mode' => array(
+ 'default' => 'terms',
+ ),
);
);
}
}
@@ -150,12 +214,45 @@ class SearchApiViewsQuery extends views_plugin_query {
'#description' => t('If the underlying search index has access checks enabled, this option allows to disable them for this view.'),
'#description' => t('If the underlying search index has access checks enabled, this option allows to disable them for this view.'),
+ if ($this->index && $this->index->getEntityType()) {
+ $form['entity_access'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Additional access checks on result entities'),
+ '#description' => t("Execute an access check for all result entities. This prevents users from seeing inappropriate content when the index contains stale data, or doesn't provide access checks. However, result counts, paging and other things won't work correctly if results are eliminated in this way, so only use this as a last ressort (and in addition to other checks, if possible)."),
+ watchdog('search_api_views', 'The search index returned a reference to an entity with ID @id, which does not exist in the database. Your index may be out of sync and should be rebuilt.', array('@id' => $id), WATCHDOG_ERROR);
+ }
}
}
catch (EntityMetadataWrapperException $e) {
catch (EntityMetadataWrapperException $e) {
- // Ignore.
+ watchdog_exception('search_api_views', $e, "%type while trying to load search result entity with ID @id: !message in %function (line %line of %file).", array('@id' => $id), WATCHDOG_ERROR);
}
}
}
}
return array($type, $return);
return array($type, $return);
@@ -371,31 +547,31 @@ class SearchApiViewsQuery extends views_plugin_query {
* query backend.
* query backend.
*/
*/
public function get_result_wrappers($results, $relationship = NULL, $field = NULL) {
public function get_result_wrappers($results, $relationship = NULL, $field = NULL) {
+ watchdog_exception('search_api_views', $e, "%type while retrieving metadata for index %index: !message in %function (line %line of %file).", array('%index' => $index->name), WATCHDOG_WARNING);
+ continue;
+ }
// Add field handlers and relationships provided by the Entity API.
// Add field handlers and relationships provided by the Entity API.
foreach ($wrapper as $key => $property) {
foreach ($wrapper as $key => $property) {
@@ -37,6 +43,14 @@ function search_api_views_views_data() {
}
}
}
}
+ try {
+ $wrapper = $index->entityWrapper(NULL);
+ }
+ catch (EntityMetadataWrapperException $e) {
+ watchdog_exception('search_api_views', $e, "%type while retrieving metadata for index %index: !message in %function (line %line of %file).", array('%index' => $index->name), WATCHDOG_WARNING);
+ continue;
+ }
+
// Add handlers for all indexed fields.
// Add handlers for all indexed fields.
foreach ($index->getFields() as $key => $field) {
foreach ($index->getFields() as $key => $field) {
$tmp = $wrapper;
$tmp = $wrapper;
@@ -63,7 +77,7 @@ function search_api_views_views_data() {
+ '#description' => t('For aggregation type "Fulltext", set the text that should be used to separate the aggregated field values. Use "\t" for tabs and "\n" for newline characters.'),
form_error($form['fields'][$name]['fields'], t('You have to select at least one field to aggregate. If you want to remove an aggregated field, please delete its name.'));
form_error($form['fields'][$name]['fields'], t('You have to select at least one field to aggregate. If you want to remove an aggregated field, please delete its name.'));
@@ -184,7 +231,22 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
return isset($a) ? min($a, $b) : $b;
return isset($a) ? min($a, $b) : $b;
case 'first':
case 'first':
return isset($a) ? $a : $b;
return isset($a) ? $a : $b;
+ case 'first_char':
+ $b = "$b";
+ if (isset($a) || $b === '') {
+ return $a;
+ }
+ return drupal_substr($b, 0, 1);
+ case 'last':
+ return isset($b) ? $b : $a;
+ case 'list':
+ if (!isset($a)) {
+ $a = array();
+ }
+ $a[] = $b;
+ return $a;
}
}
+ return NULL;
}
}
/**
/**
@@ -237,10 +299,13 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
/**
/**
* Helper method for getting all available aggregation types.
* Helper method for getting all available aggregation types.
*
*
- * @param $info (optional)
- * One of "name", "type" or "description", to indicate what values should be
- * returned for the types. Defaults to "name".
+ * @param string $info
+ * (optional) One of "name", "type" or "description", to indicate what
+ * information should be returned for the types.
*
*
+ * @return string[]
+ * An associative array of aggregation type identifiers mapped to their
+ * names, data types or descriptions, as requested.
*/
*/
protected function getTypes($info = 'name') {
protected function getTypes($info = 'name') {
switch ($info) {
switch ($info) {
@@ -252,6 +317,9 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
'max' => t('Maximum'),
'max' => t('Maximum'),
'min' => t('Minimum'),
'min' => t('Minimum'),
'first' => t('First'),
'first' => t('First'),
+ 'first_char' => t('First letter'),
+ 'last' => t('Last'),
+ 'list' => t('List'),
);
);
case 'type':
case 'type':
return array(
return array(
@@ -260,7 +328,10 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
'count' => 'integer',
'count' => 'integer',
'max' => 'integer',
'max' => 'integer',
'min' => 'integer',
'min' => 'integer',
- 'first' => 'string',
+ 'first' => 'token',
+ 'first_char' => 'token',
+ 'last' => 'token',
+ 'list' => 'list<token>',
);
);
case 'description':
case 'description':
return array(
return array(
@@ -270,8 +341,12 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
'max' => t('The Maximum aggregation computes the numerically largest contained field value.'),
'max' => t('The Maximum aggregation computes the numerically largest contained field value.'),
'min' => t('The Minimum aggregation computes the numerically smallest 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.'),
'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.'),
+ 'first_char' => t('The "First letter" aggregation uses just the first letter of the first encountered field value as the aggregated value. This can, for example, be used to build a Glossary view.'),
+ 'last' => t('The Last aggregation will simply keep the last encountered field value.'),
+ 'list' => t('The List aggregation collects all field values into a multi-valued field containing all values.'),
);
);
}
}
+ return array();
}
}
/**
/**
@@ -280,6 +355,8 @@ class SearchApiAlterAddAggregation extends SearchApiAbstractAlterCallback {
public function formButtonSubmit(array $form, array &$form_state) {
public function formButtonSubmit(array $form, array &$form_state) {
+ throw new SearchApiDataSourceException(t("Entity type @type doesn't specify an ID key.", array('@type' => $this->entityInfo['label'])));
}
}
- $field = $info['entity keys']['id'];
- if (empty($properties['properties'][$field]['type'])) {
- throw new SearchApiDataSourceException(t("Entity type @type doesn't specify a type for the @prop property.", array('@type' => $info['label'], '@prop' => $field)));
+ if (empty($properties['properties'][$this->idKey]['type'])) {
+ throw new SearchApiDataSourceException(t("Entity type @type doesn't specify a type for the @prop property.", array('@type' => $this->entityInfo['label'], '@prop' => $this->idKey)));
- throw new SearchApiDataSourceException(t("Entity type @type uses list field @prop as its ID.", array('@type' => $info['label'], '@prop' => $field)));
+ throw new SearchApiDataSourceException(t("Entity type @type uses list field @prop as its ID.", array('@type' => $this->entityInfo['label'], '@prop' => $this->idKey)));
}
}
if ($type == 'token') {
if ($type == 'token') {
$type = 'string';
$type = 'string';
}
}
return array(
return array(
- 'key' => $field,
+ 'key' => $this->idKey,
'type' => $type,
'type' => $type,
);
);
}
}
/**
/**
- * Load items of the type of this data source controller.
- *
- * @param array $ids
- * The IDs of the items to laod.
- *
- * @return array
- * The loaded items, keyed by ID.
+ * {@inheritdoc}
*/
*/
public function loadItems(array $ids) {
public function loadItems(array $ids) {
- $items = entity_load($this->type, $ids);
+ $items = entity_load($this->entityType, $ids);
// If some items couldn't be loaded, remove them from tracking.
// If some items couldn't be loaded, remove them from tracking.
if (count($items) != count($ids)) {
if (count($items) != count($ids)) {
$ids = array_flip($ids);
$ids = array_flip($ids);
@@ -65,65 +94,33 @@ class SearchApiEntityDataSourceController extends SearchApiAbstractDataSourceCon
}
}
/**
/**
- * Get a metadata wrapper for the item type of this data source controller.
- *
- * @param $item
- * Unless NULL, an item of the item type for this controller to be wrapped.
- * @param array $info
- * Optionally, additional information that should be used for creating the
- * wrapper. Uses the same format as entity_metadata_wrapper().
- *
- * @return EntityMetadataWrapper
- * A wrapper for the item type of this data source controller, according to
- * the info array, and optionally loaded with the given data.
- *
- * @see entity_metadata_wrapper()
+ * {@inheritdoc}
*/
*/
public function getMetadataWrapper($item = NULL, array $info = array()) {
public function getMetadataWrapper($item = NULL, array $info = array()) {
+ public function trackItemInsert(array $item_ids, array $indexes) {
+ $ret = array();
+
+ foreach ($indexes as $index_id => $index) {
+ $ids = $item_ids;
+ if ($bundles = $this->getIndexBundles($index)) {
+ $ids = drupal_map_assoc($ids);
+ foreach (entity_load($this->entityType, $ids) as $id => $entity) {
+ if (empty($bundles[$entity->{$this->bundleKey}])) {
+ unset($ids[$id]);
+ }
+ }
+ }
+ if ($ids) {
+ parent::trackItemInsert($ids, array($index));
+ $ret[$index_id] = $index;
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function configurationForm(array $form, array &$form_state) {
+ $options = $this->getAvailableBundles();
+ if (!$options) {
+ return FALSE;
+ }
+ $form['bundles'] = array(
+ '#type' => 'checkboxes',
+ '#title' => t('Bundles'),
+ '#description' => t('Restrict the entity bundles that will be included in this index. Leave blank to include all bundles. This setting cannot be changed for enabled indexes.'),
+ '#description' => t('Text/HTML that will be prepended to all occurrences of search keywords in highlighted text.'),
+ '#default_value' => $this->options['prefix'],
+ );
+ $form['suffix'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Highlighting suffix'),
+ '#description' => t('Text/HTML that will be appended to all occurrences of search keywords in highlighted text.'),
+ '#default_value' => $this->options['suffix'],
+ );
+ $form['excerpt'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Create excerpt'),
+ '#description' => t('When enabled, an excerpt will be created for searches with keywords, containing all occurrences of keywords in a fulltext field.'),
+ '#default_value' => $this->options['excerpt'],
+ );
+ $form['excerpt_length'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Excerpt length'),
+ '#description' => t('The requested length of the excerpt, in characters.'),
+ '#markup' => '<p>' . t('Optionally, provide an exclusion list to override the stemmer algorithm. (<a href="@algorithm">Read about the algorithm</a>.)', $args) . '</p>',
+ ),
+ 'exceptions' => array(
+ '#type' => 'textarea',
+ '#title' => t('Exceptions'),
+ '#description' => t('Enter exceptions in the form of WORD=STEM, where "WORD" is the term entered and "STEM" is the resulting stem. List each exception on a separate line.'),
* Processor for removing stopwords from index and search terms.
* Processor for removing stopwords from index and search terms.
*/
*/
class SearchApiStopWords extends SearchApiAbstractProcessor {
class SearchApiStopWords extends SearchApiAbstractProcessor {
+ /**
+ * Holds all words ignored for the last query.
+ *
+ * @var array
+ */
+ protected $ignored = array();
+
public function configurationForm() {
public function configurationForm() {
$form = parent::configurationForm();
$form = parent::configurationForm();
@@ -14,8 +26,7 @@ class SearchApiStopWords extends SearchApiAbstractProcessor {
),
),
'file' => array(
'file' => array(
'#type' => 'textfield',
'#type' => 'textfield',
- '#title' => t('Stopwords file URI'),
- '#title' => t('Enter the URI of your stopwords.txt file'),
+ '#title' => t('Stopwords file'),
'#description' => t('This must be a stream-type description like <code>public://stopwords/stopwords.txt</code> or <code>http://example.com/stopwords.txt</code> or <code>private://stopwords.txt</code>.'),
'#description' => t('This must be a stream-type description like <code>public://stopwords/stopwords.txt</code> or <code>http://example.com/stopwords.txt</code> or <code>private://stopwords.txt</code>.'),
),
),
'stopwords' => array(
'stopwords' => array(
@@ -36,13 +47,8 @@ class SearchApiStopWords extends SearchApiAbstractProcessor {
public function configurationFormValidate(array $form, array &$values, array &$form_state) {
public function configurationFormValidate(array $form, array &$values, array &$form_state) {
public function fieldsUpdated(SearchApiIndex $index) {
public function fieldsUpdated(SearchApiIndex $index) {
$this->ensureProxy();
$this->ensureProxy();
- return $this->proxy->fieldsUpdated($index);
+ try {
+ if ($this->proxy->fieldsUpdated($index)) {
+ _search_api_index_reindex($index);
+ return TRUE;
+ }
+ }
+ catch (SearchApiException $e) {
+ $vars = array(
+ '%server' => $this->name,
+ '%index' => $index->name,
+ );
+ watchdog_exception('search_api', $e, '%type while updating the fields of index %index on server %server: !message in %function (line %line of %file).', $vars);
+ // removeIndex() might throw exceptions, but this method mustn't.
+ try {
+ $this->removeIndex($index);
+ }
+ catch (SearchApiException $e) {
+ $variables['%index'] = $index->name;
+ $variables['%server'] = $this->server->name;
+ watchdog_exception('search_api', $e, '%type while trying to remove index %index from deleted server %server: !message in %function (line %line of %file).', $variables);
@@ -22,6 +22,32 @@ function search_api_drush_command() {
'aliases' => array('sapi-l'),
'aliases' => array('sapi-l'),
);
);
+ $items['search-api-enable'] = array(
+ 'description' => 'Enable one or all disabled search_api indexes.',
+ 'examples' => array(
+ 'drush searchapi-enable' => dt('Enable all disabled indexes.'),
+ 'drush sapi-en' => dt('Alias to enable all disabled indexes.'),
+ 'drush sapi-en 1' => dt('Enable index with the ID !id.', array('!id' => 1)),
+ ),
+ 'arguments' => array(
+ 'index_id' => dt('The numeric ID or machine name of an index to enable.'),
+ ),
+ 'aliases' => array('sapi-en'),
+ );
+
+ $items['search-api-disable'] = array(
+ 'description' => 'Disable one or all enabled search_api indexes.',
+ 'examples' => array(
+ 'drush searchapi-disable' => dt('Disable all enabled indexes.'),
+ 'drush sapi-dis' => dt('Alias to disable all enabled indexes.'),
+ 'drush sapi-dis 1' => dt('Disable index with the ID !id.', array('!id' => 1)),
+ ),
+ 'arguments' => array(
+ 'index_id' => dt('The numeric ID or machine name of an index to disable.'),
+ ),
+ 'aliases' => array('sapi-dis'),
+ );
+
$items['search-api-status'] = array(
$items['search-api-status'] = array(
'description' => 'Show the status of one or all search indexes.',
'description' => 'Show the status of one or all search indexes.',
'examples' => array(
'examples' => array(
@@ -45,9 +71,10 @@ function search_api_drush_command() {
'drush sapi-i default_node_index' => dt('Index items for the index with the machine name !name.', array('!name' => 'default_node_index')),
'drush sapi-i default_node_index' => dt('Index items for the index with the machine name !name.', array('!name' => 'default_node_index')),
'drush sapi-i 1 100' => dt("Index a maximum number of !limit items (index's cron batch size items per batch run) for the index with the ID !id.", array('!limit' => 100, '!id' => 1)),
'drush sapi-i 1 100' => dt("Index a maximum number of !limit items (index's cron batch size items per batch run) for the index with the ID !id.", array('!limit' => 100, '!id' => 1)),
'drush sapi-i 1 100 10' => dt("Index a maximum number of !limit items (!batch_size items per batch run) for the index with the ID !id.", array('!limit' => 100, '!batch_size' => 10, '!id' => 1)),
'drush sapi-i 1 100 10' => dt("Index a maximum number of !limit items (!batch_size items per batch run) for the index with the ID !id.", array('!limit' => 100, '!batch_size' => 10, '!id' => 1)),
+ 'drush sapi-i 0 0 100' => dt("Index all items of all indexes with !batch_size items per batch run.", array('!batch_size' => 100)),
),
),
'arguments' => array(
'arguments' => array(
- 'index_id' => dt('The numeric ID or machine name of an index.'),
+ 'index_id' => dt('The numeric ID or machine name of an index. Set to 0 to index all indexes. Defaults to 0 (index all).'),
'limit' => dt("The number of items to index (index's cron batch size items per run). Set to 0 to index all items. Defaults to 0 (index all)."),
'limit' => dt("The number of items to index (index's cron batch size items per run). Set to 0 to index all items. Defaults to 0 (index all)."),
'batch_size' => dt("The number of items to index per batch run. Set to 0 to index all items at once. Defaults to the index's cron batch size."),
'batch_size' => dt("The number of items to index per batch run. Set to 0 to index all items at once. Defaults to the index's cron batch size."),
),
),
@@ -68,13 +95,25 @@ function search_api_drush_command() {
'aliases' => array('sapi-r'),
'aliases' => array('sapi-r'),
);
);
+ $items['search-api-reindex-items'] = array(
+ 'description' => 'Force re-indexing of one or more specific items.',
+ 'examples' => array(
+ 'drush search-api-reindex-items node 12,34,56' => dt('Schedule the nodes with ID 12, 34 and 56 for re-indexing.'),
+ ),
+ 'arguments' => array(
+ 'entity_type' => dt('The entity type whose items should be re-indexed.'),
+ 'entities' => dt('The entities of the given entity type to be re-indexed.'),
+ ),
+ 'aliases' => array('sapi-ri'),
+ );
+
$items['search-api-clear'] = array(
$items['search-api-clear'] = array(
'description' => 'Clear one or all search indexes and mark them for re-indexing.',
'description' => 'Clear one or all search indexes and mark them for re-indexing.',
'examples' => array(
'examples' => array(
'drush searchapi-clear' => dt('Clear all search indexes.'),
'drush searchapi-clear' => dt('Clear all search indexes.'),
'drush sapi-c' => dt('Alias to clear all search indexes.'),
'drush sapi-c' => dt('Alias to clear all search indexes.'),
- 'drush sapi-r 1' => dt('Clear the search index with the ID !id.', array('!id' => 1)),
- 'drush sapi-r default_node_index' => dt('Clear the search index with the machine name !name.', array('!name' => 'default_node_index')),
+ 'drush sapi-c 1' => dt('Clear the search index with the ID !id.', array('!id' => 1)),
+ 'drush sapi-c default_node_index' => dt('Clear the search index with the machine name !name.', array('!name' => 'default_node_index')),
),
),
'arguments' => array(
'arguments' => array(
'index_id' => dt('The numeric ID or machine name of an index.'),
'index_id' => dt('The numeric ID or machine name of an index.'),
@@ -82,6 +121,65 @@ function search_api_drush_command() {
'aliases' => array('sapi-c'),
'aliases' => array('sapi-c'),
);
);
+ $items['search-api-execute-tasks'] = array(
+ 'description' => 'Execute all pending tasks or all for a given server.',
+ 'examples' => array(
+ 'drush search-api-execute-tasks my_solr_server' => dt('Execute all pending tasks on !server', array('!server' => 'my_solr_server')),
+ 'drush sapi-et my_solr_server' => dt('Execute all pending tasks on !server', array('!server' => 'my_solr_server')),
+ 'drush sapi-et' => dt('Execute all pending tasks on all servers.')
+ ),
+ 'arguments' => array(
+ 'server_id' => dt('The numeric ID or machine name of a server to execute tasks on.'),
+ ),
+ 'aliases' => array('sapi-et')
+ );
+
+ $items['search-api-set-index-server'] = array(
+ 'description' => 'Set the search server used by a given index.',
+ 'examples' => array(
+ 'drush search-api-set-index-server default_node_index my_solr_server' => dt('Set the !index index to use the !server server.', array('!index' => 'default_node_index', '!server' => 'my_solr_server')),
+ 'drush sapi-sis default_node_index my_solr_server' => dt('Alias to set the !index index to use the !server server.', array('!index' => 'default_node_index', '!server' => 'my_solr_server')),
+ ),
+ 'arguments' => array(
+ 'index_id' => dt('The numeric ID or machine name of an index.'),
+ 'server_id' => dt('The numeric ID or machine name of a server to set on the index.'),
+ ),
+ 'aliases' => array('sapi-sis'),
+ );
+
+ $items['search-api-server-list'] = array(
+ 'description' => 'List all search servers.',
+ 'examples' => array(
+ 'drush search-api-server-list' => dt('List all search servers.'),
+ 'drush sapi-sl' => dt('Alias to list all search servers.'),
- drush_log(dt("Indexing a maximum number of !limit items (!batch_size items per batch run) for the index !index.", array('!index' => $index->name, '!limit' => $limit, '!batch_size' => $batch_size)), 'ok');
+ drush_log(dt("Indexing a maximum number of !limit items (!batch_size items per batch run) for the index !index.", array('!index' => $index->name, '!limit' => $limit, '!batch_size' => $batch_size)), 'ok');
- // Create the batch.
- if (!_search_api_batch_indexing_create($index, $batch_size, $limit, $remaining, TRUE)) {
- drush_log(dt("Couldn't create a batch, please check the batch size and limit parameters."), 'error');
- }
- else {
- // Launch the batch process.
- drush_backend_batch_process();
- }
+ // Create the batch.
+ if (!_search_api_batch_indexing_create($index, $batch_size, $limit, $remaining, TRUE)) {
+ drush_log(dt("Couldn't create a batch, please check the batch size and limit parameters."), 'error');
+ return FALSE;
}
}
+
+ return TRUE;
}
}
/**
/**
@@ -259,6 +473,33 @@ function drush_search_api_reindex($index_id = NULL) {
}
}
}
}
+/**
+ * Marks the given entities as needing to be re-indexed.
+ drush_log(dt('There was an error setting index !index to use server !server.', array('!index' => $index->name, '!server' => $server->name)), 'error');
+ }
+ elseif (!$success) {
+ drush_log(dt('Index !index was already using server !server.', array('!index' => $index->name, '!server' => $server->name)), 'ok');
+ }
+ else {
+ drush_log(dt('Index !index has been set to use server !server and items have been queued for indexing.', array('!index' => $index->name, '!server' => $server->name)), 'ok');
+ }
+}
+
+/**
+ * Returns an index or all indexes as an array.
*
*
- * @param $index_id
- * (optional) The provided index id.
+ * @param string|int|null $index_id
+ * (optional) The ID or machine name of the index to load. Defaults to
+ * loading all available indexes.
*
*
- * @return
+ * @return SearchApiIndex[]
* An array of indexes.
* An array of indexes.
*/
*/
function search_api_drush_get_index($index_id = NULL) {
function search_api_drush_get_index($index_id = NULL) {
@@ -298,7 +609,35 @@ function search_api_drush_get_index($index_id = NULL) {
}
}
/**
/**
- * Static lookup to prevent Drush 4 from running twice.
+ * Returns a server or all servers as an array.
+ *
+ * @param string|int|null $server_id
+ * (optional) The ID or machine name of the server to load. Defaults to