diff --git a/config/schema/search_api.index.schema.yml b/config/schema/search_api.index.schema.yml index 427f03f..6348e40 100644 --- a/config/schema/search_api.index.schema.yml +++ b/config/schema/search_api.index.schema.yml @@ -17,7 +17,7 @@ search_api.index.*: read_only: type: boolean label: 'Read-only' - fields: + field_settings: type: sequence label: 'Indexed fields' sequence: @@ -48,14 +48,14 @@ search_api.index.*: hidden: type: boolean label: 'Whether the field should appear in the UI' - processors: + processor_settings: type: sequence label: 'Processor settings' sequence: type: mapping label: 'A processor' mapping: - processor_id: + plugin_id: type: string label: 'The plugin ID of the processor' weights: @@ -65,7 +65,7 @@ search_api.index.*: type: integer label: 'The processor''s weight for this stage' settings: - type: plugin.plugin_configuration.search_api_processor.[%parent.processor_id] + type: plugin.plugin_configuration.search_api_processor.[%parent.plugin_id] options: type: mapping label: 'Options' @@ -76,23 +76,30 @@ search_api.index.*: index_directly: type: boolean label: 'Index items immediately' - datasources: + datasource_settings: type: sequence - label: 'Datasource plugin IDs' + label: 'Datasource settings' sequence: - type: string - datasource_configs: + type: mapping + label: 'The settings for a datasource' + mapping: + plugin_id: + type: string + label: 'The plugin ID of the datasource' + settings: + type: plugin.plugin_configuration.search_api_datasource.[%parent.plugin_id] + tracker_settings: type: sequence - label: 'Datasource plugin configurations' + label: 'Tracker settings' sequence: - type: plugin.plugin_configuration.search_api_datasource.[%key] - label: 'Datasource plugin configuration' - tracker: - type: string - label: 'Tracker plugin ID' - tracker_config: - label: 'Tracker config plugin' - type: plugin.plugin_configuration.search_api_tracker.[%parent.tracker] + type: mapping + label: 'The settings for a tracker' + mapping: + plugin_id: + type: string + label: 'The plugin ID of the tracker' + settings: + type: plugin.plugin_configuration.search_api_tracker.[%parent.plugin_id] server: type: string label: 'Server ID' diff --git a/search_api.drush.inc b/search_api.drush.inc index e403668..e2460f7 100644 --- a/search_api.drush.inc +++ b/search_api.drush.inc @@ -216,7 +216,7 @@ function drush_search_api_list() { $rows[] = array( $index->id(), $index->label(), - $index->getServerId() ? $index->getServer()->label() : $none, + $index->getServerId() ? $index->getServerInstance()->label() : $none, $types ? implode(', ', $types) : $none, $index->status() ? $enabled : $disabled, (int) $index->getOption('cron_limit'), @@ -325,8 +325,8 @@ function drush_search_api_status($index_id = NULL) { ); foreach ($indexes as $index) { - $indexed = $index->getTracker()->getIndexedItemsCount(); - $total = $index->getTracker()->getTotalItemsCount(); + $indexed = $index->getTrackerInstance()->getIndexedItemsCount(); + $total = $index->getTrackerInstance()->getTotalItemsCount(); $complete = '-'; if ($total > 0) { @@ -365,7 +365,7 @@ function drush_search_api_index($index_id = NULL, $limit = NULL, $batch_size = N } foreach ($indexes as $index) { - $tracker = $index->getTracker(); + $tracker = $index->getTrackerInstance(); $remaining = $tracker->getTotalItemsCount() - $tracker->getIndexedItemsCount(); if (!$remaining) { diff --git a/search_api.theme.inc b/search_api.theme.inc index 7de7c73..bc42364 100644 --- a/search_api.theme.inc +++ b/search_api.theme.inc @@ -229,8 +229,8 @@ function theme_search_api_index($variables) { // Get the index. /** @var $index \Drupal\search_api\IndexInterface */ $index = $variables['index']; - $server = $index->hasValidServer() ? $index->getServer() : NULL; - $tracker = $index->hasValidTracker() ? $index->getTracker() : NULL; + $server = $index->hasValidServer() ? $index->getServerInstance() : NULL; + $tracker = $index->hasValidTracker() ? $index->getTrackerInstance() : NULL; $output = ''; diff --git a/search_api_db/search_api_db_defaults/config/optional/search_api.index.default_index.yml b/search_api_db/search_api_db_defaults/config/optional/search_api.index.default_index.yml index 42d3422..83090b9 100644 --- a/search_api_db/search_api_db_defaults/config/optional/search_api.index.default_index.yml +++ b/search_api_db/search_api_db_defaults/config/optional/search_api.index.default_index.yml @@ -71,13 +71,13 @@ fields: property_path: type processors: content_access: - processor_id: content_access + plugin_id: content_access weights: preprocess_index: -6 preprocess_query: -4 settings: { } highlight: - processor_id: highlight + plugin_id: highlight weights: postprocess_query: -9 settings: @@ -87,7 +87,7 @@ processors: prefix: '' suffix: '' html_filter: - processor_id: html_filter + plugin_id: html_filter weights: preprocess_index: -3 preprocess_query: -6 @@ -103,7 +103,7 @@ processors: string: 2 b: 2 ignorecase: - processor_id: ignorecase + plugin_id: ignorecase weights: preprocess_index: -5 preprocess_query: -8 @@ -112,17 +112,17 @@ processors: - rendered_item - title language: - processor_id: language + plugin_id: language weights: preprocess_index: -50 settings: { } node_status: - processor_id: node_status + plugin_id: node_status weights: preprocess_index: -10 settings: { } rendered_item: - processor_id: rendered_item + plugin_id: rendered_item weights: preprocess_index: -8 settings: @@ -133,7 +133,7 @@ processors: article: search_index page: search_index stopwords: - processor_id: stopwords + plugin_id: stopwords weights: preprocess_query: -10 postprocess_query: -10 @@ -178,7 +178,7 @@ processors: - will - with tokenizer: - processor_id: tokenizer + plugin_id: tokenizer weights: preprocess_index: -2 preprocess_query: -5 @@ -190,7 +190,7 @@ processors: overlap_cjk: 1 minimum_word_size: '3' transliteration: - processor_id: transliteration + plugin_id: transliteration weights: preprocess_index: -4 preprocess_query: -7 @@ -201,16 +201,18 @@ processors: options: index_directly: true cron_limit: 50 -datasources: - - 'entity:node' -datasource_configs: +datasource_settings: 'entity:node': - default: '1' - bundles: - article: '0' - page: '0' -tracker: default -tracker_config: { } + plugin_id: 'entity:node' + settings: + default: '1' + bundles: + article: '0' + page: '0' +tracker_settings: + default: + plugin_id: default + settings: {} server: default_server status: true langcode: en diff --git a/search_api_db/tests/src/Kernel/BackendTest.php b/search_api_db/tests/src/Kernel/BackendTest.php index 5c43111..c590c14 100644 --- a/search_api_db/tests/src/Kernel/BackendTest.php +++ b/search_api_db/tests/src/Kernel/BackendTest.php @@ -157,8 +157,8 @@ class BackendTest extends KernelTestBase { $index = $this->getIndex(); $this->assertTrue((bool) $index, 'The index was successfully created.'); - $this->assertEquals(5, $index->getTracker()->getTotalItemsCount(), 'Correct item count.'); - $this->assertEquals(0, $index->getTracker()->getIndexedItemsCount(), 'All items still need to be indexed.'); + $this->assertEquals(5, $index->getTrackerInstance()->getTotalItemsCount(), 'Correct item count.'); + $this->assertEquals(0, $index->getTrackerInstance()->getIndexedItemsCount(), 'All items still need to be indexed.'); } /** @@ -202,7 +202,7 @@ class BackendTest extends KernelTestBase { $processors = $index->getProcessorSettings(); $processors['html_filter'] = array( - 'processor_id' => 'html_filter', + 'plugin_id' => 'html_filter', 'weights' => array(), 'settings' => array(), ); diff --git a/src/Entity/Index.php b/src/Entity/Index.php index 64e556a..6fc0752 100644 --- a/src/Entity/Index.php +++ b/src/Entity/Index.php @@ -18,6 +18,7 @@ use Drupal\search_api\Query\QueryInterface; use Drupal\search_api\Query\ResultSetInterface; use Drupal\search_api\SearchApiException; use Drupal\search_api\ServerInterface; +use Drupal\search_api\Tracker\TrackerInterface; use Drupal\search_api\Utility; use Drupal\user\TempStoreException; use Drupal\views\Views; @@ -57,13 +58,11 @@ use Drupal\views\Views; * "name", * "description", * "read_only", - * "fields", - * "processors", + * "field_settings", + * "processor_settings", * "options", - * "datasources", - * "datasource_configs", - * "tracker", - * "tracker_config", + * "datasource_settings", + * "tracker_settings", * "server", * }, * links = { @@ -115,7 +114,7 @@ class Index extends ConfigEntityBase implements IndexInterface { * * @var array */ - protected $fields = array(); + protected $field_settings = array(); /** * An array of options configuring this index. @@ -127,18 +126,11 @@ class Index extends ConfigEntityBase implements IndexInterface { protected $options = array(); /** - * The IDs of the datasources selected for this index. - * - * @var string[] - */ - protected $datasources = array(); - - /** * The configuration for the selected datasources. * * @var array */ - protected $datasource_configs = array(); + protected $datasource_settings = array(); /** * The instantiated datasource plugins. @@ -147,30 +139,23 @@ class Index extends ConfigEntityBase implements IndexInterface { * * @see getDatasources() */ - protected $datasourcePlugins; - - /** - * The tracker plugin ID. - * - * @var string - */ - protected $tracker = 'default'; + protected $datasourceInstances; /** * The tracker plugin configuration. * * @var array */ - protected $tracker_config = array(); + protected $tracker_settings = array(); /** * The tracker plugin instance. * * @var \Drupal\search_api\Tracker\TrackerInterface|null * - * @see getTracker() + * @see getTrackerInstance() */ - protected $trackerPlugin; + protected $trackerInstance = FALSE; /** * The ID of the server on which data should be indexed. @@ -184,7 +169,7 @@ class Index extends ConfigEntityBase implements IndexInterface { * * @var \Drupal\search_api\ServerInterface * - * @see getServer() + * @see getServerInstance() */ protected $serverInstance; @@ -201,7 +186,7 @@ class Index extends ConfigEntityBase implements IndexInterface { * @var array * An array containing processor settings. */ - protected $processors = array(); + protected $processor_settings = array(); /** * Cached information about the processors available for this index. @@ -210,7 +195,7 @@ class Index extends ConfigEntityBase implements IndexInterface { * * @see loadProcessors() */ - protected $processorPlugins; + protected $processorInstances; /** * Whether reindexing has been triggered for this index in this page request. @@ -238,13 +223,6 @@ class Index extends ConfigEntityBase implements IndexInterface { /** * {@inheritdoc} */ - public function id() { - return $this->id; - } - - /** - * {@inheritdoc} - */ public function getDescription() { return $this->description; } @@ -282,10 +260,6 @@ class Index extends ConfigEntityBase implements IndexInterface { */ public function setOption($name, $option) { $this->options[$name] = $option; - // If the fields are changed, reset the static fields cache. - if ($name == 'fields') { - $this->cache = array(); - } return $this; } @@ -301,7 +275,7 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function getDatasourceIds() { - return $this->datasources; + return array_keys($this->getDatasources()); } /** @@ -320,7 +294,8 @@ class Index extends ConfigEntityBase implements IndexInterface { if (empty($datasources[$datasource_id])) { $args['@datasource'] = $datasource_id; $args['%index'] = $this->label(); - throw new SearchApiException(new FormattableMarkup('The datasource with ID "@datasource" could not be retrieved for index %index.', $args)); + $args['@all_datasources'] = implode(', ', array_keys($datasources)); + throw new SearchApiException(new FormattableMarkup('The datasource with ID "@datasource" could not be retrieved for index %index. The available datasources are: @all_datasources', $args)); } return $datasources[$datasource_id]; } @@ -329,20 +304,20 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function getDatasources($only_enabled = TRUE) { - if (!isset($this->datasourcePlugins)) { - $this->datasourcePlugins = array(); + if (!isset($this->datasourceInstances)) { + $this->datasourceInstances = array(); /** @var $datasource_plugin_manager \Drupal\search_api\Datasource\DatasourcePluginManager */ $datasource_plugin_manager = \Drupal::service('plugin.manager.search_api.datasource'); foreach ($datasource_plugin_manager->getDefinitions() as $name => $datasource_definition) { - if (class_exists($datasource_definition['class']) && empty($this->datasourcePlugins[$name])) { + if (class_exists($datasource_definition['class']) && empty($this->datasourceInstances[$name])) { // Create our settings for this datasource. - $config = isset($this->datasource_configs[$name]) ? $this->datasource_configs[$name] : array(); + $config = isset($this->datasource_settings[$name]) ? $this->datasource_settings[$name] : array(); $config += array('index' => $this); /** @var $datasource \Drupal\search_api\Datasource\DatasourceInterface */ $datasource = $datasource_plugin_manager->createInstance($name, $config); - $this->datasourcePlugins[$name] = $datasource; + $this->datasourceInstances[$name] = $datasource; } elseif (!class_exists($datasource_definition['class'])) { \Drupal::logger('search_api')->warning('Datasource @id specifies a non-existing @class.', array('@id' => $name, '@class' => $datasource_definition['class'])); @@ -352,53 +327,93 @@ class Index extends ConfigEntityBase implements IndexInterface { // Filter datasources by status if required. if (!$only_enabled) { - return $this->datasourcePlugins; + return $this->datasourceInstances; + } + + // No settings are saved for datasources, so we can go ahead and return an + // empty array. + if ($this->datasource_settings === array()) { + return array(); } - return array_intersect_key($this->datasourcePlugins, array_flip($this->datasources)); + + $enabled_datasources = array_flip(array_keys($this->datasource_settings)); + $datasource_instances = $this->datasourceInstances; + + foreach ($datasource_instances as $key => $datasource) { + if (!isset($enabled_datasources[$key])) { + unset($datasource_instances[$key]); + } + } + + return $datasource_instances; } /** * {@inheritdoc} */ public function hasValidTracker() { - return (bool) \Drupal::service('plugin.manager.search_api.tracker')->getDefinition($this->getTrackerId(), FALSE); + $tracker = $this->getTrackerInstance(); + return ($tracker instanceof TrackerInterface); } /** * {@inheritdoc} */ public function getTrackerId() { - return $this->tracker; + $settings = $this->getTrackerSettings(); + if ($settings === array()) { + return 'default'; + } + $tracker_settings = array_values($settings)[0]; + return $tracker_settings['plugin_id']; } /** * {@inheritdoc} */ - public function getTracker() { - if (!$this->trackerPlugin) { - $tracker_plugin_configuration = array('index' => $this) + $this->tracker_config; - if (!($this->trackerPlugin = \Drupal::service('plugin.manager.search_api.tracker')->createInstance($this->getTrackerId(), $tracker_plugin_configuration))) { - $args['@tracker'] = $this->tracker; + public function getTrackerInstance() { + if ($this->getTrackerSettings() === NULL) { + return NULL; + } + + if (!$this->trackerInstance) { + if ($this->getTrackerSettings() === array()) { + $tracker_settings = array( + 'settings' => array(), + 'plugin_id' => $this->getTrackerId(), + ); + } + else { + $tracker_settings = $this->getTrackerSettings()[$this->getTrackerId()]; + } + $tracker_plugin_configuration = array('index' => $this) + $tracker_settings['settings']; + if (!($this->trackerInstance = \Drupal::service('plugin.manager.search_api.tracker')->createInstance($this->getTrackerId(), $tracker_plugin_configuration))) { + $args['@tracker'] = $this->tracker_settings; $args['%index'] = $this->label(); throw new SearchApiException(new FormattableMarkup('The tracker with ID "@tracker" could not be retrieved for index %index.', $args)); } } - return $this->trackerPlugin; + return $this->trackerInstance; + } + + public function getTrackerSettings() { + return $this->tracker_settings; } /** * {@inheritdoc} */ public function hasValidServer() { - return $this->server !== NULL && Server::load($this->server) !== NULL; + $server = $this->getServerInstance(); + return ($server instanceof ServerInterface); } /** * {@inheritdoc} */ public function isServerEnabled() { - return $this->hasValidServer() && $this->getServer()->status(); + return $this->hasValidServer() && $this->getServerInstance()->status(); } /** @@ -411,7 +426,7 @@ class Index extends ConfigEntityBase implements IndexInterface { /** * {@inheritdoc} */ - public function getServer() { + public function getServerInstance() { if (!$this->serverInstance && $this->server) { $this->serverInstance = Server::load($this->server); if (!$this->serverInstance) { @@ -486,13 +501,13 @@ class Index extends ConfigEntityBase implements IndexInterface { * The loaded processors, keyed by processor ID. */ protected function loadProcessors() { - if (empty($this->processorPlugins)) { + if (empty($this->processorInstances)) { /** @var $processor_plugin_manager \Drupal\search_api\Processor\ProcessorPluginManager */ $processor_plugin_manager = \Drupal::service('plugin.manager.search_api.processor'); $processor_settings = $this->getProcessorSettings(); foreach ($processor_plugin_manager->getDefinitions() as $name => $processor_definition) { - if (class_exists($processor_definition['class']) && empty($this->processorPlugins[$name])) { + if (class_exists($processor_definition['class']) && empty($this->processorInstances[$name])) { // Create our settings for this processor. $settings = empty($processor_settings[$name]['settings']) ? array() : $processor_settings[$name]['settings']; $settings['index'] = $this; @@ -500,7 +515,7 @@ class Index extends ConfigEntityBase implements IndexInterface { /** @var $processor \Drupal\search_api\Processor\ProcessorInterface */ $processor = $processor_plugin_manager->createInstance($name, $settings); if ($processor->supportsIndex($this)) { - $this->processorPlugins[$name] = $processor; + $this->processorInstances[$name] = $processor; } } elseif (!class_exists($processor_definition['class'])) { @@ -509,21 +524,21 @@ class Index extends ConfigEntityBase implements IndexInterface { } } - return $this->processorPlugins; + return $this->processorInstances; } /** * {@inheritdoc} */ public function getProcessorSettings() { - return $this->processors; + return $this->processor_settings; } /** * {@inheritdoc} */ public function setProcessorSettings(array $processors) { - $this->processors = $processors; + $this->processor_settings = $processors; return $this; } @@ -578,7 +593,7 @@ class Index extends ConfigEntityBase implements IndexInterface { throw new SearchApiException(new FormattableMarkup('Cannot add field with machine name %field_id: machine name is already taken.', $args)); } - $this->fields[$field_id] = $field->getSettings(); + $this->field_settings[$field_id] = $field->getSettings(); $this->resetCaches(); return $this; @@ -588,7 +603,7 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function renameField($old_field_id, $new_field_id) { - if (isset($this->fields[$old_field_id])) { + if (isset($this->field_settings[$old_field_id])) { $args['%field_id'] = $old_field_id; throw new SearchApiException(new FormattableMarkup('Could not rename field with machine name %field_id: no such field.', $args)); } @@ -596,13 +611,13 @@ class Index extends ConfigEntityBase implements IndexInterface { $args['%field_id'] = $new_field_id; throw new SearchApiException(new FormattableMarkup('%field_id is a reserved value and cannot be used as the machine name of a normal field.', $args)); } - if (isset($this->fields[$new_field_id])) { + if (isset($this->field_settings[$new_field_id])) { $args['%field_id'] = $new_field_id; throw new SearchApiException(new FormattableMarkup('%field_id is a reserved value and cannot be used as the machine name of a normal field.', $args)); } - $this->fields[$new_field_id] = $this->fields[$old_field_id]; - unset($this->fields[$old_field_id]); + $this->field_settings[$new_field_id] = $this->field_settings[$old_field_id]; + unset($this->field_settings[$old_field_id]); $this->resetCaches(); return $this; @@ -621,7 +636,7 @@ class Index extends ConfigEntityBase implements IndexInterface { throw new SearchApiException(new FormattableMarkup('Cannot remove field with machine name %field_id: field is locked.', $args)); } - unset($this->fields[$field_id]); + unset($this->field_settings[$field_id]); $this->resetCaches(); return $this; @@ -657,7 +672,7 @@ class Index extends ConfigEntityBase implements IndexInterface { public function getFieldsByDatasource($datasource_id) { $datasource_fields = $this->getCache(__FUNCTION__); if (!$datasource_fields) { - $datasource_fields = array_fill_keys($this->datasources, array()); + $datasource_fields = array_fill_keys(array_keys($this->datasource_settings), array()); $datasource_fields[NULL] = array(); foreach ($this->getFields() as $field_id => $field) { $datasource_fields[$field->getDatasourceId()][$field_id] = $field; @@ -689,14 +704,14 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function getFieldSettings() { - return $this->fields; + return $this->field_settings; } /** * {@inheritdoc} */ public function setFieldSettings(array $fields = array()) { - $this->fields = $fields; + $this->field_settings = $fields; return $this; } @@ -767,7 +782,7 @@ class Index extends ConfigEntityBase implements IndexInterface { */ public function indexItems($limit = '-1', $datasource_id = NULL) { if ($this->hasValidTracker() && !$this->isReadOnly()) { - $tracker = $this->getTracker(); + $tracker = $this->getTrackerInstance(); $next_set = $tracker->getRemainingItems($limit, $datasource_id); $items = $this->loadItemsMultiple($next_set); if ($items) { @@ -787,13 +802,16 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function indexSpecificItems(array $search_objects) { - if (!$search_objects || $this->read_only) { + if (!$search_objects) { + return array(); + } + if ($this->isReadOnly()) { return array(); } - if (!$this->status) { + if (!$this->status()) { throw new SearchApiException(new FormattableMarkup("Couldn't index values on index %index (index is disabled)", array('%index' => $this->label()))); } - if (empty($this->fields)) { + if (empty($this->getFields())) { throw new SearchApiException(new FormattableMarkup("Couldn't index values on index %index (no fields selected)", array('%index' => $this->label()))); } @@ -824,12 +842,12 @@ class Index extends ConfigEntityBase implements IndexInterface { // Items that are rejected should also be deleted from the server. if ($rejected_ids) { - $this->getServer()->deleteItems($this, $rejected_ids); + $this->getServerInstance()->deleteItems($this, $rejected_ids); } $indexed_ids = array(); if ($items) { - $indexed_ids = $this->getServer()->indexItems($this, $items); + $indexed_ids = $this->getServerInstance()->indexItems($this, $items); } // Return the IDs of all items that were either successfully indexed or @@ -838,7 +856,7 @@ class Index extends ConfigEntityBase implements IndexInterface { if ($processed_ids) { if ($this->hasValidTracker()) { - $this->getTracker()->trackItemsIndexed($processed_ids); + $this->getTrackerInstance()->trackItemsIndexed($processed_ids); } // Since we've indexed items now, triggering reindexing would have some // effect again. Therefore, we reset the flag. @@ -883,7 +901,7 @@ class Index extends ConfigEntityBase implements IndexInterface { foreach ($ids as $id) { $item_ids[] = Utility::createCombinedId($datasource_id, $id); } - $this->getTracker()->$tracker_method($item_ids); + $this->getTrackerInstance()->$tracker_method($item_ids); if (!$this->isReadOnly() && $this->getOption('index_directly')) { try { $items = $this->loadItemsMultiple($item_ids); @@ -907,9 +925,9 @@ class Index extends ConfigEntityBase implements IndexInterface { foreach ($ids as $id) { $item_ids[] = Utility::createCombinedId($datasource_id, $id); } - $this->getTracker()->trackItemsDeleted($item_ids); + $this->getTrackerInstance()->trackItemsDeleted($item_ids); if (!$this->isReadOnly() && $this->isServerEnabled()) { - $this->getServer()->deleteItems($this, $item_ids); + $this->getServerInstance()->deleteItems($this, $item_ids); } } } @@ -918,9 +936,9 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function reindex() { - if ($this->status() && !$this->hasReindexed) { + if ($this->status() && !$this->isReindexing()) { $this->hasReindexed = TRUE; - $this->getTracker()->trackAllItemsUpdated(); + $this->getTrackerInstance()->trackAllItemsUpdated(); \Drupal::moduleHandler()->invokeAll('search_api_index_reindex', array($this, FALSE)); } } @@ -932,14 +950,14 @@ class Index extends ConfigEntityBase implements IndexInterface { if ($this->status()) { // Only invoke the hook if we actually did something. $invoke_hook = FALSE; - if (!$this->hasReindexed) { + if (!$this->isReindexing()) { $invoke_hook = TRUE; $this->hasReindexed = TRUE; - $this->getTracker()->trackAllItemsUpdated(); + $this->getTrackerInstance()->trackAllItemsUpdated(); } if (!$this->isReadOnly()) { $invoke_hook = TRUE; - $this->getServer()->deleteAllIndexItems($this); + $this->getServerInstance()->deleteAllIndexItems($this); } if ($invoke_hook) { \Drupal::moduleHandler()->invokeAll('search_api_index_reindex', array($this, !$this->isReadOnly())); @@ -1014,10 +1032,10 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function resetCaches($include_stored = TRUE) { - $this->datasourcePlugins = NULL; - $this->trackerPlugin = NULL; + $this->datasourceInstances = NULL; + $this->trackerInstance = NULL; $this->serverInstance = NULL; - $this->processorPlugins = NULL; + $this->processorInstances = NULL; $this->cache = array(); if ($include_stored) { Cache::invalidateTags($this->getCacheTags()); @@ -1069,18 +1087,18 @@ class Index extends ConfigEntityBase implements IndexInterface { // Remove all "locked" and "hidden" flags from all fields of the index. If // they are still valid, they should be re-added by the processors. - foreach ($this->fields as $field_id => $field_settings) { - unset($this->fields[$field_id]['indexed_locked']); - unset($this->fields[$field_id]['type_locked']); - unset($this->fields[$field_id]['hidden']); + foreach ($this->field_settings as $field_id => $field_settings) { + unset($this->field_settings[$field_id]['indexed_locked']); + unset($this->field_settings[$field_id]['type_locked']); + unset($this->field_settings[$field_id]['hidden']); } // We first have to check for locked processors, otherwise their // preIndexSave() methods might not be called in the next step. foreach ($this->getProcessors(FALSE) as $processor_id => $processor) { - if ($processor->isLocked() && !isset($this->processors[$processor_id])) { - $this->processors[$processor_id] = array( - 'processor_id' => $processor_id, + if ($processor->isLocked() && !isset($this->processor_settings[$processor_id])) { + $this->processor_settings[$processor_id] = array( + 'plugin_id' => $processor_id, 'weights' => array(), 'settings' => array(), ); @@ -1105,8 +1123,10 @@ class Index extends ConfigEntityBase implements IndexInterface { try { // Fake an original for inserts to make code cleaner. + /** @var \Drupal\search_api\IndexInterface $original */ $original = $update ? $this->original : static::create(array('status' => FALSE)); + // Reactions for an index that was previously enabled and still is. if ($this->status() && $original->status()) { // React on possible changes that would require re-indexing, etc. $this->reactToServerSwitch($original); @@ -1114,16 +1134,20 @@ class Index extends ConfigEntityBase implements IndexInterface { $this->reactToTrackerSwitch($original); $this->reactToProcessorChanges($original); } - elseif (!$this->status() && $original->status()) { + + // Reactions for an index that is being disabled. + if (!$this->status() && $original->status()) { if ($this->hasValidTracker()) { \Drupal::getContainer()->get('search_api.index_task_manager')->stopTracking($this); } if ($original->isServerEnabled()) { - $original->getServer()->removeIndex($this); + $original->getServerInstance()->removeIndex($this); } } - elseif ($this->status() && !$original->status()) { - $this->getServer()->addIndex($this); + + // Reactions for an index that is being enabled. + if ($this->status() && !$original->status()) { + $this->getServerInstance()->addIndex($this); if ($this->hasValidTracker()) { \Drupal::getContainer()->get('search_api.index_task_manager')->startTracking($this); } @@ -1167,19 +1191,23 @@ class Index extends ConfigEntityBase implements IndexInterface { * The previous version of the index. */ protected function reactToServerSwitch(IndexInterface $original) { + if (!$original->status() || !$this->status()) { + throw new SearchApiException("Invalid operation, this should only be called when the index was enabled before the change and remained so."); + } + if ($this->getServerId() != $original->getServerId()) { if ($original->isServerEnabled()) { - $original->getServer()->removeIndex($this); + $original->getServerInstance()->removeIndex($this); } if ($this->isServerEnabled()) { - $this->getServer()->addIndex($this); + $this->getServerInstance()->addIndex($this); } // When the server changes we also need to trigger a reindex. $this->reindex(); } elseif ($this->isServerEnabled()) { // Tell the server the index configuration got updated - $this->getServer()->updateIndex($this); + $this->getServerInstance()->updateIndex($this); } } @@ -1193,6 +1221,10 @@ class Index extends ConfigEntityBase implements IndexInterface { * The previous version of the index. */ protected function reactToDatasourceSwitch(IndexInterface $original) { + if (!$original->status() || !$this->status()) { + throw new SearchApiException("Invalid operation, this should only be called when the index was enabled before the change and remained so."); + } + $new_datasource_ids = $this->getDatasourceIds(); $original_datasource_ids = $original->getDatasourceIds(); if ($new_datasource_ids != $original_datasource_ids) { @@ -1204,7 +1236,6 @@ class Index extends ConfigEntityBase implements IndexInterface { } } - /** * Checks whether the index switched tracker plugin and reacts accordingly. * @@ -1215,7 +1246,11 @@ class Index extends ConfigEntityBase implements IndexInterface { * The previous version of the index. */ protected function reactToTrackerSwitch(IndexInterface $original) { - if ($this->tracker != $original->getTrackerId()) { + if (!$original->status() || !$this->status()) { + throw new SearchApiException("Invalid operation, this should only be called when the index was enabled before the change and remained so."); + } + + if ($this->getTrackerId() != $original->getTrackerId()) { $index_task_manager = \Drupal::getContainer()->get('search_api.index_task_manager'); if ($original->hasValidTracker()) { $index_task_manager->stopTracking($this); @@ -1291,10 +1326,10 @@ class Index extends ConfigEntityBase implements IndexInterface { /** @var \Drupal\search_api\IndexInterface[] $entities */ foreach ($entities as $index) { if ($index->hasValidTracker()) { - $index->getTracker()->trackAllItemsDeleted(); + $index->getTrackerInstance()->trackAllItemsDeleted(); } if ($index->hasValidServer()) { - $index->getServer()->removeIndex($index); + $index->getServerInstance()->removeIndex($index); } } } @@ -1352,7 +1387,7 @@ class Index extends ConfigEntityBase implements IndexInterface { * 'CONFIG_DEPENDENCY_KEY' => array( * 'always' => array( * 'processors' => array( - * 'PROCESSOR_ID' => $processor, + * 'PLUGIN_ID' => $processor, * ), * 'datasources' => array( * 'DATASOURCE_ID_1' => $datasource_1, @@ -1401,7 +1436,7 @@ class Index extends ConfigEntityBase implements IndexInterface { // The server needs special treatment, since it is a dependency of the index // itself, and not one of its plugins. if ($this->hasValidServer()) { - $name = $this->getServer()->getConfigDependencyName(); + $name = $this->getServerInstance()->getConfigDependencyName(); $dependency_data['config'][$name]['optional']['index'][$this->id] = $this; } @@ -1515,18 +1550,23 @@ class Index extends ConfigEntityBase implements IndexInterface { // The handling of how we translate plugin changes back to the index varies // according to plugin type, unfortunately. // First, remove plugins that need to be removed. - $this->processors = array_intersect_key($this->processors, $all_plugins['processors']); - $this->datasources = array_keys($all_plugins['datasources']); - $this->datasource_configs = array_intersect_key($this->datasource_configs, $all_plugins['datasources']); - // There always needs to be a tracker. + $this->processor_settings = array_intersect_key($this->processor_settings, $all_plugins['processors']); + $this->datasource_settings = array_intersect_key($this->datasource_settings, $all_plugins['datasources']); + // There always needs to be a tracker but tracker settings are tracker + // specific so they can't be moved over to the default tracker. if (empty($all_plugins['tracker'])) { - $this->tracker = \Drupal::config('search_api.settings')->get('default_tracker'); - $this->tracker_config = array(); + $default_tracker = \Drupal::config('search_api.settings')->get('default_tracker'); + $this->tracker_settings = array( + $default_tracker => array( + 'plugin_id' => $default_tracker, + 'settings' => array(), + ) + ); } // There also always needs to be a datasource, but here we have no easy way // out – if we had to remove all datasources, the operation fails. Return // FALSE to indicate this, which will cause the index to be deleted. - if (!$this->datasources) { + if (!$this->datasource_settings) { return FALSE; } @@ -1535,13 +1575,13 @@ class Index extends ConfigEntityBase implements IndexInterface { foreach ($plugin_configs as $plugin_id => $plugin_config) { switch ($plugin_type) { case 'processors': - $this->processors[$plugin_id]['settings'] = $plugin_config; + $this->processor_settings[$plugin_id]['settings'] = $plugin_config; break; case 'datasources': - $this->datasource_configs[$plugin_id] = $plugin_config; + $this->datasource_settings[$plugin_id] = $plugin_config; break; case 'tracker': - $this->tracker_config = $plugin_config; + $this->tracker_settings = $plugin_config; break; } } @@ -1564,8 +1604,8 @@ class Index extends ConfigEntityBase implements IndexInterface { protected function getAllPlugins() { $plugins = array(); - if ($this->hasValidTracker()) { - $plugins['tracker'][$this->getTrackerId()] = $this->getTracker(); + if (!$this->isNew() && $this->hasValidTracker()) { + $plugins['tracker'][$this->getTrackerId()] = $this->getTrackerInstance(); } $plugins['processors'] = $this->getProcessors(); $plugins['datasources'] = $this->getDatasources(); @@ -1590,10 +1630,10 @@ class Index extends ConfigEntityBase implements IndexInterface { */ public function __sleep() { $properties = get_object_vars($this); - unset($properties['datasourcePlugins']); - unset($properties['trackerPlugin']); + unset($properties['datasourceInstances']); + unset($properties['trackerInstance']); unset($properties['serverInstance']); - unset($properties['processorPlugins']); + unset($properties['processorInstances']); unset($properties['cache']); return array_keys($properties); } diff --git a/src/Form/IndexFieldsForm.php b/src/Form/IndexFieldsForm.php index 4b4b2e5..a214251 100644 --- a/src/Form/IndexFieldsForm.php +++ b/src/Form/IndexFieldsForm.php @@ -213,7 +213,7 @@ class IndexFieldsForm extends EntityForm { $form['description']['#markup'] = $this->t('

The data type of a field determines how it can be used for searching and filtering. The boost is used to give additional weight to certain fields, e.g. titles or tags.

Whether detailed field types are supported depends on the type of server this index resides on. In any case, fields of type "Fulltext" will always be fulltext-searchable.

'); if ($index->hasValidServer()) { $form['description']['#markup'] .= '

' . $this->t('Check the ' . "server's backend class description for details.", - array(':server-url' => $index->getServer()->toUrl('canonical')->toString())) . '

'; + array(':server-url' => $index->getServerInstance()->toUrl('canonical')->toString())) . '

'; } if ($fields = $index->getFieldsByDatasource(NULL)) { diff --git a/src/Form/IndexForm.php b/src/Form/IndexForm.php index 2bfca64..3885dfd 100644 --- a/src/Form/IndexForm.php +++ b/src/Form/IndexForm.php @@ -262,7 +262,7 @@ class IndexForm extends EntityForm { '#title' => $this->t('Tracker'), '#description' => $this->t('Select the type of tracker which should be used for keeping track of item changes.'), '#options' => $this->getTrackerPluginManager()->getOptionsList(), - '#default_value' => $index->hasValidTracker() ? $index->getTracker()->getPluginId() : key($tracker_options), + '#default_value' => !$index->isNew() && $index->hasValidTracker() ? $index->getTrackerInstance()->getPluginId() : key($tracker_options), '#required' => TRUE, '#disabled' => !$index->isNew(), '#ajax' => array( @@ -313,7 +313,7 @@ class IndexForm extends EntityForm { '#description' => $this->t('Only enabled indexes can be used for indexing and searching. This setting will only take effect if the selected server is also enabled.'), '#default_value' => $index->status(), // Can't enable an index lying on a disabled server or no server at all. - '#disabled' => !$index->status() && (!$index->hasValidServer() || !$index->getServer()->status()), + '#disabled' => !$index->status() && (!$index->hasValidServer() || !$index->getServerInstance()->status()), // @todo This doesn't seem to work and should also hide for disabled // servers. If that works, we can probably remove the last sentence of // the description. @@ -391,8 +391,8 @@ class IndexForm extends EntityForm { * The index being created or edited. */ public function buildTrackerConfigForm(array &$form, FormStateInterface $form_state, IndexInterface $index) { - if ($index->hasValidTracker()) { - $tracker = $index->getTracker(); + if (!$index->isNew() && $index->hasValidTracker()) { + $tracker = $index->getTrackerInstance(); // @todo Create, use and save SubFormState already here, not only in // validate(). Also, use proper subset of $form for first parameter? if ($config_form = $tracker->buildConfigurationForm(array(), $form_state)) { @@ -484,7 +484,7 @@ class IndexForm extends EntityForm { // form structure). $tracker_id = $form_state->getValue('tracker', NULL); if ($this->originalEntity->getTrackerId() == $tracker_id) { - $tracker = $this->originalEntity->getTracker(); + $tracker = $this->originalEntity->getTrackerInstance(); } else { $tracker = $this->trackerPluginManager->createInstance($tracker_id, array('index' => $this->originalEntity)); @@ -532,9 +532,12 @@ class IndexForm extends EntityForm { $datasource_form = (!empty($form['datasource_configs'][$datasource_id])) ? $form['datasource_configs'][$datasource_id] : array(); $datasource_form_state = new SubFormState($form_state, array('datasource_configs', $datasource_id)); $datasource->submitConfigurationForm($datasource_form, $datasource_form_state); - $datasource_configuration[$datasource_id] = $datasource->getConfiguration(); + $datasource_configuration[$datasource_id] = array( + 'plugin_id' => $datasource_id, + 'settings' => $datasource->getConfiguration() + ); } - $index->set('datasource_configs', $datasource_configuration); + $index->set('datasource_settings', $datasource_configuration); // Call submitConfigurationForm() for the (possibly new) tracker. // @todo It seems if we change the tracker, we would validate/submit the old @@ -543,8 +546,8 @@ class IndexForm extends EntityForm { // just always be empty (because datasources have their plugin ID in the // form structure). $tracker_id = $form_state->getValue('tracker', NULL); - if ($this->originalEntity->getTrackerId() == $tracker_id) { - $tracker = $this->originalEntity->getTracker(); + if (!$index->isNew() && $this->originalEntity->getTrackerId() == $tracker_id) { + $tracker = $this->originalEntity->getTrackerInstance(); } else { $tracker = $this->trackerPluginManager->createInstance($tracker_id, array('index' => $this->originalEntity)); @@ -552,7 +555,13 @@ class IndexForm extends EntityForm { $tracker_form_state = new SubFormState($form_state, array('tracker_config')); $tracker->submitConfigurationForm($form['tracker_config'], $tracker_form_state); - $index->set('tracker_config', $tracker->getConfiguration()); + $tracker_settings = array( + $tracker_id => array( + 'plugin_id' => $tracker_id, + 'settings' => $tracker->getConfiguration() + ) + ); + $index->set('tracker_settings', $tracker_settings); } /** diff --git a/src/Form/IndexProcessorsForm.php b/src/Form/IndexProcessorsForm.php index d32e5ac..3474eff 100644 --- a/src/Form/IndexProcessorsForm.php +++ b/src/Form/IndexProcessorsForm.php @@ -96,8 +96,9 @@ class IndexProcessorsForm extends EntityForm { $processors_by_stage[$stage] = $this->entity->getProcessorsByStage($stage, FALSE); } - if ($this->entity->getServer()) { - $backend_discouraged_processors = $this->entity->getServer() + if ($this->entity->getServerInstance()) { + $backend_discouraged_processors = $this->entity + ->getServerInstance() ->getBackend() ->getDiscouragedProcessors(); @@ -262,7 +263,7 @@ class IndexProcessorsForm extends EntityForm { continue; } $new_settings[$processor_id] = array( - 'processor_id' => $processor_id, + 'plugin_id' => $processor_id, 'weights' => array(), 'settings' => array(), ); diff --git a/src/Form/IndexStatusForm.php b/src/Form/IndexStatusForm.php index 640e795..ad42155 100644 --- a/src/Form/IndexStatusForm.php +++ b/src/Form/IndexStatusForm.php @@ -65,7 +65,7 @@ class IndexStatusForm extends FormBase { 'class' => array('container-inline'), ), ); - $has_remaining_items = ($index->getTracker()->getRemainingItemsCount() > 0); + $has_remaining_items = ($index->getTrackerInstance()->getRemainingItemsCount() > 0); $all_value = $this->t('all', array(), array('context' => 'items to index')); $limit = array( '#type' => 'textfield', diff --git a/src/IndexBatchHelper.php b/src/IndexBatchHelper.php index 9da6463..379a9e8 100644 --- a/src/IndexBatchHelper.php +++ b/src/IndexBatchHelper.php @@ -137,7 +137,7 @@ class IndexBatchHelper { // Get the remaining item count. When no valid tracker is available then // the value will be set to zero which will cause the batch process to // stop. - $remaining_item_count = ($index->hasValidTracker() ? $index->getTracker()->getRemainingItemsCount() : 0); + $remaining_item_count = ($index->hasValidTracker() ? $index->getTrackerInstance()->getRemainingItemsCount() : 0); // Check if an explicit limit needs to be used. if ($context['sandbox']['limit'] > -1) { diff --git a/src/IndexInterface.php b/src/IndexInterface.php index a435f35..4aa2645 100644 --- a/src/IndexInterface.php +++ b/src/IndexInterface.php @@ -200,7 +200,7 @@ interface IndexInterface extends ConfigEntityInterface { * @throws \Drupal\search_api\SearchApiException * Thrown if the tracker couldn't be instantiated. */ - public function getTracker(); + public function getTrackerInstance(); /** * Determines whether this index is lying on a valid server. @@ -236,10 +236,13 @@ interface IndexInterface extends ConfigEntityInterface { * @throws \Drupal\search_api\SearchApiException * Thrown if the server couldn't be loaded. */ - public function getServer(); + public function getServerInstance(); /** - * Sets the server the index is attached to + * Sets the server the index is attached to. + * + * When setting this to NULL, the configured server will be removed from the + * index. * * @param \Drupal\search_api\ServerInterface|null $server * The server to move this index to, or NULL. diff --git a/src/Plugin/views/argument/SearchApiMoreLikeThis.php b/src/Plugin/views/argument/SearchApiMoreLikeThis.php index f39c8b0..bfe03e3 100644 --- a/src/Plugin/views/argument/SearchApiMoreLikeThis.php +++ b/src/Plugin/views/argument/SearchApiMoreLikeThis.php @@ -69,7 +69,7 @@ class SearchApiMoreLikeThis extends SearchApiArgument { */ public function query($group_by = FALSE) { try { - $server = $this->query->getIndex()->getServer(); + $server = $this->query->getIndex()->getServerInstance(); if (!$server->supportsFeature('search_api_mlt')) { $backend_id = $server->getBackendId(); \Drupal::logger('search_api')->error('The search backend "@backend_id" does not offer "More like this" functionality.', diff --git a/src/Query/Query.php b/src/Query/Query.php index eb22371..53bbe60 100644 --- a/src/Query/Query.php +++ b/src/Query/Query.php @@ -318,7 +318,7 @@ class Query implements QueryInterface { $this->preExecute(); // Execute query. - $response = $this->index->getServer()->search($this); + $response = $this->index->getServerInstance()->search($this); // Postprocess the search results. $this->postExecute($response); diff --git a/src/Task/IndexTaskManager.php b/src/Task/IndexTaskManager.php index db1b5b8..4cfafcb 100644 --- a/src/Task/IndexTaskManager.php +++ b/src/Task/IndexTaskManager.php @@ -99,7 +99,7 @@ class IndexTaskManager implements IndexTaskManagerInterface { $item_ids[] = Utility::createCombinedId($datasource_id, $raw_id); } $added = count($item_ids); - $index->getTracker()->trackItemsInserted($item_ids); + $index->getTrackerInstance()->trackItemsInserted($item_ids); } } } @@ -195,7 +195,7 @@ class IndexTaskManager implements IndexTaskManagerInterface { if (!isset($datasource_ids)) { $this->state->delete($this->getIndexStateKey($index)); if ($valid_tracker) { - $index->getTracker()->trackAllItemsDeleted(); + $index->getTrackerInstance()->trackAllItemsDeleted(); } return; } @@ -211,7 +211,7 @@ class IndexTaskManager implements IndexTaskManagerInterface { foreach ($datasource_ids as $datasource_id) { unset($index_state['pages'][$datasource_id]); if ($valid_tracker) { - $index->getTracker()->trackAllItemsDeleted($datasource_id); + $index->getTrackerInstance()->trackAllItemsDeleted($datasource_id); } } diff --git a/src/Tests/IntegrationTest.php b/src/Tests/IntegrationTest.php index a14f24d..bf81971 100644 --- a/src/Tests/IntegrationTest.php +++ b/src/Tests/IntegrationTest.php @@ -98,6 +98,53 @@ class IntegrationTest extends WebTestBase { } /** + * Test what happens when an index has an integer as id/label. + * + * This needs to be in a seperate index because we also want to see what + * happens with the content and we don't want to mess with the content entity + * tracking of the other index. + */ + public function testIntegerIndex() { + $this->drupalLogin($this->adminUser); + $this->getTestServer(); + + $this->drupalCreateNode(array('type' => 'article')); + $this->drupalCreateNode(array('type' => 'article')); + + $this->drupalGet('admin/config/search/search-api/add-index'); + + $this->indexId = 123; + $edit = array( + 'name' => $this->indexId, + 'id' => $this->indexId, + 'status' => 1, + 'description' => 'test Index:: 123~', + 'server' => 'webtest_server', + 'datasources[]' => array('entity:node'), + ); + $this->drupalPostForm(NULL, $edit, $this->t('Save')); + $this->assertText($this->t('The index was successfully saved.')); + $this->assertText($this->t('Successfully tracked @count items for this index.', array('@count' => 2))); + $this->assertEqual(2, $this->countTrackedItems()); + + $this->enableAllProcessors(); + $this->checkFieldLabels(); + + $this->addFieldsToIndex(); + $this->removeFieldsFromIndex(); + + $this->configureFilter(); + $this->configureFilterPage(); + $this->checkProcessorChanges(); + $this->changeProcessorFieldBoost(); + + $this->setReadOnly(); + $this->disableEnableIndex(); + $this->changeIndexDatasource(); + $this->changeIndexServer(); + } + + /** * Tests creating a search server via the UI. */ protected function createServer($server_id = '_test_server') { @@ -169,7 +216,6 @@ class IntegrationTest extends WebTestBase { $this->assertText($this->t('@name field is required.', array('@name' => $this->t('Machine-readable name')))); $this->assertText($this->t('@name field is required.', array('@name' => $this->t('Data sources')))); - $edit = array( 'name' => $index_name, 'id' => $this->indexId, @@ -382,7 +428,9 @@ class IntegrationTest extends WebTestBase { * The number of tracked items in the test index. */ protected function countTrackedItems() { - return $this->getIndex()->getTracker()->getTotalItemsCount(); + return $this->getIndex() + ->getTrackerInstance() + ->getTotalItemsCount(); } /** @@ -392,7 +440,9 @@ class IntegrationTest extends WebTestBase { * The number of unindexed items in the test index. */ protected function countRemainingItems() { - return $this->getIndex()->getTracker()->getRemainingItemsCount(); + return $this->getIndex() + ->getTrackerInstance() + ->getRemainingItemsCount(); } /** @@ -723,7 +773,7 @@ class IntegrationTest extends WebTestBase { $this->drupalPostForm($index_path, array(), $this->t('Index now')); - $remaining_after = $index->getTracker()->getRemainingItemsCount(); + $remaining_after = $index->getTrackerInstance()->getRemainingItemsCount(); $this->assertEqual(0, $remaining_after, 'Items were indexed after removing the "read only" flag.'); } diff --git a/src/Tests/LanguageIntegrationTest.php b/src/Tests/LanguageIntegrationTest.php index 5dfec22..0dc654e 100644 --- a/src/Tests/LanguageIntegrationTest.php +++ b/src/Tests/LanguageIntegrationTest.php @@ -128,7 +128,7 @@ class LanguageIntegrationTest extends WebTestBase { protected function countTrackedItems() { /** @var \Drupal\search_api\IndexInterface $index */ $index = Index::load($this->indexId); - return $index->getTracker()->getTotalItemsCount(); + return $index->getTrackerInstance()->getTotalItemsCount(); } /** diff --git a/src/Tests/Processor/ContentAccessTest.php b/src/Tests/Processor/ContentAccessTest.php index b301cd4..1b443c5 100644 --- a/src/Tests/Processor/ContentAccessTest.php +++ b/src/Tests/Processor/ContentAccessTest.php @@ -109,7 +109,23 @@ class ContentAccessTest extends ProcessorTestBase { $this->nodes[2]->save(); // Also index users, to verify that they are unaffected by the processor. - $this->index->set('datasources', array('entity:comment', 'entity:node', 'entity:user')); + $this->index->set( + 'datasource_settings', + array( + 'entity:comment' => array( + 'plugin_id' => 'entity:comment', + 'settings' => array(), + ), + 'entity:node' => array( + 'plugin_id' => 'entity:node', + 'settings' => array(), + ), + 'entity:user' => array( + 'plugin_id' => 'entity:user', + 'settings' => array(), + ) + ) + ); $this->index->save(); \Drupal::getContainer()->get('search_api.index_task_manager')->addItemsAll($this->index); @@ -128,6 +144,7 @@ class ContentAccessTest extends ProcessorTestBase { $query = Utility::createQuery($this->index); $result = $query->execute(); + $this->assertEqual($result->getResultCount(), 4); $this->assertResults($result, array('user' => array(0), 'comment' => array(0), 'node' => array(0, 1))); } diff --git a/src/Tests/Processor/ProcessorIntegrationTest.php b/src/Tests/Processor/ProcessorIntegrationTest.php index ad617c8..92e590f 100644 --- a/src/Tests/Processor/ProcessorIntegrationTest.php +++ b/src/Tests/Processor/ProcessorIntegrationTest.php @@ -32,7 +32,12 @@ class ProcessorIntegrationTest extends WebTestBase { 'name' => 'Test index', 'id' => $this->indexId, 'status' => 1, - 'datasources' => array('entity:node'), + 'datasource_settings' => array( + 'entity:node' => array( + 'plugin_id' => 'entity:node', + 'settings' => array(), + ) + ), ))->save(); } diff --git a/src/Tests/Processor/ProcessorTestBase.php b/src/Tests/Processor/ProcessorTestBase.php index 2809c31..abb60e6 100644 --- a/src/Tests/Processor/ProcessorTestBase.php +++ b/src/Tests/Processor/ProcessorTestBase.php @@ -87,9 +87,23 @@ abstract class ProcessorTestBase extends EntityUnitTestBase { 'id' => 'index', 'name' => 'Index name', 'status' => TRUE, - 'datasources' => array('entity:comment', 'entity:node'), + 'datasource_settings' => array( + 'entity:comment' => array( + 'plugin_id' => 'entity:comment', + 'settings' => array(), + ), + 'entity:node' => array( + 'plugin_id' => 'entity:node', + 'settings' => array(), + ), + ), 'server' => 'server', - 'tracker' => 'default', + 'tracker_settings' => array( + 'default' => array( + 'plugin_id' => 'default', + 'settings' => array() + ) + ), )); $this->index->setServer($this->server); $this->index->setFieldSettings(array( @@ -109,7 +123,7 @@ abstract class ProcessorTestBase extends EntityUnitTestBase { if ($processor) { $this->index->setProcessorSettings(array( $processor => array( - 'processor_id' => $processor, + 'plugin_id' => $processor, 'weights' => array(), 'settings' => array(), ), diff --git a/src/Tests/WebTestBase.php b/src/Tests/WebTestBase.php index 8b85ea6..72bb5e2 100644 --- a/src/Tests/WebTestBase.php +++ b/src/Tests/WebTestBase.php @@ -169,7 +169,18 @@ abstract class WebTestBase extends SimpletestWebTestBase { 'name' => $name, 'description' => $name . ' description', 'server' => $server_id, - 'datasources' => array($datasource_id), + 'datasource_settings' => array( + $datasource_id => array( + 'plugin_id' => $datasource_id, + 'settings' => array(), + ) + ), + 'tracker_settings' => array( + 'default' => array( + 'plugin_id' => 'default', + 'settings' => array(), + ) + ), )); $index->save(); $this->indexId = $index->id(); diff --git a/src/UnsavedIndexConfiguration.php b/src/UnsavedIndexConfiguration.php index 8fe07be..bb93c57 100644 --- a/src/UnsavedIndexConfiguration.php +++ b/src/UnsavedIndexConfiguration.php @@ -249,8 +249,8 @@ class UnsavedIndexConfiguration implements IndexInterface, UnsavedConfigurationI /** * {@inheritdoc} */ - public function getTracker() { - return $this->entity->getTracker(); + public function getTrackerInstance() { + return $this->entity->getTrackerInstance(); } /** @@ -277,8 +277,8 @@ class UnsavedIndexConfiguration implements IndexInterface, UnsavedConfigurationI /** * {@inheritdoc} */ - public function getServer() { - return $this->entity->getServer(); + public function getServerInstance() { + return $this->entity->getServerInstance(); } /** diff --git a/src/Utility.php b/src/Utility.php index 15dccc4..34a4717 100644 --- a/src/Utility.php +++ b/src/Utility.php @@ -153,7 +153,7 @@ class Utility { if (empty(static::$dataTypeFallbackMapping[$index_id])) { $server = NULL; try { - $server = $index->getServer(); + $server = $index->getServerInstance(); } catch (SearchApiException $e) { // If the server isn't available, just ignore it here and return all diff --git a/tests/search_api_test_backend/src/Plugin/search_api/backend/TestBackend.php b/tests/search_api_test_backend/src/Plugin/search_api/backend/TestBackend.php index 5032989..57ced24 100644 --- a/tests/search_api_test_backend/src/Plugin/search_api/backend/TestBackend.php +++ b/tests/search_api_test_backend/src/Plugin/search_api/backend/TestBackend.php @@ -128,6 +128,18 @@ class TestBackend extends BackendPluginBase { $results = Utility::createSearchResultSet($query); $result_items = array(); $datasources = $query->getIndex()->getDatasources(); + + // Searching on an index without datasources is useless, return an empty + // result set and log this so the admin knows what's going on. + if ($datasources === array()) { + $logger = \Drupal::getContainer() + ->get('logger.factory') + ->get('search_api'); + $logger->notice($this->t('Tried searching on an index with no datasources.')); + + $results->setResultCount(0); + return $results; + } /** @var \Drupal\search_api\Datasource\DatasourceInterface $datasource */ $datasource = reset($datasources); $datasource_id = $datasource->getPluginId(); diff --git a/tests/search_api_test_db/config/install/search_api.index.database_search_index.yml b/tests/search_api_test_db/config/install/search_api.index.database_search_index.yml index 4f42d29..3404c09 100644 --- a/tests/search_api_test_db/config/install/search_api.index.database_search_index.yml +++ b/tests/search_api_test_db/config/install/search_api.index.database_search_index.yml @@ -2,7 +2,7 @@ id: database_search_index name: 'Test index' description: 'An index used for testing' read_only: false -fields: +field_settings: id: label: ID type: integer @@ -40,25 +40,28 @@ fields: property_path: search_api_language index_locked: true type_locked: true -processors: +processor_settings: add_url: - processor_id: add_url + plugin_id: add_url weights: preprocess_index: -30 settings: { } language: - processor_id: language + plugin_id: language weights: preprocess_index: -50 settings: { } options: cron_limit: -1 index_directly: false -datasources: - - 'entity:entity_test' -datasource_configs: { } -tracker: default -tracker_config: { } +datasource_settings: + 'entity:entity_test': + plugin_id: 'entity:entity_test' + settings: {} +tracker_settings: + default: + plugin_id: default + settings: {} server: database_search_server status: true langcode: en diff --git a/tests/src/Kernel/CliTest.php b/tests/src/Kernel/CliTest.php index 70fd5cc..bba9fed 100644 --- a/tests/src/Kernel/CliTest.php +++ b/tests/src/Kernel/CliTest.php @@ -101,8 +101,8 @@ class CliTest extends KernelTestBase { )); $index->save(); - $total_items = $index->getTracker()->getTotalItemsCount(); - $indexed_items = $index->getTracker()->getIndexedItemsCount(); + $total_items = $index->getTrackerInstance()->getTotalItemsCount(); + $indexed_items = $index->getTrackerInstance()->getIndexedItemsCount(); $this->assertEquals($total_items, 2, 'The 2 items are tracked.'); $this->assertEquals($indexed_items, 0, 'No items are indexed'); @@ -122,8 +122,8 @@ class CliTest extends KernelTestBase { 'category' => 'item_category' ))->save(); - $total_items = $index->getTracker()->getTotalItemsCount(); - $indexed_items = $index->getTracker()->getIndexedItemsCount(); + $total_items = $index->getTrackerInstance()->getTotalItemsCount(); + $indexed_items = $index->getTrackerInstance()->getIndexedItemsCount(); $this->assertEquals($total_items, 4, 'All 4 items are tracked.'); $this->assertEquals($indexed_items, 2, '2 items are indexed'); diff --git a/tests/src/Kernel/DependencyRemovalTest.php b/tests/src/Kernel/DependencyRemovalTest.php index 61a7da3..c5b3242 100644 --- a/tests/src/Kernel/DependencyRemovalTest.php +++ b/tests/src/Kernel/DependencyRemovalTest.php @@ -277,7 +277,7 @@ class DependencyRemovalTest extends KernelTestBase { $dependency_name = $this->dependency->getConfigDependencyName(); $this->index->set('processors', array( 'search_api_test_dependencies' => array( - 'processor_id' => 'search_api_test_dependencies', + 'plugin_id' => 'search_api_test_dependencies', 'settings' => array( $dependency_key => array( $dependency_name, @@ -336,12 +336,15 @@ class DependencyRemovalTest extends KernelTestBase { // server. $dependency_key = $this->dependency->getConfigDependencyKey(); $dependency_name = $this->dependency->getConfigDependencyName(); - $this->index->set('tracker', 'search_api_test_dependencies'); - $this->index->set('tracker_config', array( - $dependency_key => array( - $dependency_name, - ), + $tracker_settings = array('search_api_test_dependencies' => array( + 'plugin_id' => 'search_api_test_dependencies', + 'settings' => array( + $dependency_key => array( + $dependency_name, + ), + ) )); + $this->index->set('tracker_settings', $tracker_settings); $this->index->save(); // Check the dependencies were calculated correctly. @@ -375,8 +378,10 @@ class DependencyRemovalTest extends KernelTestBase { // Depending on whether the plugin should have removed the dependency or // not, make sure the right action was taken. - $tracker = $this->index->get('tracker'); - $tracker_config = $this->index->get('tracker_config'); + $tracker_settings = $this->index->get('tracker_settings'); + $tracker = array_keys($tracker_settings)[0]; + $tracker_config = $tracker_settings[$tracker]['settings']; + if ($remove_dependency) { $this->assertEquals('search_api_test_dependencies', $tracker, 'Tracker not reset'); $this->assertEmpty($tracker_config, 'Tracker settings adapted'); diff --git a/tests/src/Kernel/LanguageKernelTest.php b/tests/src/Kernel/LanguageKernelTest.php index 671a957..b555e77 100644 --- a/tests/src/Kernel/LanguageKernelTest.php +++ b/tests/src/Kernel/LanguageKernelTest.php @@ -153,10 +153,10 @@ class LanguageKernelTest extends KernelTestBase { $this->assertEquals($expected, $datasource_item_ids, 'Datasource returns correct item ids.'); // Test indexing the new entity. - $this->assertEquals(0, $this->index->getTracker()->getIndexedItemsCount(), 'The index is empty.'); - $this->assertEquals(2, $this->index->getTracker()->getTotalItemsCount(), 'There are two items to be indexed.'); + $this->assertEquals(0, $this->index->getTrackerInstance()->getIndexedItemsCount(), 'The index is empty.'); + $this->assertEquals(2, $this->index->getTrackerInstance()->getTotalItemsCount(), 'There are two items to be indexed.'); $this->index->indexItems(); - $this->assertEquals(2, $this->index->getTracker()->getIndexedItemsCount(), 'Two items have been indexed.'); + $this->assertEquals(2, $this->index->getTrackerInstance()->getIndexedItemsCount(), 'Two items have been indexed.'); // Now, make the first entity language-specific by assigning a language. $default_langcode = $this->langcodes[0]; @@ -175,8 +175,8 @@ class LanguageKernelTest extends KernelTestBase { $this->assertEquals($expected, $datasource_item_ids, 'Datasource returns correct item ids.'); // Test that the index needs to be updated. - $this->assertEquals(1, $this->index->getTracker()->getIndexedItemsCount(), 'The updated item needs to be reindexed.'); - $this->assertEquals(2, $this->index->getTracker()->getTotalItemsCount(), 'There are two items in total.'); + $this->assertEquals(1, $this->index->getTrackerInstance()->getIndexedItemsCount(), 'The updated item needs to be reindexed.'); + $this->assertEquals(2, $this->index->getTrackerInstance()->getTotalItemsCount(), 'There are two items in total.'); // Set two translations for the first entity and test that the datasource // returns three separate item IDs, one for each translation. @@ -197,8 +197,8 @@ class LanguageKernelTest extends KernelTestBase { $this->assertEquals($expected, $datasource_item_ids, 'Datasource returns correct item ids for a translated entity.'); // Test that the index needs to be updated. - $this->assertEquals(1, $this->index->getTracker()->getIndexedItemsCount(), 'The updated items needs to be reindexed.'); - $this->assertEquals(4, $this->index->getTracker()->getTotalItemsCount(), 'There are four items in total.'); + $this->assertEquals(1, $this->index->getTrackerInstance()->getIndexedItemsCount(), 'The updated items needs to be reindexed.'); + $this->assertEquals(4, $this->index->getTrackerInstance()->getTotalItemsCount(), 'There are four items in total.'); // Delete one translation and test that the datasource returns only three // items. @@ -215,10 +215,10 @@ class LanguageKernelTest extends KernelTestBase { $this->assertEquals($expected, $datasource_item_ids, 'Datasource returns correct item ids for a translated entity.'); // Test reindexing. - $this->assertEquals(3, $this->index->getTracker()->getTotalItemsCount(), 'There are three items in total.'); - $this->assertEquals(1, $this->index->getTracker()->getIndexedItemsCount(), 'The updated items needs to be reindexed.'); + $this->assertEquals(3, $this->index->getTrackerInstance()->getTotalItemsCount(), 'There are three items in total.'); + $this->assertEquals(1, $this->index->getTrackerInstance()->getIndexedItemsCount(), 'The updated items needs to be reindexed.'); $this->index->indexItems(); - $this->assertEquals(3, $this->index->getTracker()->getIndexedItemsCount(), 'Three items are indexed.'); + $this->assertEquals(3, $this->index->getTrackerInstance()->getIndexedItemsCount(), 'Three items are indexed.'); } }