FacetForm.php 9.7 KB
Newer Older
Nick_vh's avatar
Nick_vh committed
1
2
3
4
5
6
7
8
9
<?php

/**
 * @file
 * Contains \Drupal\facetapi\Form\FacetForm.
 */

namespace Drupal\facetapi\Form;

10
use Drupal\Core\Config\Config;
Nick_vh's avatar
Nick_vh committed
11
12
13
14
15
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\facetapi\FacetInterface;
use Drupal\facetapi\FacetApiException;
borisson_'s avatar
borisson_ committed
16
17
use Drupal\facetapi\Widget\WidgetPluginManager;
use Drupal\search_api\Form\SubFormState;
18
use Drupal\search_api\IndexInterface;
Nick_vh's avatar
Nick_vh committed
19
20
21
22
23
24
25
26
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a form for creating and editing search servers.
 */
class FacetForm extends EntityForm {

  /**
27
   * The facet storage controller.
Nick_vh's avatar
Nick_vh committed
28
29
30
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
31
  protected $facetStorage;
Nick_vh's avatar
Nick_vh committed
32

borisson_'s avatar
borisson_ committed
33
34
35
36
37
38
  /**
   * The plugin manager for widgets.
   * @var \Drupal\facetapi\Widget\WidgetPluginManager
   */
  protected $widgetPluginManager;

Nick_vh's avatar
Nick_vh committed
39
  /**
40
   * Constructs a FacetForm object.
Nick_vh's avatar
Nick_vh committed
41
42
43
   *
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
   *   The entity manager.
borisson_'s avatar
borisson_ committed
44
45
   * @param \Drupal\facetapi\Widget\WidgetPluginManager $widget_plugin_manager
   *   Plugin manager for widgets.
Nick_vh's avatar
Nick_vh committed
46
   */
borisson_'s avatar
borisson_ committed
47
  public function __construct(EntityManagerInterface $entity_manager, WidgetPluginManager $widgetPluginManager) {
48
    $this->facetStorage = $entity_manager->getStorage('facetapi_facet');
borisson_'s avatar
borisson_ committed
49
    $this->widgetPluginManager = $widgetPluginManager;
Nick_vh's avatar
Nick_vh committed
50
51
52
53
54
55
56
57
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    /** @var \Drupal\Core\Entity\EntityManagerInterface $entity_manager */
    $entity_manager = $container->get('entity.manager');
borisson_'s avatar
borisson_ committed
58
59
60
61

    /** @var \Drupal\facetapi\Widget\WidgetPluginManager $widget_plugin_manager */
    $widget_plugin_manager = $container->get('plugin.manager.facetapi.widget');
    return new static($entity_manager, $widget_plugin_manager);
Nick_vh's avatar
Nick_vh committed
62
63
64
  }

  /**
65
   * Retrieves the facet storage controller.
Nick_vh's avatar
Nick_vh committed
66
67
   *
   * @return \Drupal\Core\Entity\EntityStorageInterface
68
   *   The facet storage controller.
Nick_vh's avatar
Nick_vh committed
69
   */
70
71
  protected function getFacetStorage() {
    return $this->facetStorage ?: \Drupal::service('entity.manager')->getStorage('facetapi_facet');
Nick_vh's avatar
Nick_vh committed
72
73
  }

borisson_'s avatar
borisson_ committed
74
75
76
77
78
79
80
81
82
83
  /**
   * Returns the widget plugin manager.
   *
   * @return \Drupal\facetapi\Widget\WidgetPluginManager
   *   The widget plugin manager.
   */
  protected function getWidgetPluginManager() {
    return $this->widgetPluginManager?: \Drupal::service('plugin.manager.facetapi.widget');
  }

Nick_vh's avatar
Nick_vh committed
84
85
86
87
88
89
90
91
92
93
94
95
  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    // If the form is being rebuilt, rebuild the entity with the current form
    // values.
    if ($form_state->isRebuilding()) {
      $this->entity = $this->buildEntity($form, $form_state);
    }

