diff --git a/config/schema/search_api.datasource.schema.yml b/config/schema/search_api.datasource.schema.yml index fc0f4a2..e98979d 100644 --- a/config/schema/search_api.datasource.schema.yml +++ b/config/schema/search_api.datasource.schema.yml @@ -3,7 +3,7 @@ label: 'Entity datasource configuration' mapping: default: - type: integer + type: string label: 'Decides if we want to include or exclude the selected bundles.' bundles: type: sequence 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 3cc2de8..7539dff 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 @@ -206,7 +206,7 @@ datasource_settings: 'entity:node': plugin_id: 'entity:node' settings: - default: 1 + default: '1' bundles: article: '0' page: '0' diff --git a/src/Entity/Index.php b/src/Entity/Index.php index 95078e6..5ddeece 100644 --- a/src/Entity/Index.php +++ b/src/Entity/Index.php @@ -125,7 +125,7 @@ class Index extends ConfigEntityBase implements IndexInterface { * * @var \Drupal\search_api\Item\FieldInterface[]|null */ - protected $fieldInstances = NULL; + protected $fieldInstances; /** * An array of options configuring this index. @@ -140,14 +140,18 @@ class Index extends ConfigEntityBase implements IndexInterface { * The settings of the datasources selected for this index. * * The array has the following structure: + * + * @code * array( - * DS => array( - * 'plugin_id' => 'DS', + * 'DATASOURCE_ID' => array( + * 'plugin_id' => 'DATASOURCE_ID', * 'settings' => array(), * ), + * … * ) + * @endcode * - * @var string[] + * @var array */ protected $datasource_settings = array(); @@ -156,26 +160,32 @@ class Index extends ConfigEntityBase implements IndexInterface { * * In the ::preSave method we're saving the contents of these back into the * $datasource_settings array. When adding, removing or changing configuration - * we should always use these. + * we should therefore always manipulate this property instead of the stored + * one. * * @var \Drupal\search_api\Datasource\DatasourceInterface[]|null * * @see getDatasources() */ - protected $datasourceInstances = NULL; + protected $datasourceInstances; /** - * The tracker settings + * The tracker settings. * * The array has the following structure: + * + * @code * array( - * TS => array( - * 'plugin_id' => 'TS', + * 'TRACKER_ID' => array( + * 'plugin_id' => 'TRACKER_ID', * 'settings' => array(), * ), * ) + * @endcode + * + * There is always just a single entry in the array. * - * @var string[] + * @var array */ protected $tracker_settings = NULL; @@ -184,7 +194,8 @@ class Index extends ConfigEntityBase implements IndexInterface { * * In the ::preSave method we're saving the contents of these back into the * $tracker_settings array. When adding, removing or changing configuration - * we should always use this instance. + * we should therefore always manipulate this property instead of the stored + * one. * * @var \Drupal\search_api\Tracker\TrackerInterface|null * @@ -195,7 +206,7 @@ class Index extends ConfigEntityBase implements IndexInterface { /** * The ID of the server on which data should be indexed. * - * @var string + * @var string|null */ protected $server; @@ -219,15 +230,21 @@ class Index extends ConfigEntityBase implements IndexInterface { * The array of processor settings. * * The array has the following structure: + * + * @code * array( - * PS => array( - * 'plugin_id' => 'PS', - * 'settings' => array('weights' => array(), ...), + * 'PROCESSOR_ID' => array( + * 'plugin_id' => 'PROCESSOR_ID', + * 'settings' => array( + * 'weights' => array(), + * … + * ), * ), + * … * ) + * @endcode * * @var array - * An array containing processor settings. */ protected $processor_settings = array(); @@ -236,12 +253,14 @@ class Index extends ConfigEntityBase implements IndexInterface { * * In the ::preSave method we're saving the contents of these back into the * $tracker_settings array. When adding, removing or changing configuration - * we should always use this instance. + * we should therefore always manipulate this property instead of the stored + * one. + * * @var \Drupal\search_api\Processor\ProcessorInterface[]|null * * @see loadProcessors() */ - protected $processorInstances = NULL; + protected $processorInstances; /** * Whether reindexing has been triggered for this index in this page request. @@ -415,7 +434,11 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function getTrackerId() { - return $this->getTrackerInstance()->getPluginId(); + if (empty($this->tracker_settings)) { + return \Drupal::config('search_api.settings')->get('default_tracker'); + } + reset($this->tracker_settings); + return key($this->tracker_settings); } /** @@ -423,19 +446,17 @@ class Index extends ConfigEntityBase implements IndexInterface { */ public function getTrackerInstance() { if (!$this->trackerInstance) { + $tracker_id = $this->getTrackerId(); - if (is_null($this->tracker_settings)) { - $tracker_plugin_configuration = array('index' => $this); - $plugin_id = 'default'; + if (empty($this->tracker_settings[$tracker_id]['settings'])) { + $configuration = array('index' => $this); } else { - $plugins = array_keys($this->tracker_settings); - $tracker_plugin_configuration = array('index' => $this) + $this->tracker_settings[$plugins[0]]['settings']; - $plugin_id = $this->tracker_settings[$plugins[0]]['plugin_id']; + $configuration = array('index' => $this) + $this->tracker_settings[$tracker_id]['settings']; } - if (!($this->trackerInstance = \Drupal::service('plugin.manager.search_api.tracker')->createInstance($plugin_id, $tracker_plugin_configuration))) { - $args['@tracker'] = $this->getTrackerId(); + if (!($this->trackerInstance = \Drupal::service('plugin.manager.search_api.tracker')->createInstance($tracker_id, $configuration))) { + $args['@tracker'] = $tracker_id; $args['%index'] = $this->label(); throw new SearchApiException(new FormattableMarkup('The tracker with ID "@tracker" could not be retrieved for index %index.', $args)); } @@ -449,7 +470,6 @@ class Index extends ConfigEntityBase implements IndexInterface { */ public function setTracker(TrackerInterface $tracker) { $this->trackerInstance = $tracker; - return $this; } @@ -512,18 +532,10 @@ class Index extends ConfigEntityBase implements IndexInterface { $processors = $this->loadProcessors(); - // Filter the processors by status, ::loadProcessors() returns an array of - // enabled processors for all possible processors. - // Because we usually return early from this method if ::$processorInstances - // is already set we can safely assume that ::$processor_settings still - // holds the enabled processors we're settings ::$processorInstances to an - // array of processors that only have the same ID's as the ones in - // ::$processor_settings. - // - // We should only reach this point in the code once after the index is - // loaded. - $processors_settings = $this->processor_settings; - $this->processorInstances = array_intersect_key($processors, $processors_settings); + // Filter the processors by status. + // We should only reach this point in the code once, at the first call after + // the index is loaded. + $this->processorInstances = array_intersect_key($processors, $this->processor_settings); return $this->processorInstances; } @@ -564,6 +576,11 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function addProcessor(ProcessorInterface $processor) { + // Make sure the processorInstances are loaded before trying to add a plugin + // to them. + if (is_null($this->processorInstances)) { + $this->getProcessors(); + } $this->processorInstances[$processor->getPluginId()] = $processor; return $this; @@ -654,15 +671,8 @@ class Index extends ConfigEntityBase implements IndexInterface { throw new SearchApiException(new FormattableMarkup('%field_id is a reserved value and cannot be used as the machine name of a normal field.', $args)); } - // @todo If we have a single field object per field on the index, we'd just - // need the first two checks – and that would also (correctly) prevent - // renaming a field to an existing, different machine name. $old_field = $this->getField($field_id); - $would_overwrite = $old_field - && $old_field != $field - && ($old_field->getDatasourceId() != $field->getDatasourceId() - || $old_field->getPropertyPath() != $field->getPropertyPath()); - if ($would_overwrite) { + if ($old_field && $old_field != $field) { $args['%field_id'] = $field_id; throw new SearchApiException(new FormattableMarkup('Cannot add field with machine name %field_id: machine name is already taken.', $args)); } @@ -676,7 +686,7 @@ class Index extends ConfigEntityBase implements IndexInterface { * {@inheritdoc} */ public function renameField($old_field_id, $new_field_id) { - if (isset($this->getFields()[$old_field_id])) { + if (!isset($this->getFields()[$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)); } @@ -1098,7 +1108,7 @@ class Index extends ConfigEntityBase implements IndexInterface { ) ); - // Dump the active datasources to the settings array. + // Write the active datasources to the settings array. $this->datasource_settings = array(); foreach ($this->getDatasources() as $plugin_id => $datasource) { $this->datasource_settings[$plugin_id] = array( @@ -1107,6 +1117,14 @@ 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->getFields() as $field_id => $field) { + $field->setIndexedLocked(FALSE); + $field->setTypeLocked(FALSE); + $field->setHidden(FALSE); + } + // Call the preIndexSave() method of all applicable processors. foreach ($this->getProcessorsByStage(ProcessorInterface::STAGE_PRE_INDEX_SAVE) as $processor) { $processor->preIndexSave();