SearchSettingsForm.php 10.2 KB
Newer Older
1
2
3
4
5
6
7
8
<?php
/**
 * @file
 * Contains \Drupal\search\Form\SearchSettingsForm.
 */

namespace Drupal\search\Form;

9
10
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Config\Context\ContextInterface;
11
use Drupal\Core\Extension\ModuleHandlerInterface;
12
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
13
use Drupal\search\SearchPluginManager;
14
use Drupal\Core\Form\ConfigFormBase;
15
16
17
18
19
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Configure search settings for this site.
 */
20
class SearchSettingsForm extends ConfigFormBase {
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

  /**
   * A configuration object with the current search settings.
   *
   * @var \Drupal\Core\Config\Config
   */
  protected $searchSettings;

  /**
   * A search plugin manager object.
   *
   * @var \Drupal\search\SearchPluginManager
   */
  protected $searchPluginManager;

36
37
38
  /**
   * The module handler.
   *
39
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
40
41
42
43
44
45
46
47
48
49
50
   */
  protected $moduleHandler;

  /**
   * The Drupal state storage service.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
   */
  protected $state;

  /**
51
   * Constructs a \Drupal\search\Form\SearchSettingsForm object.
52
   *
53
54
55
56
   * @param \Drupal\Core\Config\ConfigFactory $config_factory
   *   The configuration factory object that manages search settings.
   * @param \Drupal\Core\Config\Context\ContextInterface $context
   *   The context interface
57
58
59
   * @param \Drupal\search\SearchPluginManager $manager
   *   The manager for search plugins.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
60
   *   The module handler
61
62
   * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $state
   *   The state key/value store interface, gives access to state based config settings.
63
   */
64
  public function __construct(ConfigFactory $config_factory, ContextInterface $context, SearchPluginManager $manager, ModuleHandlerInterface $module_handler, KeyValueStoreInterface $state) {
65
    parent::__construct($config_factory, $context);
66
67
    $this->searchSettings = $config_factory->get('search.settings');
    $this->searchPluginManager = $manager;
68
69
70
71
72
73
74
75
76
    $this->moduleHandler = $module_handler;
    $this->state = $state;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
77
78
      $container->get('config.factory'),
      $container->get('config.context.free'),
79
      $container->get('plugin.manager.search'),
80
      $container->get('module_handler'),
81
      $container->get('state')
82
83
84
85
86
87
88
89
90
91
92
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormID() {
    return 'search_admin_settings';
  }

  /**
93
   * Returns names of available search plugins.
94
95
   *
   * @return array
96
   *   An array of the names of available search plugins.
97
   */
98
99
100
101
102
103
104
  protected function getOptions() {
    $options = array();
    foreach ($this->searchPluginManager->getDefinitions() as $plugin_id => $search_info) {
      $options[$plugin_id] = $search_info['title'] . ' (' . $plugin_id . ')';
    }
    asort($options, SORT_STRING);
    return $options;
105
106
107
108
109
110
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, array &$form_state) {
111
112

    // Collect some stats.
113
114
    $remaining = 0;
    $total = 0;
115
116
117

    foreach ($this->searchPluginManager->getActiveIndexingPlugins() as $plugin) {
      if ($status = $plugin->indexStatus()) {
118
119
120
121
        $remaining += $status['remaining'];
        $total += $status['total'];
      }
    }
122
    $active_plugins = $this->searchPluginManager->getActivePlugins();
123
124
    $this->moduleHandler->loadAllIncludes('admin.inc');
    $count = format_plural($remaining, 'There is 1 item left to index.', 'There are @count items left to index.');
125
    $percentage = ((int) min(100, 100 * ($total - $remaining) / max(1, $total))) . '%';
126
    $status = '<p><strong>' . $this->t('%percentage of the site has been indexed.', array('%percentage' => $percentage)) . ' ' . $count . '</strong></p>';
127
128
    $form['status'] = array(
      '#type' => 'details',
129
      '#title' => $this->t('Indexing status'),
130
131
132
133
    );
    $form['status']['status'] = array('#markup' => $status);
    $form['status']['wipe'] = array(
      '#type' => 'submit',
134
      '#value' => $this->t('Re-index site'),
135
136
137
138
139
140
141
142
      '#submit' => array(array($this, 'searchAdminReindexSubmit')),
    );

    $items = drupal_map_assoc(array(10, 20, 50, 100, 200, 500));

    // Indexing throttle:
    $form['indexing_throttle'] = array(
      '#type' => 'details',
143
      '#title' => $this->t('Indexing throttle')
144
145
146
    );
    $form['indexing_throttle']['cron_limit'] = array(
      '#type' => 'select',
147
      '#title' => $this->t('Number of items to index per cron run'),
148
      '#default_value' => $this->searchSettings->get('index.cron_limit'),
149
      '#options' => $items,
150
      '#description' => $this->t('The maximum number of items indexed in each pass of a <a href="@cron">cron maintenance task</a>. If necessary, reduce the number of items to prevent timeouts and memory errors while indexing.', array('@cron' => $this->url('system.status')))
151
152
153
154
    );
    // Indexing settings:
    $form['indexing_settings'] = array(
      '#type' => 'details',
155
      '#title' => $this->t('Indexing settings')
156
157
    );
    $form['indexing_settings']['info'] = array(
158
      '#markup' => $this->t('<p><em>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.</em></p><p><em>The default settings should be appropriate for the majority of sites.</em></p>')
159
160
161
    );
    $form['indexing_settings']['minimum_word_size'] = array(
      '#type' => 'number',
162
      '#title' => $this->t('Minimum word length to index'),
163
      '#default_value' => $this->searchSettings->get('index.minimum_word_size'),
164
165
      '#min' => 1,
      '#max' => 1000,
166
      '#description' => $this->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).')
167
168
169
    );
    $form['indexing_settings']['overlap_cjk'] = array(
      '#type' => 'checkbox',
170
      '#title' => $this->t('Simple CJK handling'),
171
      '#default_value' => $this->searchSettings->get('index.overlap_cjk'),
172
      '#description' => $this->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.')
173
174
175
176
    );

    $form['active'] = array(
      '#type' => 'details',
177
      '#title' => $this->t('Active search plugins')
178
    );
179
180
    $options = $this->getOptions();
    $form['active']['active_plugins'] = array(
181
      '#type' => 'checkboxes',
182
      '#title' => $this->t('Active plugins'),
183
      '#title_display' => 'invisible',
184
185
      '#default_value' => $this->searchSettings->get('active_plugins'),
      '#options' => $options,
186
      '#description' => $this->t('Choose which search plugins are active from the available plugins.')
187
    );
188
    $form['active']['default_plugin'] = array(
189
      '#title' => $this->t('Default search plugin'),
190
      '#type' => 'radios',
191
192
      '#default_value' => $this->searchSettings->get('default_plugin'),
      '#options' => $options,
193
      '#description' => $this->t('Choose which search plugin is the default.')
194
195
    );

196
197
198
    // Per plugin settings.
    foreach ($active_plugins as $plugin) {
      $plugin->addToAdminForm($form, $form_state);
199
200
    }
    // Set #submit so we are sure it's invoked even if one of
201
    // the active search plugins added its own #submit.
202
203
204
205
206
207
208
209
210
211
212
213
    $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.
214
    if ($form_state['triggering_element']['#value'] != $this->t('Reset to defaults')) {
215
216
217
      $new_plugins = array_filter($form_state['values']['active_plugins']);
      $default = $form_state['values']['default_plugin'];
      if (!in_array($default, $new_plugins, TRUE)) {
218
        form_set_error('default_plugin', $this->t('Your default search plugin is not selected as an active plugin.'));
219
220
221
222
223
224
225
226
227
228
229
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, array &$form_state) {
    parent::submitForm($form, $form_state);

    // If these settings change, the index needs to be rebuilt.
230
231
232
    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']);
233
      drupal_set_message($this->t('The index will be rebuilt.'));
234
235
      search_reindex();
    }
236
237
238
239
240
241
242
    $this->searchSettings->set('index.cron_limit', $form_state['values']['cron_limit']);
    $this->searchSettings->set('default_plugin', $form_state['values']['default_plugin']);

    // Handle per-plugin submission logic.
    foreach ($this->searchPluginManager->getActivePlugins() as $plugin) {
      $plugin->submitAdminForm($form, $form_state);
    }
243
244

    // Check whether we are resetting the values.
245
    if ($form_state['triggering_element']['#value'] == $this->t('Reset to defaults')) {
246
      $new_plugins = array('node_search', 'user_search');
247
248
    }
    else {
249
      $new_plugins = array_filter($form_state['values']['active_plugins']);
250
    }
251
252
    if ($this->searchSettings->get('active_plugins') != $new_plugins) {
      $this->searchSettings->set('active_plugins', $new_plugins);
253
      drupal_set_message($this->t('The active search plugins have been changed.'));
254
255
      $this->state->set('menu_rebuild_needed', TRUE);
    }
256
    $this->searchSettings->save();
257
258
259
260
261
262
263
264
265
266
  }

  /**
   * 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';
  }
267

268
}