    $form = parent::form($form, $form_state);

borisson_'s avatar
borisson_ committed
96
    /** @var \Drupal\facetapi\FacetInterface $facet */
Nick_vh's avatar
Nick_vh committed
97
98
99
100
101
102
103
104
105
106
107
    $facet = $this->getEntity();

    // Set the page title according to whether we are creating or editing the
    // server.
    if ($facet->isNew()) {
      $form['#title'] = $this->t('Add facet');
    }
    else {
      $form['#title'] = $this->t('Edit facet %label', array('%label' => $facet->label()));
    }

108
109
    $search_api_index = $form_state->get('search_api_index');
    $this->buildEntityForm($form, $form_state, $facet, $search_api_index);
Nick_vh's avatar
Nick_vh committed
110
111
112
113
114
115
116
117
118

    return $form;
  }

  /**
   * Builds the form for the basic server properties.
   *
   * @param \Drupal\facetapi\FacetInterface $facet
   *   The server that is being created or edited.
119
120
   * @param \Drupal\search_api\IndexInterface $search_api_index
   *   The search index we're creating a facet for.
Nick_vh's avatar
Nick_vh committed
121
   */
122
  public function buildEntityForm(array &$form, FormStateInterface $form_state, FacetInterface $facet, IndexInterface $search_api_index) {
Nick_vh's avatar
Nick_vh committed
123
124
125
126
127
128
129
130

    $form['name'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Facet name'),
      '#description' => $this->t('Enter the displayed name for the facet.'),
      '#default_value' => $facet->label(),
      '#required' => TRUE,
    );
131

Nick_vh's avatar
Nick_vh committed
132
133
134
135
136
137
    $form['id'] = array(
      '#type' => 'machine_name',
      '#default_value' => $facet->id(),
      '#maxlength' => 50,
      '#required' => TRUE,
      '#machine_name' => array(
138
        'exists' => array($this->getFacetStorage(), 'load'),
Nick_vh's avatar
Nick_vh committed
139
140
141
        'source' => array('name'),
      ),
    );
142
143
144
145
146
147
148
149
150
151

    $form['field_identifier'] = [
      '#type' => 'select',
      '#options' => $this->getIndexedFields($search_api_index),
      '#title' => $this->t('Facet field'),
      '#description' => $this->t('Choose the indexed field.'),
      '#required' => TRUE,
      '#default_value' => $facet->getFieldIdentifier()
    ];

borisson_'s avatar
borisson_ committed
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    $widget_options = [];
    foreach ($this->getWidgetPluginManager()->getDefinitions() as $widget_id => $definition) {
      $widget_options[$widget_id] = !empty($definition['label']) ? $definition['label'] : $widget_id;
    }
    $form['widget'] = [
      '#type' => 'select',
      '#title' => $this->t('Widget'),
      '#description' => $this->t('Select the widget used for displaying this facet.'),
      '#options' => $widget_options,
      '#default_value' => $facet->getWidget(),
      '#required' => TRUE,
      '#ajax' => [
        'trigger_as' => ['name' => 'widgets_configure'],
        'callback' => '::buildAjaxWidgetConfigForm',
        'wrapper' => 'facet-api-widget-config-form',
        'method' => 'replace',
        'effect' => 'fade',
      ],
    ];
    $form['widget_configs'] = array(
      '#type' => 'container',
      '#attributes' => array(
        'id' => 'facet-api-widget-config-form',
      ),
      '#tree' => TRUE,
    );
    $form['widget_configure_button'] = [
      '#type' => 'submit',
      '#name' => 'widget_configure',
      '#value' => $this->t('Configure'),
      '#limit_validation_errors' => [['widget']],
      '#submit' => ['::submitAjaxWidgetConfigForm'],
      '#ajax' => [
        'callback' => '::buildAjaxWidgetConfigForm',
        'wrapper' => 'facet-api-widget-config-form',
      ],
      '#attributes' => ['class' => ['js-hide']],
    ];
    $this->buildWidgetConfigForm($form, $form_state, $facet);

Nick_vh's avatar
Nick_vh committed
192
193
194
195
196
197
198
199
    $form['status'] = array(
      '#type' => 'checkbox',
      '#title' => $this->t('Enabled'),
      '#description' => $this->t('Only enabled facets can be displayed.'),
      '#default_value' => $facet->status(),
    );
  }

