diff --git a/core/lib/Drupal/Core/Plugin/ConfigurablePluginInterface.php b/core/lib/Drupal/Core/Plugin/ConfigurablePluginInterface.php new file mode 100644 index 0000000..b66d4d3 --- /dev/null +++ b/core/lib/Drupal/Core/Plugin/ConfigurablePluginInterface.php @@ -0,0 +1,56 @@ +manager = $manager; + $this->instanceIDs = drupal_map_assoc($instance_ids); + $this->configuration = $configuration; + } + + /** + * {@inheritdoc} + */ + protected function initializePlugin($instance_id) { + if (!isset($this->pluginInstances[$instance_id])) { + $this->pluginInstances[$instance_id] = $this->manager->createInstance($instance_id, $this->configuration); + } + } + +} diff --git a/core/modules/node/config/search.search.node_search.yml b/core/modules/node/config/search.search.node_search.yml new file mode 100644 index 0000000..5c73892 --- /dev/null +++ b/core/modules/node/config/search.search.node_search.yml @@ -0,0 +1,7 @@ +id: node_search +label: Node +uuid: 25687eeb-4bb5-469c-ad05-5eb24cd7012c +status: '1' +langcode: en +plugin: node_search +configuration: { } diff --git a/core/modules/node/lib/Drupal/node/Plugin/Search/NodeSearch.php b/core/modules/node/lib/Drupal/node/Plugin/Search/NodeSearch.php index 6c194d4..04dbdfb 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/Search/NodeSearch.php +++ b/core/modules/node/lib/Drupal/node/Plugin/Search/NodeSearch.php @@ -14,9 +14,8 @@ use Drupal\Core\Entity\EntityManager; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\KeyValueStore\KeyValueStoreInterface; -use Drupal\search\Plugin\SearchPluginBase; +use Drupal\search\Plugin\ConfigurableSearchPluginBase; use Drupal\search\Annotation\SearchPlugin; - use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -28,7 +27,7 @@ * path = "node" * ) */ -class NodeSearch extends SearchPluginBase { +class NodeSearch extends ConfigurableSearchPluginBase { /** * A database connection object. @@ -298,7 +297,7 @@ public function indexStatus() { /** * {@inheritdoc} */ - public function addToAdminForm(array &$form, array &$form_state) { + public function form(array $form, array &$form_state) { // Output form for defining rank factor weights. $form['content_ranking'] = array( '#type' => 'details', @@ -319,12 +318,13 @@ public function addToAdminForm(array &$form, array &$form_state) { '#default_value' => variable_get('node_rank_' . $var, 0), ); } + return $form; } /** * {@inheritdoc} */ - public function submitAdminForm(array &$form, array &$form_state) { + public function submit(array &$form, array &$form_state) { foreach ($this->moduleHandler->invokeAll('ranking') as $var => $values) { if (isset($form_state['values']['node_rank_' . $var])) { // @todo Fix when https://drupal.org/node/1831632 is in. diff --git a/core/modules/search/config/search.settings.yml b/core/modules/search/config/search.settings.yml index a1a88b4..ff32f97 100644 --- a/core/modules/search/config/search.settings.yml +++ b/core/modules/search/config/search.settings.yml @@ -1,8 +1,5 @@ -active_modules: - - node - - user and_or_limit: '7' -default_module: node +default_entity: node_search index: cron_limit: '100' overlap_cjk: '1' diff --git a/core/modules/search/lib/Drupal/search/Controller/SearchController.php b/core/modules/search/lib/Drupal/search/Controller/SearchController.php new file mode 100644 index 0000000..7c7f54f --- /dev/null +++ b/core/modules/search/lib/Drupal/search/Controller/SearchController.php @@ -0,0 +1,117 @@ +searchManager = $search_manager; + $this->state = $state; + $this->urlGenerator = $url_generator; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.search'), + $container->get('state'), + $container->get('url_generator') + ); + } + + /** + * Provides a list of eligible search plugins for configuring. + * + * @return array + * A list of search plugins that can be configured. + */ + public function addSearchConfig() { + // @todo Remove this when https://drupal.org/node/2032535 is in. + drupal_set_title(t('Add new search configuration')); + + $search_types = array(); + foreach ($this->searchManager->getDefinitions() as $plugin_id => $search_info) { + $search_types[$plugin_id] = array( + 'title' => $search_info['title'], + 'href' => 'admin/config/search/settings/add/' . $plugin_id, + 'localized_options' => array(), + ); + } + return array( + '#theme' => 'admin_block_content', + '#content' => $search_types, + ); + } + + /** + * Performs an operation on the search entity. + * + * @param \Drupal\search\SearchInterface $search + * The search entity. + * @param string $op + * The operation to perform, usually 'enable' or 'disable'. + * + * @return \Symfony\Component\HttpFoundation\RedirectResponse + * A redirect back to the search settings page. + */ + public function performOperation(SearchInterface $search, $op) { + // Perform the operation. + if (!$search->isDefaultSearch()) { + $search->$op()->save(); + } + else { + debug($search->id()); + } + return new RedirectResponse($this->urlGenerator->generateFromPath('admin/config/search/settings', array('absolute' => TRUE))); + } + +} diff --git a/core/modules/search/lib/Drupal/search/Form/SearchAddForm.php b/core/modules/search/lib/Drupal/search/Form/SearchAddForm.php new file mode 100644 index 0000000..6e11b77 --- /dev/null +++ b/core/modules/search/lib/Drupal/search/Form/SearchAddForm.php @@ -0,0 +1,33 @@ +entity->setPlugin($search_plugin_id); + $definition = $this->entity->getPluginDefinition(); + $this->entity->set('label', $definition['title']); + return parent::buildForm($form, $form_state); + } + +} diff --git a/core/modules/search/lib/Drupal/search/Form/SearchDeleteForm.php b/core/modules/search/lib/Drupal/search/Form/SearchDeleteForm.php new file mode 100644 index 0000000..9ff0c2d --- /dev/null +++ b/core/modules/search/lib/Drupal/search/Form/SearchDeleteForm.php @@ -0,0 +1,47 @@ + $this->entity->label())); + } + + /** + * {@inheritdoc} + */ + public function getCancelPath() { + return 'admin/config/search/settings'; + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return t('Delete'); + } + + /** + * {@inheritdoc} + */ + public function submit(array $form, array &$form_state) { + $this->entity->delete(); + $form_state['redirect'] = 'admin/config/search/settings'; + drupal_set_message(t('The %label search has been deleted.', array('%label' => $this->entity->label()))); + } + +} diff --git a/core/modules/search/lib/Drupal/search/Form/SearchEditForm.php b/core/modules/search/lib/Drupal/search/Form/SearchEditForm.php new file mode 100644 index 0000000..34c8bef --- /dev/null +++ b/core/modules/search/lib/Drupal/search/Form/SearchEditForm.php @@ -0,0 +1,23 @@ + $this->entity->label()))); + parent::init($form_state); + } + +} diff --git a/core/modules/search/lib/Drupal/search/Form/SearchFormBase.php b/core/modules/search/lib/Drupal/search/Form/SearchFormBase.php new file mode 100644 index 0000000..f310210 --- /dev/null +++ b/core/modules/search/lib/Drupal/search/Form/SearchFormBase.php @@ -0,0 +1,167 @@ +storageController = $storage_controller; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + return new static( + $container->get('module_handler'), + $container->get('plugin.manager.entity')->getStorageController($entity_type) + ); + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state) { + $this->plugin = $this->entity->getPlugin(); + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function form(array $form, array &$form_state) { + $form['label'] = array( + '#type' => 'textfield', + '#title' => t('Label'), + '#default_value' => $this->entity->label(), + '#maxlength' => '255', + ); + + $form['id'] = array( + '#type' => 'machine_name', + '#default_value' => $this->entity->id(), + '#disabled' => !$this->entity->isNew(), + '#maxlength' => 64, + '#machine_name' => array( + 'exists' => array($this, 'exists'), + ), + ); + $form['plugin'] = array( + '#type' => 'value', + '#value' => $this->entity->get('plugin'), + ); + $form['type'] = array( + '#type' => 'value', + '#value' => $this->entity->getType(), + ); + + if ($this->plugin instanceof ConfigurablePluginInterface) { + $form += $this->plugin->form($form, $form_state); + } + + return parent::form($form, $form_state); + } + + /** + * Determines if the search entity already exists. + * + * @param string $id + * The search configuration ID. + * + * @return bool + * TRUE if the search configuration exists, FALSE otherwise. + */ + public function exists($id) { + $search = $this->storageController->load($id); + return !empty($search); + } + + /** + * {@inheritdoc} + */ + protected function actions(array $form, array &$form_state) { + $actions = parent::actions($form, $form_state); + unset($actions['delete']); + return $actions; + } + + /** + * {@inheritdoc} + */ + public function validate(array $form, array &$form_state) { + parent::validate($form, $form_state); + + if ($this->plugin instanceof ConfigurablePluginInterface) { + $this->plugin->validate($form, $form_state); + } + } + + /** + * {@inheritdoc} + */ + public function submit(array $form, array &$form_state) { + parent::submit($form, $form_state); + + if ($this->plugin instanceof ConfigurablePluginInterface) { + $this->plugin->submit($form, $form_state); + } + return $this->entity; + } + + /** + * {@inheritdoc} + */ + public function save(array $form, array &$form_state) { + $this->entity->save(); + drupal_set_message(t('The search has been successfully saved.')); + + $form_state['redirect'] = 'admin/config/search/settings'; + } + +} diff --git a/core/modules/search/lib/Drupal/search/Form/SearchSettingsForm.php b/core/modules/search/lib/Drupal/search/Form/SearchSettingsForm.php deleted file mode 100644 index 4d52e69..0000000 --- a/core/modules/search/lib/Drupal/search/Form/SearchSettingsForm.php +++ /dev/null @@ -1,266 +0,0 @@ -searchSettings = $config_factory->get('search.settings'); - $this->searchPluginManager = $manager; - $this->moduleHandler = $module_handler; - $this->state = $state; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('config.factory'), - $container->get('plugin.manager.search'), - $container->get('module_handler'), - $container->get('keyvalue')->get('state') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormID() { - return 'search_admin_settings'; - } - - /** - * Returns names of available search modules. - * - * @return array - * An array of the names of enabled modules that call hook_search_info - * sorted into alphabetical order. - */ - protected function getModuleOptions() { - $options = array(); - $names = system_get_module_info('name'); - foreach ($this->searchPluginManager->getDefinitions() as $search_info) { - if (isset($names[$search_info['module']])) { - $options[$search_info['module']] = $names[$search_info['module']]; - } - } - asort($options, SORT_STRING); - return $options; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, array &$form_state) { - // Collect some stats. - $remaining = 0; - $total = 0; - $active_plugins = $this->searchPluginManager->getActivePlugins(); - foreach ($active_plugins as $plugin) { - if ($status = $plugin->indexStatus()) { - $remaining += $status['remaining']; - $total += $status['total']; - } - } - - $this->moduleHandler->loadAllIncludes('admin.inc'); - $count = format_plural($remaining, 'There is 1 item left to index.', 'There are @count items left to index.'); - $percentage = ((int) min(100, 100 * ($total - $remaining) / max(1, $total))) . '%'; - $status = '

' . t('%percentage of the site has been indexed.', array('%percentage' => $percentage)) . ' ' . $count . '

'; - $form['status'] = array( - '#type' => 'details', - '#title' => t('Indexing status'), - ); - $form['status']['status'] = array('#markup' => $status); - $form['status']['wipe'] = array( - '#type' => 'submit', - '#value' => t('Re-index site'), - '#submit' => array(array($this, 'searchAdminReindexSubmit')), - ); - - $items = drupal_map_assoc(array(10, 20, 50, 100, 200, 500)); - - // Indexing throttle: - $form['indexing_throttle'] = array( - '#type' => 'details', - '#title' => t('Indexing throttle') - ); - $form['indexing_throttle']['cron_limit'] = array( - '#type' => 'select', - '#title' => t('Number of items to index per cron run'), - '#default_value' => $this->searchSettings->get('index.cron_limit'), - '#options' => $items, - '#description' => t('The maximum number of items indexed in each pass of a cron maintenance task. If necessary, reduce the number of items to prevent timeouts and memory errors while indexing.', array('@cron' => url('admin/reports/status'))) - ); - // Indexing settings: - $form['indexing_settings'] = array( - '#type' => 'details', - '#title' => t('Indexing settings') - ); - $form['indexing_settings']['info'] = array( - '#markup' => t('

Changing the settings below will cause the site index to be rebuilt. The search index is not cleared but systematically updated to reflect the new settings. Searching will continue to work but new content won\'t be indexed until all existing content has been re-indexed.

The default settings should be appropriate for the majority of sites.

') - ); - $form['indexing_settings']['minimum_word_size'] = array( - '#type' => 'number', - '#title' => t('Minimum word length to index'), - '#default_value' => $this->searchSettings->get('index.minimum_word_size'), - '#min' => 1, - '#max' => 1000, - '#description' => t('The number of characters a word has to be to be indexed. A lower setting means better search result ranking, but also a larger database. Each search query must contain at least one keyword that is this size (or longer).') - ); - $form['indexing_settings']['overlap_cjk'] = array( - '#type' => 'checkbox', - '#title' => t('Simple CJK handling'), - '#default_value' => $this->searchSettings->get('index.overlap_cjk'), - '#description' => t('Whether to apply a simple Chinese/Japanese/Korean tokenizer based on overlapping sequences. Turn this off if you want to use an external preprocessor for this instead. Does not affect other languages.') - ); - - $form['active'] = array( - '#type' => 'details', - '#title' => t('Active search modules') - ); - $module_options = $this->getModuleOptions(); - $form['active']['active_modules'] = array( - '#type' => 'checkboxes', - '#title' => t('Active modules'), - '#title_display' => 'invisible', - '#default_value' => $this->searchSettings->get('active_modules'), - '#options' => $module_options, - '#description' => t('Choose which search modules are active from the available modules.') - ); - $form['active']['default_module'] = array( - '#title' => t('Default search module'), - '#type' => 'radios', - '#default_value' => $this->searchSettings->get('default_module'), - '#options' => $module_options, - '#description' => t('Choose which search module is the default.') - ); - - // Per module plugin settings - foreach ($active_plugins as $plugin) { - $plugin->addToAdminForm($form, $form_state); - } - // Set #submit so we are sure it's invoked even if one of - // the active search modules added its own #submit. - $form['#submit'][] = array($this, 'submitForm'); - - return parent::buildForm($form, $form_state); - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, array &$form_state) { - parent::validateForm($form, $form_state); - - // Check whether we selected a valid default. - if ($form_state['triggering_element']['#value'] != t('Reset to defaults')) { - $new_modules = array_filter($form_state['values']['active_modules']); - $default = $form_state['values']['default_module']; - if (!in_array($default, $new_modules, TRUE)) { - form_set_error('default_module', t('Your default search module is not selected as an active module.')); - } - } - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, array &$form_state) { - parent::submitForm($form, $form_state); - - // If these settings change, the index needs to be rebuilt. - if (($this->searchSettings->get('index.minimum_word_size') != $form_state['values']['minimum_word_size']) || ($this->searchSettings->get('index.overlap_cjk') != $form_state['values']['overlap_cjk'])) { - $this->searchSettings->set('index.minimum_word_size', $form_state['values']['minimum_word_size']); - $this->searchSettings->set('index.overlap_cjk', $form_state['values']['overlap_cjk']); - drupal_set_message(t('The index will be rebuilt.')); - search_reindex(); - } - $this->searchSettings->set('index.cron_limit', $form_state['values']['cron_limit']); - $this->searchSettings->set('default_module', $form_state['values']['default_module']); - - // Handle per-plugin submission logic. - foreach ($this->searchPluginManager->getActivePlugins() as $plugin) { - $plugin->submitAdminForm($form, $form_state); - } - - // Check whether we are resetting the values. - if ($form_state['triggering_element']['#value'] == t('Reset to defaults')) { - $new_modules = array('node', 'user'); - } - else { - $new_modules = array_filter($form_state['values']['active_modules']); - } - if ($this->searchSettings->get('active_modules') != $new_modules) { - $this->searchSettings->set('active_modules', $new_modules); - drupal_set_message(t('The active search modules have been changed.')); - $this->state->set('menu_rebuild_needed', TRUE); - } - $this->searchSettings->save(); - } - - /** - * Form submission handler for the reindex button on the search admin settings - * form. - */ - public function searchAdminReindexSubmit(array $form, array &$form_state) { - // send the user to the confirmation page - $form_state['redirect'] = 'admin/config/search/settings/reindex'; - } - -} diff --git a/core/modules/search/lib/Drupal/search/Plugin/ConfigurableSearchPluginBase.php b/core/modules/search/lib/Drupal/search/Plugin/ConfigurableSearchPluginBase.php new file mode 100644 index 0000000..d41836a --- /dev/null +++ b/core/modules/search/lib/Drupal/search/Plugin/ConfigurableSearchPluginBase.php @@ -0,0 +1,48 @@ +configuration += $this->getDefaultConfiguration(); + } + + /** + * Returns default configuration for this search plugin. + * + * @return array + */ + protected function getDefaultConfiguration() { + return array(); + } + + /** + * {@inheritdoc} + */ + public function getConfiguration() { + return $this->configuration; + } + + /** + * {@inheritdoc} + */ + public function validate(array &$form, array &$form_state) { + } + +} diff --git a/core/modules/search/lib/Drupal/search/Plugin/Core/Entity/Search.php b/core/modules/search/lib/Drupal/search/Plugin/Core/Entity/Search.php new file mode 100644 index 0000000..42d2f9e --- /dev/null +++ b/core/modules/search/lib/Drupal/search/Plugin/Core/Entity/Search.php @@ -0,0 +1,194 @@ +pluginBag = new DefaultPluginBag(\Drupal::service('plugin.manager.search'), array($this->plugin), $this->configuration); + } + + /** + * {@inheritdoc} + */ + public function getPlugin() { + return $this->pluginBag->get($this->plugin); + } + + /** + * {@inheritdoc} + */ + public function setPlugin($plugin_id) { + $this->plugin = $plugin_id; + $this->pluginBag->addInstanceID($plugin_id); + } + + /** + * {@inheritdoc} + */ + public function getPluginDefinition() { + return $this->getPlugin()->getPluginDefinition(); + } + + /** + * {@inheritdoc} + */ + public function isConfigurable() { + return $this->getPlugin() instanceof ConfigurablePluginInterface; + } + + /** + * {@inheritdoc} + */ + public function isDefaultSearch() { + return \Drupal::service('config.factory')->get('search.settings')->get('default_entity') == $this->id(); + } + + /** + * {@inheritdoc} + */ + public function uri() { + return array( + 'path' => 'admin/config/search/settings/manage/' . $this->id(), + 'options' => array( + 'entity_type' => $this->entityType, + 'entity' => $this, + ), + ); + } + + /** + * {@inheritdoc} + */ + public function getExportProperties() { + $properties = parent::getExportProperties(); + $names = array( + 'plugin', + 'configuration', + ); + foreach ($names as $name) { + $properties[$name] = $this->get($name); + } + return $properties; + } + + /** + * {@inheritdoc} + */ + public function preSave(EntityStorageControllerInterface $storage_controller) { + parent::preSave($storage_controller); + + $plugin = $this->getPlugin(); + // If this plugin has any configuration, ensure that it is set. + if ($plugin instanceof ConfigurablePluginInterface) { + $this->set('configuration', $plugin->getConfiguration()); + } + } + + /** + * {@inheritdoc} + */ + public function postSave(EntityStorageControllerInterface $storage_controller, $update = TRUE) { + parent::postSave($storage_controller, $update); + + \Drupal::state()->set('menu_rebuild_needed', TRUE); + } + + /** + * {@inheritdoc} + */ + public static function sort($a, $b) { + $a_status = (int) $a->status(); + $b_status = (int) $b->status(); + if ($a_status != $b_status) { + return ($a_status > $b_status) ? -1 : 1; + } + return strnatcasecmp($a->label(), $b->label()); + } + +} diff --git a/core/modules/search/lib/Drupal/search/Plugin/SearchInterface.php b/core/modules/search/lib/Drupal/search/Plugin/SearchInterface.php index c4cc34d..a9e4850 100644 --- a/core/modules/search/lib/Drupal/search/Plugin/SearchInterface.php +++ b/core/modules/search/lib/Drupal/search/Plugin/SearchInterface.php @@ -7,10 +7,12 @@ namespace Drupal\search\Plugin; +use Drupal\Component\Plugin\PluginInspectionInterface; + /** * Defines a common interface for all SearchPlugin objects. */ -interface SearchInterface { +interface SearchInterface extends PluginInspectionInterface { /** * Set the keywords, params, and attributes to be used by execute(). @@ -115,32 +117,4 @@ public function resetIndex(); */ public function indexStatus(); - /** - * Add elements to the search settings form. - * - * The core search module only invokes this method on active module plugins. - * - * @param $form - * Nested array of form elements that comprise the form. - * @param $form_state - * A keyed array containing the current state of the form. The arguments - * that drupal_get_form() was originally called with are available in the - * array $form_state['build_info']['args']. - */ - public function addToAdminForm(array &$form, array &$form_state); - - /** - * Handle any submission for elements on the search settings form. - * - * The core search module only invokes this method on active module plugins. - * - * @param $form - * Nested array of form elements that comprise the form. - * @param $form_state - * A keyed array containing the current state of the form. The arguments - * that drupal_get_form() was originally called with are available in the - * array $form_state['build_info']['args']. - */ - public function submitAdminForm(array &$form, array &$form_state); - } diff --git a/core/modules/search/lib/Drupal/search/Plugin/SearchPluginBase.php b/core/modules/search/lib/Drupal/search/Plugin/SearchPluginBase.php index d69c4a6..86490c3 100644 --- a/core/modules/search/lib/Drupal/search/Plugin/SearchPluginBase.php +++ b/core/modules/search/lib/Drupal/search/Plugin/SearchPluginBase.php @@ -83,7 +83,7 @@ public function buildResults() { return array( '#theme' => 'search_results', '#results' => $results, - '#module' => $this->pluginDefinition['module'], + '#module' => $this->pluginDefinition['provider'], ); } @@ -109,18 +109,4 @@ public function indexStatus() { return array('remaining' => 0, 'total' => 0); } - /** - * {@inheritdoc} - */ - public function addToAdminForm(array &$form, array &$form_state) { - // Empty default implementation. - } - - /** - * {@inheritdoc} - */ - public function submitAdminForm(array &$form, array &$form_state) { - // Empty default implementation. - } - } diff --git a/core/modules/search/lib/Drupal/search/SearchAccessController.php b/core/modules/search/lib/Drupal/search/SearchAccessController.php new file mode 100644 index 0000000..be812a3 --- /dev/null +++ b/core/modules/search/lib/Drupal/search/SearchAccessController.php @@ -0,0 +1,34 @@ +configFactory = $config_factory; + $this->configFactory->enterContext($context); + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + return new static( + $entity_type, + $entity_info, + $container->get('plugin.manager.entity')->getStorageController($entity_type), + $container->get('module_handler'), + $container->get('config.factory'), + $container->get('config.context.free') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'search_admin_settings'; + } + + /** + * {@inheritdoc} + */ + public function render() { + return drupal_get_form($this); + } + + /** + * {@inheritdoc} + */ + public function buildHeader() { + $header['label'] = t('Label'); + $header['plugin'] = t('Plugin'); + $header['status'] = t('Status'); + $header['operations'] = t('Operations'); + return $header; + } + + /** + * {@inheritdoc} + */ + public function buildRow(EntityInterface $entity) { + $row['label'] = String::checkPlain($entity->label()); + $definition = $entity->getPlugin()->getPluginDefinition(); + $row['plugin'] = $definition['title']; + $row['status'] = $entity->status() ? t('Enabled') : t('Disabled'); + $row['operations']['data'] = $this->buildOperations($entity); + return $row; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state) { + $search_settings = $this->configFactory->get('search.settings'); + // Collect some stats. + $remaining = 0; + $total = 0; + $entities = $this->load(); + foreach ($entities as $entity) { + if ($entity->status() && $status = $entity->getPlugin()->indexStatus()) { + $remaining += $status['remaining']; + $total += $status['total']; + } + } + + $this->moduleHandler->loadAllIncludes('admin.inc'); + $count = format_plural($remaining, 'There is 1 item left to index.', 'There are @count items left to index.'); + $percentage = ((int) min(100, 100 * ($total - $remaining) / max(1, $total))) . '%'; + $status = '

' . t('%percentage of the site has been indexed.', array('%percentage' => $percentage)) . ' ' . $count . '

'; + $form['status'] = array( + '#type' => 'details', + '#title' => t('Indexing status'), + ); + $form['status']['status'] = array('#markup' => $status); + $form['status']['wipe'] = array( + '#type' => 'submit', + '#value' => t('Re-index site'), + '#submit' => array(array($this, 'searchAdminReindexSubmit')), + ); + + $items = drupal_map_assoc(array(10, 20, 50, 100, 200, 500)); + + // Indexing throttle: + $form['indexing_throttle'] = array( + '#type' => 'details', + '#title' => t('Indexing throttle') + ); + $form['indexing_throttle']['cron_limit'] = array( + '#type' => 'select', + '#title' => t('Number of items to index per cron run'), + '#default_value' => $search_settings->get('index.cron_limit'), + '#options' => $items, + '#description' => t('The maximum number of items indexed in each pass of a cron maintenance task. If necessary, reduce the number of items to prevent timeouts and memory errors while indexing.', array('@cron' => url('admin/reports/status'))) + ); + // Indexing settings: + $form['indexing_settings'] = array( + '#type' => 'details', + '#title' => t('Indexing settings') + ); + $form['indexing_settings']['info'] = array( + '#markup' => t('

Changing the settings below will cause the site index to be rebuilt. The search index is not cleared but systematically updated to reflect the new settings. Searching will continue to work but new content won\'t be indexed until all existing content has been re-indexed.

The default settings should be appropriate for the majority of sites.

') + ); + $form['indexing_settings']['minimum_word_size'] = array( + '#type' => 'number', + '#title' => t('Minimum word length to index'), + '#default_value' => $search_settings->get('index.minimum_word_size'), + '#min' => 1, + '#max' => 1000, + '#description' => t('The number of characters a word has to be to be indexed. A lower setting means better search result ranking, but also a larger database. Each search query must contain at least one keyword that is this size (or longer).') + ); + $form['indexing_settings']['overlap_cjk'] = array( + '#type' => 'checkbox', + '#title' => t('Simple CJK handling'), + '#default_value' => $search_settings->get('index.overlap_cjk'), + '#description' => t('Whether to apply a simple Chinese/Japanese/Korean tokenizer based on overlapping sequences. Turn this off if you want to use an external preprocessor for this instead. Does not affect other languages.') + ); + + $form['search_plugins'] = array( + '#type' => 'details', + '#title' => t('Search plugins'), + ); + $form['search_plugins']['inline_actions'] = array( + '#prefix' => '', + ); + $form['search_plugins']['inline_actions']['add'] = array( + '#theme' => 'menu_local_action', + '#link' => array( + 'title' => t('Add new search settings'), + 'href' => 'admin/config/search/settings/add', + ), + ); + $rows = array(); + foreach ($entities as $entity) { + $rows[$entity->id()] = $this->buildRow($entity); + } + $form['search_plugins']['default_entity'] = array( + '#type' => 'tableselect', + '#header' => $this->buildHeader(), + '#options' => $rows, + '#required' => TRUE, + '#multiple' => FALSE, + '#default_value' => $search_settings->get('default_entity'), + ); + + $form['actions']['#type'] = 'actions'; + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Save configuration'), + '#button_type' => 'primary', + ); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function getOperations(EntityInterface $entity) { + $operations = parent::getOperations($entity); + + // Prevent the default search from being disabled or deleted. + if ($entity->isDefaultSearch()) { + unset($operations['disable'], $operations['delete']); + } + + return $operations; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + $search_settings = $this->configFactory->get('search.settings'); + // If these settings change, the index needs to be rebuilt. + if (($search_settings->get('index.minimum_word_size') != $form_state['values']['minimum_word_size']) || ($search_settings->get('index.overlap_cjk') != $form_state['values']['overlap_cjk'])) { + $search_settings->set('index.minimum_word_size', $form_state['values']['minimum_word_size']); + $search_settings->set('index.overlap_cjk', $form_state['values']['overlap_cjk']); + drupal_set_message(t('The index will be rebuilt.')); + search_reindex(); + } + + // If the default search is disabled, enable it. + $entity = $this->storage->load($form_state['values']['default_entity']); + if (!$entity->status()) { + $entity->enable()->save(); + } + + $search_settings + ->set('index.cron_limit', $form_state['values']['cron_limit']) + ->set('default_entity', $form_state['values']['default_entity']) + ->save(); + + drupal_set_message(t('The configuration options have been saved.')); + } + + /** + * Form submission handler for the reindex button on the search admin settings + * form. + */ + public function searchAdminReindexSubmit(array &$form, array &$form_state) { + // Send the user to the confirmation page. + $form_state['redirect'] = 'admin/config/search/settings/reindex'; + } + +} diff --git a/core/modules/search/lib/Drupal/search/SearchPluginManager.php b/core/modules/search/lib/Drupal/search/SearchPluginManager.php index 0100b28..9661332 100644 --- a/core/modules/search/lib/Drupal/search/SearchPluginManager.php +++ b/core/modules/search/lib/Drupal/search/SearchPluginManager.php @@ -8,29 +8,19 @@ namespace Drupal\search; use Drupal\Component\Utility\NestedArray; -use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Plugin\DefaultPluginManager; /** - * SearchExecute plugin manager. + * Provides a search plugin manager. */ class SearchPluginManager extends DefaultPluginManager { /** - * The config factory. - * - * @var \Drupal\Core\Config\ConfigFactory - */ - protected $configFactory; - - /** * {@inheritdoc} */ - public function __construct(\Traversable $namespaces, ConfigFactory $config_factory) { + public function __construct(\Traversable $namespaces) { $annotation_namespaces = array('Drupal\search\Annotation' => $namespaces['Drupal\search']); parent::__construct('Search', $namespaces, $annotation_namespaces, 'Drupal\search\Annotation\SearchPlugin'); - - $this->configFactory = $config_factory; } /** @@ -43,54 +33,7 @@ public function processDefinition(&$definition, $plugin_id) { $definition += array( 'title' => $definition['provider'], 'path' => $definition['provider'], - 'module' => $definition['provider'], ); } - /** - * Returns definitions for active search plugins. - * - * @return \Drupal\search\Plugin\SearchInterface[] - * An array of active search plugins, keyed by their ID. - */ - public function getActivePlugins() { - $plugins = array(); - foreach ($this->getActiveDefinitions() as $plugin_id => $definition) { - $plugins[$plugin_id] = $this->createInstance($plugin_id); - } - return $plugins; - } - - /** - * Returns definitions for active search plugins keyed by their ID. - * - * @return array - * An array of active search plugin definitions, keyed by their ID. - */ - public function getActiveDefinitions() { - $active_definitions = array(); - $active_modules = array_flip($this->configFactory->get('search.settings')->get('active_modules')); - foreach ($this->getDefinitions() as $plugin_id => $definition) { - if (isset($active_modules[$definition['module']])) { - $active_definitions[$plugin_id] = $definition; - } - } - return $active_definitions; - } - - /** - * Returns definitions for active search plugins keyed by their module. - * - * @return array - * An array of active search plugin definitions, keyed by their providing - * module. - */ - public function getActiveDefinitionsByModule() { - $active_definitions = array(); - foreach ($this->getActiveDefinitions() as $definition) { - // Re-key by plugin module name. - $active_definitions[$definition['module']] = $definition; - } - return $active_definitions; - } } diff --git a/core/modules/search/lib/Drupal/search/Tests/SearchConfigSettingsFormTest.php b/core/modules/search/lib/Drupal/search/Tests/SearchConfigSettingsFormTest.php index 961d163..118a8e7 100644 --- a/core/modules/search/lib/Drupal/search/Tests/SearchConfigSettingsFormTest.php +++ b/core/modules/search/lib/Drupal/search/Tests/SearchConfigSettingsFormTest.php @@ -66,22 +66,22 @@ function testSearchSettingsPage() { $this->assertText(t('There are @count items left to index.', array('@count' => 0))); // Test the re-index button. - $this->drupalPost('admin/config/search/settings', array(), t('Re-index site')); + $this->drupalPost(NULL, array(), t('Re-index site')); $this->assertText(t('Are you sure you want to re-index the site')); - $this->drupalPost('admin/config/search/settings/reindex', array(), t('Re-index site')); + $this->drupalPost(NULL, array(), t('Re-index site')); $this->assertText(t('The index will be rebuilt')); $this->drupalGet('admin/config/search/settings'); $this->assertText(t('There is 1 item left to index.')); // Test that the form saves with the default values. - $this->drupalPost('admin/config/search/settings', array(), t('Save configuration')); + $this->drupalPost(NULL, array(), t('Save configuration')); $this->assertText(t('The configuration options have been saved.'), 'Form saves with the default values.'); // Test that the form does not save with an invalid word length. $edit = array( 'minimum_word_size' => $this->randomName(3), ); - $this->drupalPost('admin/config/search/settings', $edit, t('Save configuration')); + $this->drupalPost(NULL, $edit, t('Save configuration')); $this->assertNoText(t('The configuration options have been saved.'), 'Form does not save with an invalid word length.'); } @@ -98,19 +98,24 @@ function testSearchModuleSettingsPage() { $this->assertNoText(t('Extra type settings')); $this->assertNoText(t('Boost method')); + $this->clickLink(t('Add new search settings')); + // Ensure that the test module is listed as an option - $this->assertTrue($this->xpath('//input[@id="edit-active-modules-search-extra-type"]'), 'Checkbox for activating search for an extra module is visible'); - $this->assertTrue($this->xpath('//input[@id="edit-default-module-search-extra-type"]'), 'Radio button for setting extra module as default search module is visible'); + $this->assertLinkByHref('admin/config/search/settings/add/search_extra_type_search'); // Enable search for the test module - $edit['active_modules[search_extra_type]'] = 'search_extra_type'; - $edit['default_module'] = 'search_extra_type'; + $edit = array( + 'default_entity' => 'dummy_search_type', + 'minimum_word_size' => 5, + ); $this->drupalPost('admin/config/search/settings', $edit, t('Save configuration')); + $this->assertTrue($this->xpath('//input[@id="edit-minimum-word-size" and @value="5"]'), 'Common search settings can be modified if a module-specific form is active'); - // Ensure that the settings fieldset is visible after enabling search for - // the test module - $this->assertText(t('Extra type settings')); - $this->assertText(t('Boost method')); + // Ensure that the modifications took effect. + $this->assertText(t('The configuration options have been saved.')); + + $this->assertText(t('Dummy search type')); + $this->drupalGet('admin/config/search/settings/manage/dummy_search_type'); // Ensure that the default setting was picked up from the default config $this->assertTrue($this->xpath('//select[@id="edit-extra-type-settings-boost"]//option[@value="bi" and @selected="selected"]'), 'Module specific settings are picked up from the default config'); @@ -118,14 +123,11 @@ function testSearchModuleSettingsPage() { // Change extra type setting and also modify a common search setting. $edit = array( 'extra_type_settings[boost]' => 'ii', - 'minimum_word_size' => 5, ); - $this->drupalPost('admin/config/search/settings', $edit, t('Save configuration')); + $this->drupalPost(NULL, $edit, t('Save')); - // Ensure that the modifications took effect. - $this->assertText(t('The configuration options have been saved.')); + $this->drupalGet('admin/config/search/settings/manage/dummy_search_type'); $this->assertTrue($this->xpath('//select[@id="edit-extra-type-settings-boost"]//option[@value="ii" and @selected="selected"]'), 'Module specific settings can be changed'); - $this->assertTrue($this->xpath('//input[@id="edit-minimum-word-size" and @value="5"]'), 'Common search settings can be modified if a module-specific form is active'); } /** @@ -136,19 +138,19 @@ function testSearchModuleDisabling() { // the tab title, 'keys' are the keywords to search for, and 'text' is // the text to assert is on the results page. $module_info = array( - 'node' => array( + 'node_search' => array( 'path' => 'node', 'title' => 'Content', 'keys' => 'pizza', 'text' => $this->search_node->label(), ), - 'user' => array( + 'user_search' => array( 'path' => 'user', 'title' => 'User', 'keys' => $this->search_user->name, 'text' => $this->search_user->mail, ), - 'search_extra_type' => array( + 'dummy_search_type' => array( 'path' => 'dummy_path', 'title' => 'Dummy search type', 'keys' => 'foo', @@ -160,15 +162,17 @@ function testSearchModuleDisabling() { // Test each module if it's enabled as the only search module. foreach ($modules as $module) { // Enable the one module and disable other ones. - $info = $module_info[$module]; - $edit = array(); + $edit = array('default_entity' => $module); + $this->drupalPost('admin/config/search/settings', $edit, t('Save configuration')); + foreach ($modules as $other) { - $edit['active_modules[' . $other . ']'] = (($other == $module) ? $module : FALSE); + if ($other != $module) { + $this->drupalGet('admin/config/search/settings/manage/' . $other . '/disable'); + } } - $edit['default_module'] = $module; - $this->drupalPost('admin/config/search/settings', $edit, t('Save configuration')); // Run a search from the correct search URL. + $info = $module_info[$module]; $this->drupalGet('search/' . $info['path'] . '/' . $info['keys']); $this->assertNoText('no results', $info['title'] . ' search found results'); $this->assertText($info['text'], 'Correct search text found'); @@ -200,12 +204,11 @@ function testSearchModuleDisabling() { // Test with all search modules enabled. When you go to the search // page or run search, all modules should be shown. - $edit = array(); - foreach ($modules as $module) { - $edit['active_modules[' . $module . ']'] = $module; + foreach (entity_load_multiple('search') as $search) { + $search->enable()->save(); } - $edit['default_module'] = 'node'; + $edit = array('default_entity' => 'node_search'); $this->drupalPost('admin/config/search/settings', $edit, t('Save configuration')); foreach (array('search/node/pizza', 'search/node') as $path) { @@ -216,4 +219,5 @@ function testSearchModuleDisabling() { } } } + } diff --git a/core/modules/search/search.module b/core/modules/search/search.module index c6aef5b..ffe969b 100644 --- a/core/modules/search/search.module +++ b/core/modules/search/search.module @@ -152,17 +152,34 @@ function search_menu() { $items['search'] = array( 'title' => 'Search', 'page callback' => 'search_view', - 'page arguments' => array(NULL, '', ''), 'access callback' => 'search_is_active', 'type' => MENU_SUGGESTED_ITEM, 'file' => 'search.pages.inc', ); + $items['admin/config/search/settings/add'] = array( + 'title' => t('Add'), + 'type' => MENU_VISIBLE_IN_BREADCRUMB, + 'route_name' => 'search.add', + ); + $items['admin/config/search/settings/add/%'] = array( + 'route_name' => 'search.add_settings', + ); $items['admin/config/search/settings'] = array( 'title' => 'Search settings', 'description' => 'Configure relevance settings for search and other indexing options.', 'route_name' => 'search_settings', 'weight' => -10, ); + $items['admin/config/search/settings/manage/%search'] = array( + 'title callback' => 'entity_page_label', + 'title arguments' => array(5), + 'route_name' => 'search.edit', + ); + $items['admin/config/search/settings/manage/%search/delete'] = array( + 'title callback' => 'entity_page_label', + 'title arguments' => array(5), + 'route_name' => 'search.delete', + ); $items['admin/config/search/settings/reindex'] = array( 'title' => 'Clear index', 'route_name' => 'search_reindex_confirm', @@ -176,27 +193,28 @@ function search_menu() { // system appears to be having two sets of tabs. See discussion on issue // http://drupal.org/node/245103 for details. - $default_info = search_get_default_module_info(); + $default_info = search_get_default_entity_info(); if ($default_info) { - foreach (Drupal::service('plugin.manager.search')->getActiveDefinitionsByModule() as $module => $search_info) { + foreach (entity_load_multiple_by_properties('search', array('status' => '1')) as $search_id => $entity) { + $search_info = $entity->getPluginDefinition(); $path = 'search/' . $search_info['path']; $items[$path] = array( 'title' => $search_info['title'], 'page callback' => 'search_view', - 'page arguments' => array($search_info['id'], $module, ''), + 'page arguments' => array($search_id, ''), 'access callback' => '_search_menu_access', - 'access arguments' => array($module), + 'access arguments' => array($search_info['provider']), 'type' => MENU_LOCAL_TASK, 'file' => 'search.pages.inc', - 'weight' => $module == $default_info['module'] ? -10 : 0, + 'weight' => $search_info['provider'] == $default_info['provider'] ? -10 : 0, ); $items["$path/%menu_tail"] = array( 'title' => $search_info['title'], 'load arguments' => array('%map', '%index'), 'page callback' => 'search_view', - 'page arguments' => array($search_info['id'], $module, 2), + 'page arguments' => array($search_id, 2), 'access callback' => '_search_menu_access', - 'access arguments' => array($module), + 'access arguments' => array($search_info['provider']), // The default local task points to its parent, but this item points to // where it should so it should not be changed. 'type' => MENU_LOCAL_TASK, @@ -213,11 +231,30 @@ function search_menu() { } /** + * Loads an active search entity. + * + * @param string $entity_id + * The search entity ID. + * @param bool $active_only + * (optional) TRUE if only an active search entity should be returned. + * Defaults to FALSE. + * + * @return \Drupal\search\SearchInterface + * The search entity. + */ +function search_load($entity_id, $active_only = FALSE) { + $entity = entity_load('search', $entity_id); + if (!$active_only || ($entity && $entity->status())) { + return $entity; + } +} + +/** * Determines access for the 'search' path. */ function search_is_active() { // This path cannot be accessed if there are no active modules. - return user_access('search content') && Drupal::service('plugin.manager.search')->getActiveDefinitions(); + return user_access('search content') && Drupal::entityQuery('search')->condition('status', 1)->execute(); } /** @@ -226,15 +263,19 @@ function search_is_active() { * @return array * The search plugin definition for the default search module, if any. */ -function search_get_default_module_info() { - $info = Drupal::service('plugin.manager.search')->getActiveDefinitionsByModule(); - $default = config('search.settings')->get('default_module'); - if (isset($info[$default])) { - return $info[$default]; +function search_get_default_entity_info() { + $definition = array(); + $default = config('search.settings')->get('default_entity'); + if (!$default || !$entity = search_load($default, TRUE)) { + // The variable setting does not match any active plugin, so just return + // the info for the first active plugin (if any). + $id = Drupal::entityQuery('search') + ->condition('status', 1) + ->range(0, 1) + ->execute(); + $definition = entity_load('search', reset($id))->getPluginDefinition(); } - // The variable setting does not match any active module, so just return - // the info for the first active module (if any). - return reset($info); + return $definition; } /** @@ -270,8 +311,8 @@ function _search_menu_access($name) { */ function search_reindex($sid = NULL, $module = NULL, $reindex = FALSE, $langcode = NULL) { if ($module == NULL && $sid == NULL) { - foreach (Drupal::service('plugin.manager.search')->getActivePlugins() as $plugin) { - $plugin->resetIndex(); + foreach (entity_load_multiple_by_properties('search', array('status' => '1')) as $entity) { + $entity->getPlugin()->resetIndex(); } } else { @@ -329,8 +370,8 @@ function search_cron() { // to date. drupal_register_shutdown_function('search_update_totals'); - foreach (Drupal::service('plugin.manager.search')->getActivePlugins() as $plugin) { - $plugin->updateIndex(); + foreach (entity_load_multiple_by_properties('search', array('status' => '1')) as $entity) { + $entity->getPlugin()->updateIndex(); } } @@ -913,19 +954,13 @@ function search_expression_insert($expression, $option, $value = NULL) { * @see search_form_validate() * @see search_form_submit() */ -function search_form($form, &$form_state, $action = '', $keys = '', $module = NULL, $prompt = NULL) { - if (!$module) { - $module_info = search_get_default_module_info(); +function search_form($form, &$form_state, $action = '', $keys = '', $plugin_id = NULL, $prompt = NULL) { + if (!$plugin_id) { + $module_info = search_get_default_entity_info(); } else { - $info = Drupal::service('plugin.manager.search')->getActiveDefinitionsByModule(); - $module_info = isset($info[$module]) ? $info[$module] : FALSE; - } - - // Sanity check. - if (!$module_info) { - form_set_error(NULL, t('Search is currently disabled.'), 'error'); - return $form; + $entity = entity_load('search', $plugin_id); + $module_info = $entity->getPluginDefinition(); } if (!$action) { @@ -938,7 +973,7 @@ function search_form($form, &$form_state, $action = '', $keys = '', $module = NU $form['#action'] = url($action); // Record the $action for later use in redirecting. $form_state['action'] = $action; - $form['module'] = array('#type' => 'value', '#value' => $module); + $form['module'] = array('#type' => 'value', '#value' => $module_info['provider']); $form['basic'] = array('#type' => 'container', '#attributes' => array('class' => array('container-inline'))); $form['basic']['keys'] = array( '#type' => 'search', @@ -1003,7 +1038,7 @@ function search_box_form_submit($form, &$form_state) { } $form_id = $form['form_id']['#value']; - $info = search_get_default_module_info(); + $info = search_get_default_entity_info(); if ($info) { $form_state['redirect'] = 'search/' . $info['path'] . '/' . trim($form_state['values'][$form_id]); } diff --git a/core/modules/search/search.pages.inc b/core/modules/search/search.pages.inc index b828220..ed9449c 100644 --- a/core/modules/search/search.pages.inc +++ b/core/modules/search/search.pages.inc @@ -16,28 +16,18 @@ * @param $keys * Keywords to use for the search. */ -function search_view($plugin_id = NULL, $module = NULL, $keys = '') { - $info = FALSE; +function search_view($entity_id = NULL, $keys = '') { $keys = trim($keys); // Also try to pull search keywords out of the $_REQUEST variable to // support old GET format of searches for existing links. if (!$keys && !empty($_REQUEST['keys'])) { $keys = trim($_REQUEST['keys']); } - - $manager = Drupal::service('plugin.manager.search'); - if (!empty($module)) { - $active_module_info = $manager->getActiveDefinitionsByModule(); - if (isset($active_module_info[$module])) { - $info = $active_module_info[$module]; - } - } - - if (empty($plugin_id) || empty($info)) { + if (!$entity_id || !$entity = search_load($entity_id, TRUE)) { // No path or invalid path: find the default module. Note that if there // are no enabled search modules, this function should never be called, // since hook_menu() would not have defined any search paths. - $info = search_get_default_module_info(); + $info = search_get_default_entity_info(); // Redirect from bare /search or an invalid path to the default search path. $path = 'search/' . $info['path']; if ($keys) { @@ -45,9 +35,11 @@ function search_view($plugin_id = NULL, $module = NULL, $keys = '') { } return new RedirectResponse(url($path, array('absolute' => TRUE))); } - $plugin = $manager->createInstance($plugin_id); + + $plugin = $entity->getPlugin(); $request = Drupal::request(); $plugin->setSearch($keys, $request->query->all(), $request->attributes->all()); + $info = $plugin->getPluginDefinition(); // Default results output is an empty string. $results = array('#markup' => ''); // Process the search form. Note that if there is $_POST data, @@ -66,7 +58,7 @@ function search_view($plugin_id = NULL, $module = NULL, $keys = '') { } } // The form may be altered based on whether the search was run. - $build['search_form'] = drupal_get_form('search_form', NULL, $keys, $info['module']); + $build['search_form'] = drupal_get_form('search_form', NULL, $keys, $entity_id); $build['search_results'] = $results; return $build; diff --git a/core/modules/search/search.routing.yml b/core/modules/search/search.routing.yml index 8acf650..fac9ba2 100644 --- a/core/modules/search/search.routing.yml +++ b/core/modules/search/search.routing.yml @@ -1,12 +1,49 @@ search_settings: pattern: '/admin/config/search/settings' defaults: - _form: 'Drupal\search\Form\SearchSettingsForm' + _entity_list: 'search' requirements: _permission: 'administer search' + search_reindex_confirm: pattern: '/admin/config/search/settings/reindex' defaults: _form: 'Drupal\search\Form\ReindexConfirm' requirements: _permission: 'administer search' + +search.add: + pattern: '/admin/config/search/settings/add' + defaults: + _content: '\Drupal\search\Controller\SearchController::addSearchConfig' + requirements: + _permission: 'administer search' + +search.add_settings: + pattern: '/admin/config/search/settings/add/{search_plugin_id}' + defaults: + _entity_form: 'search.add' + requirements: + _entity_create_access: 'search' + +search.edit: + pattern: '/admin/config/search/settings/manage/{search}' + defaults: + _entity_form: 'search.edit' + requirements: + _entity_access: 'search.update' + +search.disable: + pattern: '/admin/config/search/settings/manage/{search}/{op}' + defaults: + _controller: '\Drupal\search\Controller\SearchController::performOperation' + requirements: + _permission: 'administer search' + op: 'enable|disable' + +search.delete: + pattern: '/admin/config/search/settings/manage/{search}/delete' + defaults: + _entity_form: 'search.delete' + requirements: + _entity_access: 'search.delete' diff --git a/core/modules/search/search.services.yml b/core/modules/search/search.services.yml index 22dc7f2..3bbd395 100644 --- a/core/modules/search/search.services.yml +++ b/core/modules/search/search.services.yml @@ -1,4 +1,4 @@ services: plugin.manager.search: class: Drupal\search\SearchPluginManager - arguments: ['@container.namespaces', '@config.factory'] + arguments: ['@container.namespaces'] diff --git a/core/modules/search/tests/modules/search_extra_type/config/search.search.dummy_search_type.yml b/core/modules/search/tests/modules/search_extra_type/config/search.search.dummy_search_type.yml new file mode 100644 index 0000000..b6e4996 --- /dev/null +++ b/core/modules/search/tests/modules/search_extra_type/config/search.search.dummy_search_type.yml @@ -0,0 +1,7 @@ +id: dummy_search_type +label: 'Dummy search type' +uuid: b55858d4-f428-474c-8200-ef47a4597aef +status: '1' +langcode: en +plugin: search_extra_type_search +configuration: { } diff --git a/core/modules/search/tests/modules/search_extra_type/lib/Drupal/search_extra_type/Plugin/Search/SearchExtraTypeSearch.php b/core/modules/search/tests/modules/search_extra_type/lib/Drupal/search_extra_type/Plugin/Search/SearchExtraTypeSearch.php index 3c44e18..a64e011 100644 --- a/core/modules/search/tests/modules/search_extra_type/lib/Drupal/search_extra_type/Plugin/Search/SearchExtraTypeSearch.php +++ b/core/modules/search/tests/modules/search_extra_type/lib/Drupal/search_extra_type/Plugin/Search/SearchExtraTypeSearch.php @@ -8,7 +8,7 @@ namespace Drupal\search_extra_type\Plugin\Search; use Drupal\Core\Config\Config; -use Drupal\search\Plugin\SearchPluginBase; +use Drupal\search\Plugin\ConfigurableSearchPluginBase; use Drupal\search\Annotation\SearchPlugin; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -21,7 +21,7 @@ * path = "dummy_path" * ) */ -class SearchExtraTypeSearch extends SearchPluginBase { +class SearchExtraTypeSearch extends ConfigurableSearchPluginBase { /** * @var \Drupal\Core\Config\Config @@ -123,7 +123,7 @@ public function buildResults() { /** * {@inheritdoc} */ - public function addToAdminForm(array &$form, array &$form_state) { + public function form(array $form, array &$form_state) { // Output form for defining rank factor weights. $form['extra_type_settings'] = array( '#type' => 'fieldset', @@ -140,12 +140,13 @@ public function addToAdminForm(array &$form, array &$form_state) { ), '#default_value' => $this->configSettings->get('boost'), ); + return $form; } /** * {@inheritdoc} */ - public function submitAdminForm(array &$form, array &$form_state) { + public function submit(array &$form, array &$form_state) { $this->configSettings ->set('boost', $form_state['values']['extra_type_settings']['boost']) ->save(); diff --git a/core/modules/user/config/search.search.user_search.yml b/core/modules/user/config/search.search.user_search.yml new file mode 100644 index 0000000..5134b69 --- /dev/null +++ b/core/modules/user/config/search.search.user_search.yml @@ -0,0 +1,7 @@ +id: user_search +label: User +uuid: c0d6b9a7-09a7-415f-b71a-26957bef635c +status: '1' +langcode: en +plugin: user_search +configuration: { }