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/config/schema/search_api.tracker.schema.yml b/config/schema/search_api.tracker.schema.yml index 297badc..1cb3518 100644 --- a/config/schema/search_api.tracker.schema.yml +++ b/config/schema/search_api.tracker.schema.yml @@ -1,4 +1,3 @@ -# @todo Update the key when https://www.drupal.org/node/2291073 is fixed. plugin.plugin_configuration.search_api_tracker.default: type: sequence label: 'Entity tracker configuration' 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..6745379 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 @@ -7,7 +7,7 @@ fields: label: 'Item language' type: string property_path: search_api_language - index_locked: true + indexed_locked: true type_locked: true title: label: Title @@ -34,7 +34,7 @@ fields: type: boolean datasource_id: 'entity:node' property_path: status - index_locked: true + indexed_locked: true type_locked: true sticky: label: 'Sticky at top of lists' @@ -56,13 +56,13 @@ fields: type: integer datasource_id: 'entity:node' property_path: uid - index_locked: true + indexed_locked: true type_locked: true search_api_node_grants: label: 'Node access information' type: string property_path: search_api_node_grants - index_locked: true + indexed_locked: true type_locked: true hidden: true type: @@ -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..abe7378 100644 --- a/src/Entity/Index.php +++ b/src/Entity/Index.php @@ -7,6 +7,7 @@ namespace Drupal\search_api\Entity; +use Drupal\Component\Plugin\Exception\PluginException; use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Cache\Cache; use Drupal\Core\Config\Entity\ConfigEntityBase; @@ -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 = NULL; /** * 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,84 @@ 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(); + } + + $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 array_intersect_key($this->datasourcePlugins, array_flip($this->datasources)); + + return $datasource_instances; } /** * {@inheritdoc} */ public function hasValidTracker() { - return (bool) \Drupal::service('plugin.manager.search_api.tracker')->getDefinition($this->getTrackerId(), FALSE); + return (bool) \Drupal::service('plugin.manager.search_api.tracker') + ->getDefinition($this->getTrackerId(), FALSE); } /** * {@inheritdoc} */ public function getTrackerId() { - return $this->tracker; + return $this->getTrackerInstance()->getPluginId(); } /** * {@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->trackerInstance) { + if ($this->tracker_settings === array()) { + $tracker_settings = array( + 'settings' => array(), + 'plugin_id' =>$default_tracker = \Drupal::config('search_api.settings') + ->get('default_tracker'), + ); + } + else { + $tracker_settings = reset($this->tracker_settings); + } + $tracker_plugin_configuration = array('index' => $this) + $tracker_settings['settings']; + + try { + $this->trackerInstance = \Drupal::service('plugin.manager.search_api.tracker')->createInstance($tracker_settings['plugin_id'], $tracker_plugin_configuration); + } catch (PluginException $pe) { + $args['@tracker'] = $tracker_settings['plugin_id']; $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; } /** * {@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 +417,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) { @@ -441,19 +447,23 @@ class Index extends ConfigEntityBase implements IndexInterface { // Filter processors by status if required. Enabled processors are those // which have settings in the "processors" option. if ($only_enabled) { - $processors_settings = $this->getProcessorSettings(); + $processors_settings = $this->processor_settings; $processors = array_intersect_key($processors, $processors_settings); } return $processors; } + public function removeProcessor($plugin_id) { + unset($this->processor_settings[$plugin_id]); + $this->processorInstances = array(); + } + /** * {@inheritdoc} */ public function getProcessorsByStage($stage, $only_enabled = TRUE) { $processors = $this->loadProcessors(); - $processor_settings = $this->getProcessorSettings(); $processor_weights = array(); // Get a list of all processors meeting the criteria (stage and, optionally, @@ -486,21 +496,25 @@ 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(); + $processor_settings = $this->processor_settings; foreach ($processor_plugin_manager->getDefinitions() as $name => $processor_definition) { - if (class_exists($processor_definition['class']) && empty($this->processorPlugins[$name])) { + if (empty($this->processorInstances[$name])) { // Create our settings for this processor. $settings = empty($processor_settings[$name]['settings']) ? array() : $processor_settings[$name]['settings']; $settings['index'] = $this; /** @var $processor \Drupal\search_api\Processor\ProcessorInterface */ - $processor = $processor_plugin_manager->createInstance($name, $settings); - if ($processor->supportsIndex($this)) { - $this->processorPlugins[$name] = $processor; + try { + $processor = $processor_plugin_manager->createInstance($name, $settings); + if ($processor->supportsIndex($this)) { + $this->processorInstances[$name] = $processor; + } + } catch (PluginException $e) { + \Drupal::logger('search_api')->warning('Processor @id specifies a non-existing @class.', array('@id' => $name, '@class' => $processor_definition['class'])); } } elseif (!class_exists($processor_definition['class'])) { @@ -509,22 +523,7 @@ class Index extends ConfigEntityBase implements IndexInterface { } } - return $this->processorPlugins; - } - - /** - * {@inheritdoc} - */ - public function getProcessorSettings() { - return $this->processors; - } - - /** - * {@inheritdoc} - */ - public function setProcessorSettings(array $processors) { - $this->processors = $processors; - return $this; + return $this->processorInstances; } /** @@ -578,7 +577,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 +587,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 +595,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 +620,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; @@ -634,7 +633,7 @@ class Index extends ConfigEntityBase implements IndexInterface { $fields = $this->getCache(__FUNCTION__, FALSE); if (!$fields) { $fields = array(); - foreach ($this->getFieldSettings() as $key => $field_info) { + foreach ($this->field_settings as $key => $field_info) { $fields[$key] = Utility::createField($this, $key, $field_info); } } @@ -657,7 +656,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; @@ -675,8 +674,8 @@ class Index extends ConfigEntityBase implements IndexInterface { $fulltext_fields = $this->getCache(__FUNCTION__); if (!$fulltext_fields) { $fulltext_fields = array(); - foreach ($this->getFieldSettings() as $key => $field_info) { - if (Utility::isTextType($field_info['type'])) { + foreach ($this->getFields() as $key => $field) { + if (Utility::isTextType($field->getType())) { $fulltext_fields[] = $key; } } @@ -688,21 +687,6 @@ class Index extends ConfigEntityBase implements IndexInterface { /** * {@inheritdoc} */ - public function getFieldSettings() { - return $this->fields; - } - - /** - * {@inheritdoc} - */ - public function setFieldSettings(array $fields = array()) { - $this->fields = $fields; - return $this; - } - - /** - * {@inheritdoc} - */ public function getPropertyDefinitions($datasource_id, $alter = TRUE) { $alter = $alter ? 1 : 0; $properties = $this->getCache(__FUNCTION__); @@ -767,7 +751,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 +771,13 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function indexSpecificItems(array $search_objects) { - if (!$search_objects || $this->read_only) { + if (!$search_objects || $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 (!$this->getFields()) { throw new SearchApiException(new FormattableMarkup("Couldn't index values on index %index (no fields selected)", array('%index' => $this->label()))); } @@ -824,12 +808,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 +822,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 +867,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 +891,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 +902,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 +916,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 +998,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 +1053,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 +1089,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 +1100,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 +1157,21 @@ class Index extends ConfigEntityBase implements IndexInterface { * The previous version of the index. */ protected function reactToServerSwitch(IndexInterface $original) { + assert($original->status() && $this->status(), '::reactToServerSwitch should only be called when the index is enabled.'); + 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 +1185,8 @@ class Index extends ConfigEntityBase implements IndexInterface { * The previous version of the index. */ protected function reactToDatasourceSwitch(IndexInterface $original) { + assert($original->status() && $this->status(), '::reactToDatasourceSwitch should only be called when the index is enabled.'); + $new_datasource_ids = $this->getDatasourceIds(); $original_datasource_ids = $original->getDatasourceIds(); if ($new_datasource_ids != $original_datasource_ids) { @@ -1204,7 +1198,6 @@ class Index extends ConfigEntityBase implements IndexInterface { } } - /** * Checks whether the index switched tracker plugin and reacts accordingly. * @@ -1215,7 +1208,9 @@ class Index extends ConfigEntityBase implements IndexInterface { * The previous version of the index. */ protected function reactToTrackerSwitch(IndexInterface $original) { - if ($this->tracker != $original->getTrackerId()) { + assert($original->status() && $this->status(), '::reactToTrackerSwitch should only be called when the index is enabled.'); + + if ($this->getTrackerId() != $original->getTrackerId()) { $index_task_manager = \Drupal::getContainer()->get('search_api.index_task_manager'); if ($original->hasValidTracker()) { $index_task_manager->stopTracking($this); @@ -1233,8 +1228,18 @@ class Index extends ConfigEntityBase implements IndexInterface { * The previous version of the index. */ protected function reactToProcessorChanges(IndexInterface $original) { - $original_settings = $original->getProcessorSettings(); - $new_settings = $this->getProcessorSettings(); + $orginal_processors = $original->getProcessors(); + $new_processors = $this->getProcessors(); + + $new_settings = array(); + $original_settings = array(); + + foreach ($orginal_processors as $k => $processor) { + $original_settings[$k] = $processor->getConfiguration(); + } + foreach ($new_processors as $k => $processor) { + $new_settings[$k] = $processor->getConfiguration(); + } // Only actually do something when the processor settings are changed. if ($original_settings != $new_settings) { @@ -1291,10 +1296,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); } } } @@ -1325,8 +1330,6 @@ class Index extends ConfigEntityBase implements IndexInterface { } } - // @todo Override static load() etc. methods? Measure performance difference. - /** * {@inheritdoc} */ @@ -1352,7 +1355,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 +1404,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 +1518,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 +1543,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 +1572,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 +1598,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..accb9b0 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->hasValidTracker() ? $index->getTrackerId() : 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..f481df1 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(); @@ -112,7 +113,7 @@ class IndexProcessorsForm extends EntityForm { } } - $processor_settings = $this->entity->getProcessorSettings(); + $processor_settings = $this->entity->getProcessors(TRUE); $form['#tree'] = TRUE; $form['#attached']['library'][] = 'search_api/drupal.search_api.index-active-formatters'; @@ -171,9 +172,10 @@ class IndexProcessorsForm extends EntityForm { foreach ($processors_by_stage as $stage => $processors) { /** @var \Drupal\search_api\Processor\ProcessorInterface $processor */ foreach ($processors as $processor_id => $processor) { - $weight = isset($processor_settings[$processor_id]['weights'][$stage]) - ? $processor_settings[$processor_id]['weights'][$stage] + $weight = isset($processor_settings[$processor_id]) + ? $processor_settings[$processor_id]->getPluginDefinition()['stages'][$stage] : $processor->getDefaultWeight($stage); + if ($processor->isHidden()) { $form['processors'][$processor_id]['weights'][$stage] = array( '#type' => 'value', @@ -262,7 +264,7 @@ class IndexProcessorsForm extends EntityForm { continue; } $new_settings[$processor_id] = array( - 'processor_id' => $processor_id, + 'plugin_id' => $processor_id, 'weights' => array(), 'settings' => array(), ); @@ -279,10 +281,10 @@ class IndexProcessorsForm extends EntityForm { // Sort the processors so we won't have unnecessary changes. ksort($new_settings); - $settings_changed = $new_settings != $this->entity->getProcessorSettings(); + $settings_changed = $new_settings != $this->entity->get('processor_settings'); $form_state->set('processors_changed', $settings_changed); if ($settings_changed) { - $this->entity->setProcessorSettings($new_settings); + $this->entity->set('processor_settings', $new_settings); } } 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..da84764 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. @@ -277,24 +280,6 @@ interface IndexInterface extends ConfigEntityInterface { public function getProcessorsByStage($stage, $only_enabled = TRUE); /** - * Retrieves this index's processor settings. - * - * @return array - * An array of processors and their settings. - */ - public function getProcessorSettings(); - - /** - * Sets this index's processor settings. - * - * @param array $processors - * An array of processors and their settings. - * - * @return $this - */ - public function setProcessorSettings(array $processors); - - /** * Preprocesses data items for indexing. * * Lets all enabled processors for this index preprocess the indexed data. @@ -420,24 +405,6 @@ interface IndexInterface extends ConfigEntityInterface { public function getFulltextFields(); /** - * Retrieves this index's field settings. - * - * @return array - * An array of field settings. - */ - public function getFieldSettings(); - - /** - * Sets this index's field settings. - * - * @param array $fields - * An array of field settings. - * - * @return $this - */ - public function setFieldSettings(array $fields); - - /** * Retrieves the properties of one of this index's datasources. * * @param string|null $datasource_id diff --git a/src/Item/Field.php b/src/Item/Field.php index 97637ad..abbe268 100644 --- a/src/Item/Field.php +++ b/src/Item/Field.php @@ -439,8 +439,7 @@ class Field implements \IteratorAggregate, FieldInterface { */ public function getBoost() { if (!isset($this->boost)) { - $fields = $this->index->getFieldSettings(); - $this->boost = isset($fields[$this->fieldIdentifier]['boost']) ? (float) $fields[$this->fieldIdentifier]['boost'] : 1.0; + $this->boost = 1.0; } return $this->boost; } diff --git a/src/Plugin/search_api/processor/RenderedItem.php b/src/Plugin/search_api/processor/RenderedItem.php index a277fc3..032be42 100644 --- a/src/Plugin/search_api/processor/RenderedItem.php +++ b/src/Plugin/search_api/processor/RenderedItem.php @@ -284,7 +284,8 @@ class RenderedItem extends ProcessorPluginBase { '%processor' => $this->label(), '@count' => $unset_view_modes, ); - $this->getLogger()->warning('Warning: While indexing items on search index %index, @count item(s) did not have a view mode configured for the %processor processor.', $context); + $this->getLogger() + ->warning('Warning: While indexing items on search index %index, @count item(s) did not have a view mode configured for the %processor processor.', $context); } // Restore the original user. 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/Task/ServerTaskManager.php b/src/Task/ServerTaskManager.php index d1f7e01..f0a7e22 100644 --- a/src/Task/ServerTaskManager.php +++ b/src/Task/ServerTaskManager.php @@ -50,9 +50,17 @@ class ServerTaskManager implements ServerTaskManagerInterface { */ public function execute(ServerInterface $server = NULL) { $select = $this->database->select('search_api_task', 't'); + // Only retrieve tasks we can handle. + $allowed_tasks = array( + 'addIndex', + 'updateIndex', + 'removeIndex', + 'deleteItems', + 'deleteAllIndexItems' + ); $select->fields('t') - // Only retrieve tasks we can handle. - ->condition('t.type', array('addIndex', 'updateIndex', 'removeIndex', 'deleteItems', 'deleteAllIndexItems'), 'IN'); + ->condition('t.type', $allowed_tasks, 'IN'); + if ($server) { if (!$server->status()) { return FALSE; 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..2d6bf7a 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(); } @@ -129,7 +134,6 @@ class ProcessorIntegrationTest extends WebTestBase { // testing environment regarding the YAML in the "tags" setting. $edit = array( 'status[html_filter]' => 1, - 'processors[html_filter][settings][fields][search_api_language]' => FALSE, 'processors[html_filter][settings][title]' => FALSE, 'processors[html_filter][settings][alt]' => FALSE, 'processors[html_filter][settings][tags]' => 'h1: 10' @@ -142,11 +146,6 @@ class ProcessorIntegrationTest extends WebTestBase { */ public function checkIgnoreCaseIntegration() { $this->enableProcessor('ignorecase'); - - $edit = array( - 'processors[ignorecase][settings][fields][search_api_language]' => FALSE, - ); - $this->editSettingsForm($edit, 'ignorecase'); } /** @@ -156,7 +155,6 @@ class ProcessorIntegrationTest extends WebTestBase { $this->enableProcessor('ignore_character'); $edit = array( - 'processors[ignore_character][settings][fields][search_api_language]' => FALSE, 'processors[ignore_character][settings][ignorable]' => '[¿¡!?,.]', 'processors[ignore_character][settings][strip][character_sets][Cc]' => TRUE, ); @@ -168,10 +166,9 @@ class ProcessorIntegrationTest extends WebTestBase { */ public function checkLanguageIntegration() { $index = $this->loadIndex(); - $processors = $index->getProcessorSettings(); + $processors = $index->getProcessors(); $this->assertTrue(!empty($processors['language']), 'The "language" processor is enabled by default.'); - unset($processors['language']); - $index->setProcessorSettings($processors)->save(); + $index->removeProcessor('language'); $processors = $this->loadIndex()->getProcessors(); $this->assertTrue(!empty($processors['language']), 'The "language" processor cannot be disabled.'); } @@ -228,11 +225,6 @@ class ProcessorIntegrationTest extends WebTestBase { */ public function checkTransliterationIntegration() { $this->enableProcessor('transliteration'); - - $edit = array( - 'processors[transliteration][settings][fields][search_api_language]' => FALSE, - ); - $this->editSettingsForm($edit, 'transliteration'); } /** @@ -240,10 +232,9 @@ class ProcessorIntegrationTest extends WebTestBase { */ public function checkUrlFieldIntegration() { $index = $this->loadIndex(); - $processors = $index->getProcessorSettings(); + $processors = $index->getProcessors(); $this->assertTrue(!empty($processors['add_url']), 'The "Add URL" processor is enabled by default.'); - unset($processors['add_url']); - $index->setProcessorSettings($processors)->save(); + $index->removeProcessor('add_url'); $processors = $this->loadIndex()->getProcessors(); $this->assertTrue(!empty($processors['add_url']), 'The "Add URL" processor cannot be disabled.'); } diff --git a/src/Tests/Processor/ProcessorTestBase.php b/src/Tests/Processor/ProcessorTestBase.php index 2809c31..cc93553 100644 --- a/src/Tests/Processor/ProcessorTestBase.php +++ b/src/Tests/Processor/ProcessorTestBase.php @@ -9,6 +9,7 @@ namespace Drupal\search_api\Tests\Processor; use Drupal\search_api\Entity\Index; use Drupal\search_api\Entity\Server; +use Drupal\search_api\Item\Field; use Drupal\search_api\Utility; use Drupal\system\Tests\Entity\EntityUnitTestBase; @@ -87,29 +88,44 @@ abstract class ProcessorTestBase extends EntityUnitTestBase { 'id' => 'index', 'name' => 'Index name', 'status' => TRUE, - 'datasources' => array('entity:comment', 'entity:node'), - 'server' => 'server', - 'tracker' => 'default', - )); - $this->index->setServer($this->server); - $this->index->setFieldSettings(array( - 'subject' => array( - 'label' => 'Subject', - 'type' => 'text', - 'datasource_id' => 'entity:comment', - 'property_path' => 'subject', + 'datasource_settings' => array( + 'entity:comment' => array( + 'plugin_id' => 'entity:comment', + 'settings' => array(), + ), + 'entity:node' => array( + 'plugin_id' => 'entity:node', + 'settings' => array(), + ), ), - 'title' => array( - 'label' => 'Title', - 'type' => 'text', - 'datasource_id' => 'entity:node', - 'property_path' => 'title', + 'server' => 'server', + 'tracker_settings' => array( + 'default' => array( + 'plugin_id' => 'default', + 'settings' => array() + ) ), )); + $this->index->setServer($this->server); + + $subject_field = new Field($this->index, 'subject'); + $subject_field->setType('text'); + $subject_field->setLabel('Subject'); + $subject_field->setDatasourceId('entity:comment'); + $subject_field->setPropertyPath('subject'); + $this->index->addField($subject_field); + + $title_field = new Field($this->index, 'title'); + $title_field->setType('text'); + $title_field->setLabel('Title'); + $title_field->setDatasourceId('entity:node'); + $title_field->setPropertyPath('title'); + $this->index->addField($title_field); + if ($processor) { - $this->index->setProcessorSettings(array( + $this->index->set('processor_settings', array( $processor => array( - 'processor_id' => $processor, + 'plugin_id' => $processor, 'weights' => array(), 'settings' => array(), ), diff --git a/src/Tests/Processor/RenderedItemTest.php b/src/Tests/Processor/RenderedItemTest.php index 8a920e4..6ff3751 100644 --- a/src/Tests/Processor/RenderedItemTest.php +++ b/src/Tests/Processor/RenderedItemTest.php @@ -10,6 +10,8 @@ namespace Drupal\search_api\Tests\Processor; use Drupal\Core\TypedData\DataDefinition; use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; +use Drupal\search_api\Item\Field; +use Drupal\search_api\Item\FieldInterface; use Drupal\search_api\Utility; use Drupal\user\Entity\Role; use Drupal\user\Entity\User; @@ -49,6 +51,11 @@ class RenderedItemTest extends ProcessorTestBase { $this->installSchema('system', array('router')); \Drupal::service('router.builder')->rebuild(); + $rendered_item_field = new Field($this->index, 'rendered_item'); + $rendered_item_field->setPropertyPath('rendered_item'); + $rendered_item_field->setType('text'); + $this->index->addField($rendered_item_field); + // Create a node type for testing. $type = NodeType::create(array( 'type' => 'page', @@ -115,6 +122,29 @@ class RenderedItemTest extends ProcessorTestBase { } /** + * Tests that the processor is added correctly. + */ + public function testAddProcessor() { + $processors = $this->index->getProcessors(); + $this->assertTrue(array_key_exists('rendered_item', $processors), 'Processor successfully added.'); + + $items = array(); + foreach ($this->nodes as $node) { + $items[] = array( + 'datasource' => 'entity:node', + 'item' => $node->getTypedData(), + 'item_id' => $node->id(), + 'text' => 'node text' . $node->id(), + ); + } + $items = $this->generateItems($items); + + foreach ($items as $item) { + $this->assertTrue(array_key_exists('rendered_item', $item->getFields()), 'Field successfully added.'); + } + } + + /** * Tests whether the rendered_item field is correctly filled by the processor. */ public function testPreprocessIndexItems() { 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..72e1971 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 @@ -38,27 +38,30 @@ fields: label: 'Item language' type: string property_path: search_api_language - index_locked: true + indexed_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/search_api_test_dependencies/src/Plugin/search_api/datasource/TestDatasource.php b/tests/search_api_test_dependencies/src/Plugin/search_api/datasource/TestDatasource.php index 800f18f..58056ac 100644 --- a/tests/search_api_test_dependencies/src/Plugin/search_api/datasource/TestDatasource.php +++ b/tests/search_api_test_dependencies/src/Plugin/search_api/datasource/TestDatasource.php @@ -29,7 +29,10 @@ class TestDatasource extends DatasourcePluginBase { * {@inheritdoc} */ public function calculateDependencies() { - return $this->configuration; + if (isset($this->configuration['settings'])) { + return $this->configuration['settings']; + } + return array(); } /** diff --git a/tests/search_api_test_dependencies/src/Plugin/search_api/processor/TestProcessor.php b/tests/search_api_test_dependencies/src/Plugin/search_api/processor/TestProcessor.php index 5ce230c..01136fa 100644 --- a/tests/search_api_test_dependencies/src/Plugin/search_api/processor/TestProcessor.php +++ b/tests/search_api_test_dependencies/src/Plugin/search_api/processor/TestProcessor.php @@ -21,7 +21,10 @@ class TestProcessor extends ProcessorPluginBase { * {@inheritdoc} */ public function calculateDependencies() { - return $this->configuration; + if (isset($this->configuration)) { + return $this->configuration; + } + return array(); } /** diff --git a/tests/search_api_test_dependencies/src/Plugin/search_api/tracker/TestTracker.php b/tests/search_api_test_dependencies/src/Plugin/search_api/tracker/TestTracker.php index 6ac77d4..dd43a65 100644 --- a/tests/search_api_test_dependencies/src/Plugin/search_api/tracker/TestTracker.php +++ b/tests/search_api_test_dependencies/src/Plugin/search_api/tracker/TestTracker.php @@ -21,7 +21,10 @@ class TestTracker extends BasicTracker { * {@inheritdoc} */ public function calculateDependencies() { - return $this->configuration; + if (isset($this->configuration)) { + return $this->configuration; + } + return array(); } /** diff --git a/tests/src/Kernel/CliTest.php b/tests/src/Kernel/CliTest.php index 70fd5cc..96109ad 100644 --- a/tests/src/Kernel/CliTest.php +++ b/tests/src/Kernel/CliTest.php @@ -94,15 +94,25 @@ class CliTest extends KernelTestBase { 'name' => 'Test index', 'id' => 'index', 'status' => 1, - 'datasources' => array('entity:entity_test'), - 'tracker' => 'default', + 'datasource_settings' => array( + 'entity:entity_test' => array( + 'plugin_id' => 'entity:entity_test', + 'settings' => array() + ) + ), + 'tracker_settings' => array( + 'default' => array( + 'plugin_id' => 'default', + 'settings' => array() + ) + ), 'server' => $this->server->id(), 'options' => array('index_directly' => TRUE), )); $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 +132,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..2c23e62 100644 --- a/tests/src/Kernel/DependencyRemovalTest.php +++ b/tests/src/Kernel/DependencyRemovalTest.php @@ -48,6 +48,9 @@ class DependencyRemovalTest extends KernelTestBase { public function setUp() { parent::setUp(); + $this->installSchema('user', array('users_data')); + $this->installEntitySchema('user'); + // The server tasks manager is needed when removing a server. $mock = $this->getMock('Drupal\search_api\Task\ServerTaskManagerInterface'); $this->container->set('search_api.server_task_manager', $mock); @@ -57,9 +60,17 @@ class DependencyRemovalTest extends KernelTestBase { $this->index = Index::create(array( 'id' => 'test_index', 'name' => 'Test index', - 'tracker' => 'default', - 'datasources' => array( - 'entity:user', + 'tracker_settings' => array( + 'default' => array( + 'plugin_id' => 'default', + 'settings' => array(), + ) + ), + 'datasource_settings' => array( + 'entity:user' => array( + 'plugin_id' => 'entity:user', + 'settings' => array(), + ) ), )); @@ -173,17 +184,21 @@ class DependencyRemovalTest extends KernelTestBase { // server. $dependency_key = $this->dependency->getConfigDependencyKey(); $dependency_name = $this->dependency->getConfigDependencyName(); - $this->index->set('datasources', array( - 'entity:user', - 'search_api_test_dependencies', - )); - $this->index->set('datasource_configs', array( + $datasource_settings = array( + 'entity:user' => array( + 'plugin_id' => 'entity:user', + 'settings' => array(), + ), 'search_api_test_dependencies' => array( - $dependency_key => array( - $dependency_name, + 'plugin_id' => 'search_api_test_dependencies', + 'settings' => array( + $dependency_key => array( + $dependency_name, + ), ), - ), - )); + ) + ); + $this->index->set('datasource_settings', $datasource_settings); $this->index->save(); // Check the dependencies were calculated correctly. @@ -210,15 +225,14 @@ class DependencyRemovalTest extends KernelTestBase { // Depending on whether the plugin should have removed the dependency or // not, make sure the right action was taken. - $datasources = $this->index->get('datasources'); - $datasource_configs = $this->index->get('datasource_configs'); + $datasource_settings = $this->index->get('datasource_settings'); + if ($remove_dependency) { - $this->assertContains('search_api_test_dependencies', $datasources, 'Datasource not removed'); - $this->assertEmpty($datasource_configs['search_api_test_dependencies'], 'Datasource settings adapted'); + $this->assertArrayHasKey('search_api_test_dependencies', $datasource_settings, 'Datasource not removed'); + $this->assertEmpty($datasource_settings['search_api_test_dependencies'], 'Datasource settings adapted'); } else { - $this->assertNotContains('search_api_test_dependencies', $datasources, 'Datasource removed'); - $this->assertArrayNotHasKey('search_api_test_dependencies', $datasource_configs, 'Datasource config removed'); + $this->assertArrayNotHasKey('search_api_test_dependencies', $datasource_settings, 'Datasource config removed'); } } @@ -231,15 +245,15 @@ class DependencyRemovalTest extends KernelTestBase { // server. $dependency_key = $this->dependency->getConfigDependencyKey(); $dependency_name = $this->dependency->getConfigDependencyName(); - $this->index->set('datasources', array( - 'search_api_test_dependencies', - )); - $this->index->set('datasource_configs', array( + $this->index->set('datasource_settings', array( 'search_api_test_dependencies' => array( - $dependency_key => array( - $dependency_name, + 'plugin_id' => 'search_api_test_dependencies', + 'settings' => array( + $dependency_key => array( + $dependency_name, + ), ), - ), + ) )); $this->index->save(); @@ -275,9 +289,9 @@ class DependencyRemovalTest extends KernelTestBase { // server. $dependency_key = $this->dependency->getConfigDependencyKey(); $dependency_name = $this->dependency->getConfigDependencyName(); - $this->index->set('processors', array( + $this->index->set('processor_settings', 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, @@ -311,13 +325,13 @@ class DependencyRemovalTest extends KernelTestBase { // Depending on whether the plugin should have removed the dependency or // not, make sure the right action was taken. - $processors = $this->index->get('processors'); + $processor_settings = $this->index->get('processor_settings'); if ($remove_dependency) { - $this->assertArrayHasKey('search_api_test_dependencies', $processors, 'Processor not removed'); - $this->assertEmpty($processors['search_api_test_dependencies']['settings'], 'Processor settings adapted'); + $this->assertArrayHasKey('search_api_test_dependencies', $processor_settings, 'Processor not removed'); + $this->assertEmpty($processor_settings['search_api_test_dependencies']['settings'], 'Processor settings adapted'); } else { - $this->assertArrayNotHasKey('search_api_test_dependencies', $processors, 'Processor removed'); + $this->assertArrayNotHasKey('search_api_test_dependencies', $processor_settings, 'Processor removed'); } } @@ -331,17 +345,23 @@ class DependencyRemovalTest extends KernelTestBase { * @dataProvider dependencyTestDataProvider */ public function testTrackerDependency($remove_dependency) { + // Set the server on the index and save that, too. + $this->index->set('server', $this->dependency->id()); + // Set the tracker for the index and save it. The tracker configuration // contains the dependencies it will return – in our case, we use the test // 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. @@ -353,13 +373,12 @@ class DependencyRemovalTest extends KernelTestBase { // \Drupal\search_api_test_dependencies\Plugin\search_api\tracker\TestTracker::onDependencyRemoval(). $key = 'search_api_test_dependencies.tracker.remove'; \Drupal::state()->set($key, $remove_dependency); + // If the index resets the tracker, it needs to know the ID of the default // tracker. - if (!$remove_dependency) { - \Drupal::configFactory()->getEditable('search_api.settings') - ->set('default_tracker', 'default') - ->save(); - } + \Drupal::configFactory()->getEditable('search_api.settings') + ->set('default_tracker', 'default') + ->save(); // Delete the tracker's dependency. $this->dependency->delete(); @@ -375,9 +394,14 @@ 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'); - if ($remove_dependency) { + $tracker_settings = $this->index->get('tracker_settings'); + + // Get first tracker in the list if there is a list. There should always + // be a tracker so there is no issue in taking the first key. + $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..dacdc3e 100644 --- a/tests/src/Kernel/LanguageKernelTest.php +++ b/tests/src/Kernel/LanguageKernelTest.php @@ -104,12 +104,23 @@ class LanguageKernelTest extends KernelTestBase { $this->server->save(); // Create a test index. + $datasource_id = 'entity:' . $this->testEntityTypeId; $this->index = Index::create(array( 'name' => 'Test Index', 'id' => 'test_index', 'status' => 1, - 'datasources' => array('entity:' . $this->testEntityTypeId), - 'tracker' => 'default', + 'datasource_settings' => array( + $datasource_id => array( + 'plugin_id' => $datasource_id, + 'settings' => array(), + ), + ), + 'tracker_settings' => array( + 'default'=> array( + 'plugin_id' => 'default', + 'settings' => array(), + ), + ), 'server' => $this->server->id(), 'options' => array('index_directly' => FALSE), )); @@ -153,10 +164,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 +186,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 +208,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 +226,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.'); } }