200
201
202
  /**
   * Gets all indexed fields for this search index.
   *
borisson_'s avatar
borisson_ committed
203
   * @param \Drupal\search_api\IndexInterface $search_api_index
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
   *   The search index we're creating a facet for.
   * @return array
   *   An array of all indexed fields.
   */
  protected function getIndexedFields(IndexInterface $search_api_index) {
    $indexed_fields = [];

    foreach ($search_api_index->getDatasources() as $datasource_id => $datasource) {
      $fields = $search_api_index->getFieldsByDatasource($datasource_id);
      foreach ($fields as $field) {
        $indexed_fields[$field->getFieldIdentifier()] = $field->getLabel();
      }
    }
    return $indexed_fields;
  }

borisson_'s avatar
borisson_ committed
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  /**
   * Handles changes to the selected widgets.
   */
  public function buildAjaxWidgetConfigForm(array $form, FormStateInterface $form_state) {
    return $form['widget_configs'];
  }

  /**
   * Builds the configuration forms for all selected widgets.
   *
   * @param \Drupal\search_api\IndexInterface $index
   *   The index begin created or edited.
   */
  public function buildWidgetConfigForm(array &$form, FormStateInterface $form_state, FacetInterface $facet) {
    $widget = $facet->getWidget();

    if (!is_null($widget)) {
      $widget_instance = $this->getWidgetPluginManager()->createInstance($widget);
      // @todo Create, use and save SubFormState already here, not only in
      //   validate(). Also, use proper subset of $form for first parameter?
240
241
242
243
244
      $config = $this->config('facetapi.facet.' . $facet->id());
      if ($config_form = $widget_instance->buildConfigurationForm([], $form_state, ($config instanceof Config) ? $config : null )) {
        $form['widget_configs']['#type'] = 'details';
        $form['widget_configs']['#title'] = $this->t('Configure the %widget widget', ['%widget' => $this->getWidgetPluginManager()->getDefinition($widget)['label']]);
        $form['widget_configs']['#open'] = $facet->isNew();
borisson_'s avatar
borisson_ committed
245

246
        $form['widget_configs'] += $config_form;
borisson_'s avatar
borisson_ committed
247
248
249
250
251
252
253
254
255
256
257
258
259
      }
    }
  }

  /**
   * Form submission handler for buildEntityForm().
   *
   * Takes care of changes in the selected datasources.
   */
  public function submitAjaxWidgetConfigForm($form, FormStateInterface $form_state) {
    $form_state->setRebuild();
  }

Nick_vh's avatar
Nick_vh committed
260
261
262
263
264
265
266
267
268
269
270
271
272
  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    parent::validateForm($form, $form_state);
  }

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

273
    /** @var \Drupal\facetapi\FacetInterface $facet */
Nick_vh's avatar
Nick_vh committed
274
275
276
277
278
279
280
281
282
    $facet = $this->getEntity();

    return $facet;
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
283
    // Only save the facet if the form doesn't need to be rebuilt.
Nick_vh's avatar
Nick_vh committed
284
285
286
287
288
    if (!$form_state->isRebuilding()) {
      try {
        $facet = $this->getEntity();
        $facet->save();
        drupal_set_message($this->t('The facet was successfully saved.'));
289
        $form_state->setRedirect('entity.search_api_index.facets', array('search_api_index' => $facet->getSearchApiIndex()));
Nick_vh's avatar
Nick_vh committed
290
291
292
293
294
295
296
297
298
299
300
301
302
      }
      catch (FacetApiException $e) {
        $form_state->setRebuild();
        watchdog_exception('facetapi', $e);
        drupal_set_message($this->t('The facet could not be saved.'), 'error');
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function delete(array $form, FormStateInterface $form_state) {
Nick_vh's avatar
Nick_vh committed
303
    $form_state->setRedirect('entity.facetapi_facet.delete_form', array('facetapi_facet' => $this->getEntity()->id()));
Nick_vh's avatar
Nick_vh committed
304
305
306
  }

}