diff --git a/search_api_db/src/Plugin/search_api/backend/Database.php b/search_api_db/src/Plugin/search_api/backend/Database.php index ef1af4a..5618afe 100644 --- a/search_api_db/src/Plugin/search_api/backend/Database.php +++ b/search_api_db/src/Plugin/search_api/backend/Database.php @@ -1287,7 +1287,7 @@ class Database extends BackendPluginBase { if (count($words) > 1 && max(array_map('strlen', $words)) <= 50) { // Overlong token is due to bad tokenizing. // Check for "Tokenizer" preprocessor on index. - if (empty($index->getProcessorSettings()['search_api_tokenizer']['status'])) { + if (empty($index->getProcessors(FALSE)['search_api_tokenizer']->getConfiguration()['status'])) { $this->getLogger()->warning('An overlong word (more than 50 characters) was encountered while indexing, due to bad tokenizing. It is recommended to enable the "Tokenizer" preprocessor for indexes using database servers. Otherwise, the backend class has to use its own, fixed tokenizing.'); } else { diff --git a/search_api_db/tests/src/Kernel/BackendTest.php b/search_api_db/tests/src/Kernel/BackendTest.php index 18f55c2..2b0d5f4 100644 --- a/search_api_db/tests/src/Kernel/BackendTest.php +++ b/search_api_db/tests/src/Kernel/BackendTest.php @@ -203,14 +203,15 @@ class BackendTest extends KernelTestBase { $property = 'body'; $this->addField($index, $property); - $processors = $index->getProcessorSettings(); - $processors['html_filter'] = array( - 'plugin_id' => 'html_filter', - 'weights' => array(), - 'settings' => array(), - ); - $index->setProcessorSettings($processors); + $processor = \Drupal::getContainer() + ->get('plugin.manager.search_api.processor') + ->createInstance('html_filter'); + + $index->addProcessor($processor, array()); $index->save(); + + $this->assertArrayHasKey('html_filter', $index->getProcessors()); + $this->assertArrayHasKey('body', $index->getFields()); } /** @@ -219,11 +220,12 @@ class BackendTest extends KernelTestBase { protected function disableHtmlFilter() { /** @var \Drupal\search_api\IndexInterface $index */ $index = $this->getIndex(); - $processors = $index->getProcessorSettings(); - unset($processors['html_filter']); - $index->setProcessorSettings($processors); $index->removeField('body'); + $index->removeProcessor('html_filter'); $index->save(); + + $this->assertArrayNotHasKey('html_filter', $index->getProcessors()); + $this->assertArrayNotHasKey('body', $index->getFields()); } /** diff --git a/src/Entity/Index.php b/src/Entity/Index.php index 89c6f74..3fe38b9 100644 --- a/src/Entity/Index.php +++ b/src/Entity/Index.php @@ -443,7 +443,7 @@ 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); } @@ -455,7 +455,7 @@ class Index extends ConfigEntityBase implements IndexInterface { */ public function getProcessorsByStage($stage, $only_enabled = TRUE) { $processors = $this->loadProcessors(); - $processor_settings = $this->getProcessorSettings(); + $processor_settings = $this->processor_settings; $processor_weights = array(); // Get a list of all processors meeting the criteria (stage and, optionally, @@ -482,6 +482,24 @@ class Index extends ConfigEntityBase implements IndexInterface { } /** + * {@inheritdoc} + */ + public function addProcessor(ProcessorInterface $processor, array $settings = array()) { + $this->processor_settings[$processor->getPluginId()] = array( + 'plugin_id' => $processor->getPluginId(), + 'weights' => array(), + 'settings' => $settings, + ); + } + + /** + * {@inheritdoc} + */ + public function removeProcessor($processor_id) { + unset($this->processor_settings[$processor_id]); + } + + /** * Retrieves all processors supported by this index. * * @return \Drupal\search_api\Processor\ProcessorInterface[] @@ -491,7 +509,7 @@ class Index extends ConfigEntityBase implements IndexInterface { 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->processorInstances[$name])) { @@ -517,21 +535,6 @@ class Index extends ConfigEntityBase implements IndexInterface { /** * {@inheritdoc} */ - public function getProcessorSettings() { - return $this->processor_settings; - } - - /** - * {@inheritdoc} - */ - public function setProcessorSettings(array $processors) { - $this->processor_settings = $processors; - return $this; - } - - /** - * {@inheritdoc} - */ public function preprocessIndexItems(array &$items) { foreach ($this->getProcessorsByStage(ProcessorInterface::STAGE_PREPROCESS_INDEX) as $processor) { $processor->preprocessIndexItems($items); @@ -1092,6 +1095,7 @@ 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)); $index_task_manager = \Drupal::getContainer() ->get('search_api.index_task_manager'); @@ -1221,8 +1225,8 @@ 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(); + $original_settings = $original->getProcessors(); + $new_settings = $this->getProcessors(); // Only actually do something when the processor settings are changed. if ($original_settings != $new_settings) { @@ -1235,7 +1239,7 @@ class Index extends ConfigEntityBase implements IndexInterface { // The processor is new, because it wasn't configured in the original // entity. if (!isset($original_settings[$key])) { - if ($processors[$key]->requiresReindexing(NULL, $new_settings[$key])) { + if ($processors[$key]->requiresReindexing(NULL, $new_settings[$key]->getConfiguration())) { $requires_reindex = TRUE; break; } @@ -1255,7 +1259,7 @@ class Index extends ConfigEntityBase implements IndexInterface { } $new_processor_settings = isset($new_settings[$key]) ? $new_settings[$key] : NULL; if (!isset($new_processor_settings) || $new_processor_settings != $old_processor_settings) { - if ($processors[$key]->requiresReindexing($old_processor_settings, $new_processor_settings)) { + if ($processors[$key]->requiresReindexing($old_processor_settings->getConfiguration(), $new_processor_settings->getConfiguration())) { $requires_reindex = TRUE; break; } diff --git a/src/Form/IndexProcessorsForm.php b/src/Form/IndexProcessorsForm.php index e1e24fe..5cff142 100644 --- a/src/Form/IndexProcessorsForm.php +++ b/src/Form/IndexProcessorsForm.php @@ -112,7 +112,7 @@ class IndexProcessorsForm extends EntityForm { } } - $processor_settings = $this->entity->getProcessorSettings(); + $enabled_processors = $this->entity->getProcessors(); $form['#tree'] = TRUE; $form['#attached']['library'][] = 'search_api/drupal.search_api.index-active-formatters'; @@ -132,7 +132,7 @@ class IndexProcessorsForm extends EntityForm { $form['status'][$processor_id] = array( '#type' => 'checkbox', '#title' => $processor->label(), - '#default_value' => $processor->isLocked() || !empty($processor_settings[$processor_id]), + '#default_value' => $processor->isLocked() || !empty($enabled_processors[$processor_id]), '#description' => $processor->getDescription(), '#attributes' => array( 'class' => array( @@ -171,9 +171,7 @@ 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] - : $processor->getDefaultWeight($stage); + $weight = $processor->getDefaultWeight($stage); if ($processor->isHidden()) { $form['processors'][$processor_id]['weights'][$stage] = array( '#type' => 'value', @@ -253,8 +251,6 @@ class IndexProcessorsForm extends EntityForm { $new_settings = array(); // Store processor settings. - // @todo Go through all available processors, enable/disable with method on - // processor plugin to allow reaction. /** @var \Drupal\search_api\Processor\ProcessorInterface $processor */ $processors = $this->entity->getProcessors(FALSE); foreach ($processors as $processor_id => $processor) { @@ -277,12 +273,21 @@ class IndexProcessorsForm extends EntityForm { } } - // Sort the processors so we won't have unnecessary changes. - ksort($new_settings); - $settings_changed = $new_settings != $this->entity->getProcessorSettings(); - $form_state->set('processors_changed', $settings_changed); - if ($settings_changed) { - $this->entity->setProcessorSettings($new_settings); + $old_processors = $this->entity->getProcessors(); + + foreach ($new_settings as $plugin_id => $new_processor_settings) { + /** @var \Drupal\search_api\Processor\ProcessorInterface $new_processor */ + $new_processor = $this->processorPluginManager->createInstance($plugin_id, $new_processor_settings['settings']); + if (isset($old_processors[$plugin_id])) { + $this->entity->removeProcessor($plugin_id); + } + $this->entity->addProcessor($new_processor, $new_settings[$plugin_id]['settings']); + } + + $new_processors = $this->entity->getProcessors(); + + if ($old_processors != $new_processors) { + $form_state->set('processors_changed', TRUE); } } diff --git a/src/IndexInterface.php b/src/IndexInterface.php index 9f3b26a..39f05f2 100644 --- a/src/IndexInterface.php +++ b/src/IndexInterface.php @@ -9,6 +9,7 @@ namespace Drupal\search_api; use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\search_api\Item\FieldInterface; +use Drupal\search_api\Processor\ProcessorInterface; use Drupal\search_api\Query\QueryInterface; use Drupal\search_api\Query\ResultSetInterface; @@ -277,22 +278,22 @@ interface IndexInterface extends ConfigEntityInterface { public function getProcessorsByStage($stage, $only_enabled = TRUE); /** - * Retrieves this index's processor settings. + * Add a processor. * - * @return array - * An array of processors and their settings. + * @param \Drupal\search_api\Processor\ProcessorInterface $processor + * Processor to be added. + * @param array $settings + * Settings for the processor + * @return void */ - public function getProcessorSettings(); + public function addProcessor(ProcessorInterface $processor, array $settings = array()); /** - * Sets this index's processor settings. - * - * @param array $processors - * An array of processors and their settings. + * Remove processor * - * @return $this + * @param $processor_id */ - public function setProcessorSettings(array $processors); + public function removeProcessor($processor_id); /** * Preprocesses data items for indexing. diff --git a/src/Tests/Processor/ProcessorIntegrationTest.php b/src/Tests/Processor/ProcessorIntegrationTest.php index 24ea7d4..6a137b0 100644 --- a/src/Tests/Processor/ProcessorIntegrationTest.php +++ b/src/Tests/Processor/ProcessorIntegrationTest.php @@ -48,18 +48,68 @@ class ProcessorIntegrationTest extends WebTestBase { * avoid the overhead of having one test per processor. */ public function testProcessorIntegration() { + // By default, the add_url and language processors are already enabled. + $enabled = array('add_url', 'language'); + $this->assertEqual($enabled, array_keys($this->loadIndex()->getProcessors())); + $this->checkContentAccessIntegration(); + $enabled[] = 'content_access'; + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + $this->checkHighlightIntegration(); + $enabled[] = 'highlight'; + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + $this->checkHtmlFilterIntegration(); + $enabled[] = 'html_filter'; + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + $this->checkIgnoreCaseIntegration(); + $enabled[] = 'ignorecase'; + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + $this->checkIgnoreCharactersIntegration(); - $this->checkLanguageIntegration(); + $enabled[] = 'ignore_character'; + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + $this->checkNodeStatusIntegration(); + $enabled[] = 'node_status'; + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + $this->checkRenderedItemIntegration(); + $enabled[] = 'rendered_item'; + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + $this->checkStopWordsIntegration(); + $enabled[] = 'stopwords'; + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + $this->checkTokenizerIntegration(); + $enabled[] = 'tokenizer'; + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + $this->checkTransliterationIntegration(); + $enabled[] = 'transliteration'; + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + + + // The 'language' and 'add_url' processors are are not available to be removed + $actual_processors = array_keys($this->loadIndex()->getProcessors()); + $this->assertEqual(sort($enabled), sort($actual_processors)); + $this->checkLanguageIntegration(); + $this->assertEqual(sort($enabled), sort($actual_processors)); $this->checkUrlFieldIntegration(); + $this->assertEqual(sort($enabled), sort($actual_processors)); } /** @@ -173,10 +223,11 @@ 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'); + $index->save(); + $processors = $this->loadIndex()->getProcessors(); $this->assertTrue(!empty($processors['language']), 'The "language" processor cannot be disabled.'); } @@ -245,10 +296,11 @@ 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'); + $index->save(); + $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 a4813c6..aa7bc3d 100644 --- a/src/Tests/Processor/ProcessorTestBase.php +++ b/src/Tests/Processor/ProcessorTestBase.php @@ -119,17 +119,10 @@ abstract class ProcessorTestBase extends EntityUnitTestBase { $this->index->addField($field_title); if ($processor) { - $this->index->setProcessorSettings(array( - $processor => array( - 'plugin_id' => $processor, - 'weights' => array(), - 'settings' => array(), - ), - )); - /** @var \Drupal\search_api\Processor\ProcessorPluginManager $plugin_manager */ $plugin_manager = \Drupal::service('plugin.manager.search_api.processor'); $this->processor = $plugin_manager->createInstance($processor, array('index' => $this->index)); + $this->index->addProcessor($this->processor, array()); } $this->index->save(); }