diff --git a/search_api.routing.yml b/search_api.routing.yml
index 34c34480..4c8c4e35 100644
--- a/search_api.routing.yml
+++ b/search_api.routing.yml
@@ -124,7 +124,19 @@ entity.search_api_index.fields:
_entity_access: 'search_api_index.fields'
entity.search_api_index.add_fields:
- path: '/admin/config/search/search-api/index/{search_api_index}/fields/add'
+ path: '/admin/config/search/search-api/index/{search_api_index}/fields/add/nojs'
+ options:
+ parameters:
+ search_api_index:
+ tempstore: TRUE
+ type: 'entity:search_api_index'
+ defaults:
+ _entity_form: 'search_api_index.add_fields'
+ requirements:
+ _entity_access: 'search_api_index.fields'
+
+entity.search_api_index.add_fields_ajax:
+ path: '/admin/config/search/search-api/index/{search_api_index}/fields/add/ajax'
options:
parameters:
search_api_index:
@@ -136,7 +148,7 @@ entity.search_api_index.add_fields:
_entity_access: 'search_api_index.fields'
entity.search_api_index.field_config:
- path: '/admin/config/search/search-api/index/{search_api_index}/fields/{field_id}/edit'
+ path: '/admin/config/search/search-api/index/{search_api_index}/fields/edit/{field_id}'
options:
parameters:
search_api_index:
@@ -149,7 +161,7 @@ entity.search_api_index.field_config:
_entity_access: 'search_api_index.fields'
entity.search_api_index.remove_field:
- path: '/admin/config/search/search-api/index/{search_api_index}/fields/{field_id}/remove'
+ path: '/admin/config/search/search-api/index/{search_api_index}/fields/remove/{field_id}'
options:
parameters:
search_api_index:
diff --git a/search_api.theme.inc b/search_api.theme.inc
index ebb0bd7e..71c85585 100644
--- a/search_api.theme.inc
+++ b/search_api.theme.inc
@@ -35,15 +35,14 @@ function theme_search_api_admin_fields_table($variables) {
$row[] = $cell;
}
}
- if (empty($form['fields'][$name]['description']['#value'])) {
- $rows[] = Utility::deepCopy($row);
- }
- else {
- $rows[] = array(
- 'data' => $row,
- 'title' => strip_tags($form['fields'][$name]['description']['#value']),
- );
+ $row = array(
+ 'data' => $row,
+ 'data-field-row-id' => $name,
+ );
+ if (!empty($form['fields'][$name]['description']['#value'])) {
+ $row['title'] = strip_tags($form['fields'][$name]['description']['#value']);
}
+ $rows[] = $row;
}
}
@@ -160,6 +159,9 @@ function theme_search_api_form_item_list(array $variables) {
$build = array(
'#theme' => 'item_list',
);
+ if (!empty($element['#title'])) {
+ $build['#title'] = $element['#title'];
+ }
foreach (Element::children($element) as $key) {
$build['#items'][$key] = $element[$key];
}
diff --git a/src/Controller/IndexController.php b/src/Controller/IndexController.php
index 07bdebdc..a1d9c487 100644
--- a/src/Controller/IndexController.php
+++ b/src/Controller/IndexController.php
@@ -3,9 +3,14 @@
namespace Drupal\search_api\Controller;
use Drupal\Component\Render\FormattableMarkup;
+use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Ajax\RemoveCommand;
use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
use Drupal\search_api\IndexInterface;
use Drupal\search_api\SearchApiException;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
@@ -14,6 +19,57 @@
class IndexController extends ControllerBase {
/**
+ * The request stack.
+ *
+ * @var \Symfony\Component\HttpFoundation\RequestStack|null
+ */
+ protected $requestStack;
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ /** @var static $controller */
+ $controller = parent::create($container);
+
+ $controller->setRequestStack($container->get('request_stack'));
+
+ return $controller;
+ }
+
+ /**
+ * Retrieves the request stack.
+ *
+ * @return \Symfony\Component\HttpFoundation\RequestStack
+ * The request stack.
+ */
+ public function getRequestStack() {
+ return $this->requestStack ?: \Drupal::service('request_stack');
+ }
+
+ /**
+ * Retrieves the current request.
+ *
+ * @return \Symfony\Component\HttpFoundation\Request|null
+ */
+ public function getRequest() {
+ return $this->getRequestStack()->getCurrentRequest();
+ }
+
+ /**
+ * Sets the request stack.
+ *
+ * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
+ * The new request stack.
+ *
+ * @return $this
+ */
+ public function setRequestStack(RequestStack $request_stack) {
+ $this->requestStack = $request_stack;
+ return $this;
+ }
+
+ /**
* Displays information about a search index.
*
* @param \Drupal\search_api\IndexInterface $search_api_index
@@ -96,10 +152,12 @@ public function indexBypassEnable(IndexInterface $search_api_index) {
*/
public function removeField(IndexInterface $search_api_index, $field_id) {
$fields = $search_api_index->getFields();
+ $success = FALSE;
if (isset($fields[$field_id])) {
try {
$search_api_index->removeField($field_id);
$search_api_index->save();
+ $success = TRUE;
}
catch (SearchApiException $e) {
$args['%field'] = $fields[$field_id]->getLabel();
@@ -110,7 +168,13 @@ public function removeField(IndexInterface $search_api_index, $field_id) {
throw new NotFoundHttpException();
}
- // Redirect to the index's "View" page.
+ // If this is an AJAX request, just remove the row in question.
+ if ($success && $this->getRequest()->request->get(AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER)) {
+ $response = new AjaxResponse();
+ $response->addCommand(new RemoveCommand("tr[data-field-row-id='$field_id']"));
+ return $response;
+ }
+ // Redirect to the index's "Fields" page.
$url = $search_api_index->toUrl('fields');
return $this->redirect($url->getRouteName(), $url->getRouteParameters());
}
diff --git a/src/Entity/Index.php b/src/Entity/Index.php
index bbe53e78..69fe5192 100644
--- a/src/Entity/Index.php
+++ b/src/Entity/Index.php
@@ -78,7 +78,8 @@
* "add-form" = "/admin/config/search/search-api/add-index",
* "edit-form" = "/admin/config/search/search-api/index/{search_api_index}/edit",
* "fields" = "/admin/config/search/search-api/index/{search_api_index}/fields",
- * "add-fields" = "/admin/config/search/search-api/index/{search_api_index}/fields/add",
+ * "add-fields" = "/admin/config/search/search-api/index/{search_api_index}/fields/add/nojs",
+ * "add-fields-ajax" = "/admin/config/search/search-api/index/{search_api_index}/fields/add/ajax",
* "break-lock-form" = "/admin/config/search/search-api/index/{search_api_index}/fields/break-lock",
* "processors" = "/admin/config/search/search-api/index/{search_api_index}/processors",
* "delete-form" = "/admin/config/search/search-api/index/{search_api_index}/delete",
diff --git a/src/Form/FieldConfigurationForm.php b/src/Form/FieldConfigurationForm.php
index c81912f5..ccb12f41 100644
--- a/src/Form/FieldConfigurationForm.php
+++ b/src/Form/FieldConfigurationForm.php
@@ -2,9 +2,12 @@
namespace Drupal\search_api\Form;
+use Drupal\Component\Render\FormattableMarkup;
+use Drupal\Component\Utility\Html;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\search_api\Processor\ConfigurablePropertyInterface;
@@ -33,6 +36,13 @@ class FieldConfigurationForm extends EntityForm {
protected $field;
/**
+ * The "id" attribute of the generated form.
+ *
+ * @var string
+ */
+ protected $formIdAttribute;
+
+ /**
* {@inheritdoc}
*/
public function getFormId() {
@@ -76,9 +86,6 @@ public static function create(ContainerInterface $container) {
public function buildForm(array $form, FormStateInterface $form_state) {
$field = $this->getField();
- $args['%field'] = $field->getLabel();
- $form['#title'] = $this->t('Edit field %field', $args);
-
if (!$field) {
$args['@id'] = $this->getRequest()->attributes->get('field_id');
$form['message'] = array(
@@ -87,6 +94,21 @@ public function buildForm(array $form, FormStateInterface $form_state) {
return $form;
}
+ $args['%field'] = $field->getLabel();
+ $form['#title'] = $this->t('Edit field %field', $args);
+
+ if ($this->getRequest()->query->get('modal_redirect')) {
+ $form['title']['#markup'] = new FormattableMarkup('
@title
', ['@title' => $form['#title']]);
+ Html::setIsAjax(TRUE);
+ }
+
+ $this->formIdAttribute = Html::getUniqueId($this->getFormId());
+ $form['#id'] = $this->formIdAttribute;
+
+ $form['messages'] = [
+ '#type' => 'status_messages',
+ ];
+
$property = $field->getDataDefinition();
if (!($property instanceof ConfigurablePropertyInterface)) {
$args['%field'] = $field->getLabel();
@@ -123,11 +145,16 @@ protected function actions(array $form, FormStateInterface $form_state) {
$actions = parent::actions($form, $form_state);
unset($actions['delete']);
- $actions['cancel'] = array(
- '#type' => 'link',
- '#title' => $this->t('Cancel'),
- '#url' => $this->entity->toUrl('fields'),
- );
+ if ($this->getRequest()->query->get('modal_redirect')) {
+ $actions['submit']['#ajax']['wrapper'] = $this->formIdAttribute;
+ }
+ else {
+ $actions['cancel'] = array(
+ '#type' => 'link',
+ '#title' => $this->t('Cancel'),
+ '#url' => $this->entity->toUrl('fields'),
+ );
+ }
return $actions;
}
@@ -152,7 +179,16 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
$property->submitConfigurationForm($field, $form, $form_state);
drupal_set_message($this->t('The field configuration was successfully saved.'));
- $form_state->setRedirectUrl($this->entity->toUrl('fields'));
+ if ($this->getRequest()->query->get('modal_redirect')) {
+ $url = $this->entity->toUrl('add-fields-ajax')
+ ->setOption('query', [
+ MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax',
+ ]);
+ $form_state->setRedirectUrl($url);
+ }
+ else {
+ $form_state->setRedirectUrl($this->entity->toUrl('fields'));
+ }
}
/**
diff --git a/src/Form/IndexAddFieldsForm.php b/src/Form/IndexAddFieldsForm.php
index 9d76f8bf..c4d5256d 100644
--- a/src/Form/IndexAddFieldsForm.php
+++ b/src/Form/IndexAddFieldsForm.php
@@ -2,19 +2,19 @@
namespace Drupal\search_api\Form;
-use Drupal\Component\Render\PlainTextOutput;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\Html;
use Drupal\Core\Datetime\DateFormatterInterface;
-use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface;
+use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
use Drupal\Core\TypedData\DataReferenceDefinitionInterface;
use Drupal\Core\Url;
+use Drupal\search_api\Datasource\DatasourceInterface;
use Drupal\search_api\Processor\ConfigurablePropertyInterface;
use Drupal\search_api\Processor\ProcessorPropertyInterface;
use Drupal\search_api\Utility\FieldsHelperInterface;
@@ -60,6 +60,13 @@ class IndexAddFieldsForm extends EntityForm {
protected $unmappedFields = array();
/**
+ * The "id" attribute of the generated form.
+ *
+ * @var string
+ */
+ protected $formIdAttribute;
+
+ /**
* {@inheritdoc}
*/
public function getFormId() {
@@ -136,43 +143,26 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$this->checkEntityEditable($form, $index);
- // Set title. Strip html to accommodate modal title.
$args['%index'] = $index->label();
- $form['#title'] = PlainTextOutput::renderFromHtml($this->t('Add fields to index %index', $args));
+ $form['#title'] = $this->t('Add fields to index %index', $args);
- // Main container.
- $form['index-fields'] = [
- '#type' => 'container',
- '#attributes' => ['id' => 'index-fields'],
+ $this->formIdAttribute = Html::getUniqueId($this->getFormId());
+ $form['#id'] = $this->formIdAttribute;
+
+ $form['messages'] = [
+ '#type' => 'status_messages',
];
- // We store the datasources we need to show in the form to accommodate the
- // AJAX magic.
- // Create hidden form field to store datasources.
- $form['datasources'] = array(
- '#type' => 'hidden',
+ $datasources = array(
+ '' => NULL,
);
-
- $datasources = $form_state->getValue('datasources');
- // First set some defaults when nothing is set.
- if (empty($datasources)) {
- // Get the datasources to add.
- // Start with the general fields.
- $datasources = ['general' => NULL];
- // Add entity datasource.
- $entity_datasources = $this->entity->getDatasources();
- // For each datasource add id to form value.
- foreach ($entity_datasources as $entity_datasource) {
- $datasource_id = $entity_datasource->getPluginId();
- $datasources[$datasource_id] = NULL;
+ $datasources += $this->entity->getDatasources();
+ foreach ($datasources as $datasource_id => $datasource) {
+ $item = $this->getDatasourceListItem($datasource);
+ if ($item) {
+ $form['datasources']['datasource_' . $datasource_id] = $item;
}
}
- $form['datasources']['#value'] = $datasources;
-
- // Create form elements for each of the datasources we want to show.
- // This is a recursive function, allowing to show the nested elements.
- $containers = $this->createFieldContainers($form['datasources']['#value']);
- $form['index-fields']['properties'] = $containers;
$form['actions'] = $this->actionsElement($form, $form_state);
@@ -203,95 +193,35 @@ public function buildForm(array $form, FormStateInterface $form_state) {
}
/**
- * Creates form elements for each field.
+ * Creates a list item for one datasource.
*
- * @param array $fields
- * A nested array which defines what fields to show. This info is
- * stored in the form.
+ * @param \Drupal\search_api\Datasource\DatasourceInterface|null $datasource
+ * The datasource, or NULL for general properties.
*
* @return array
- * Form elements for the given fields..
+ * A render array representing the given datasource and, possibly, its
+ * attached properties.
*/
- protected function createFieldContainers(array $fields) {
- $items = array();
- $url = $this->entity->toUrl('add-fields');
-
- foreach (array_keys($fields) as $datasource_id) {
- // Each element get' a container so we can add children for sub elements.
- $item = [
- '#type' => 'container',
- '#attributes' => [
- 'class' => ['container-inline'],
- '#attributes' => ['id' => '' . $datasource_id],
- ],
- '#field-name' => $datasource_id,
- ];
-
- $item['test'] = [
- '#markup' => 'Show ' . $datasource_id . ' in ' . 'index-field-' . $datasource_id . ' container',
- ];
-
- $active = FALSE;
+ protected function getDatasourceListItem(DatasourceInterface $datasource = NULL) {
+ $datasource_id = $datasource ? $datasource->getPluginId() : NULL;
+ $datasource_id_param = $datasource_id ?: '';
+ $properties = $this->entity->getPropertyDefinitions($datasource_id);
+ if ($properties) {
+ $active_property_path = '';
$active_datasource = $this->getParameter('datasource');
- if (isset($active_datasource)) {
- $active = $active_datasource == $datasource_id;
+ if ($active_datasource !== NULL && $active_datasource == $datasource_id_param) {
+ $active_property_path = $this->getParameter('property_path', '');
}
- $properties = $this->entity->getPropertyDefinitions($datasource_id == 'general' ? NULL : $datasource_id);
- if ($properties) {
- $active_property_path = NULL;
- if ($active) {
- $active_property_path = $this->getParameter('property_path', '');
- }
- $base_url = clone $url;
- $base_url->setOption('query', array('datasource' => $datasource_id));
- $item['properties'] = $this->getPropertiesList($properties, $active_property_path, $base_url);
- }
- $items[] = $item;
+ $base_url = $this->entity->toUrl('add-fields');
+ $base_url->setOption('query', array('datasource' => $datasource_id_param));
- // Add child elements.
- if (is_array($fields[$datasource_id])) {
- $new_things = $this->createFieldContainers($fields[$datasource_id]);
- foreach ($new_things as $new_thing) {
- $items[] = $new_thing;
- }
- }
+ $item = $this->getPropertiesList($properties, $active_property_path, $base_url, $datasource_id);
+ $item['#title'] = $datasource ? $datasource->label() : $this->t('General');
+ return $item;
}
- return $items;
- }
-
- /**
- * Handles form submissions for expanding a datasource.
- */
- public function expandDatasourceFormSubmit(&$form, FormStateInterface &$form_state) {
- // Find the triggering field.
- $button = $form_state->getTriggeringElement();
- // Go one level up in the form, to the widgets container.
- $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
- $field_name = $element['#field-name'];
-
- // Add new items to form state.
- $datasources = $form_state->getValue('datasources');
-
- $properties = $this->entity->getPropertyDefinitions($field_name == 'general' ? NULL : $field_name);
-
- foreach (array_keys($properties) as $property) {
- $datasources[$field_name][$property] = NULL;
- }
-
- $form_state->setValue('datasources', $datasources);
- $form_state->setRebuild();
- }
-
- /**
- * Returns new datasource structure.
- */
- public function expandDatasourceFormAjax(array $form, FormStateInterface &$form_state) {
- $form['messages']['status'] = [
- '#type' => 'status_messages',
- ];
- return $form;
+ return NULL;
}
/**
@@ -304,6 +234,9 @@ public function expandDatasourceFormAjax(array $form, FormStateInterface &$form_
* @param \Drupal\Core\Url $base_url
* The base URL to which property path parameters should be added for
* the navigation links.
+ * @param string|null $datasource_id
+ * The datasource ID of the listed properties, or NULL for
+ * datasource-independent properties.
* @param string $parent_path
* (optional) The common property path prefix of the given properties.
* @param string $label_prefix
@@ -313,7 +246,7 @@ public function expandDatasourceFormAjax(array $form, FormStateInterface &$form_
* A render array representing the given properties and, possibly, nested
* properties.
*/
- protected function getPropertiesList(array $properties, $active_property_path, Url $base_url, $parent_path = '', $label_prefix = '') {
+ protected function getPropertiesList(array $properties, $active_property_path, Url $base_url, $datasource_id, $parent_path = '', $label_prefix = '') {
$list = array(
'#theme' => 'search_api_form_item_list',
);
@@ -386,65 +319,59 @@ protected function getPropertiesList(array $properties, $active_property_path, U
continue;
}
- $nested_list = FALSE;
- $expand_link = FALSE;
+ $item = array(
+ '#type' => 'container',
+ '#attributes' => array(
+ 'class' => array('container-inline'),
+ ),
+ );
+
+ $nested_list = array();
if ($nested_properties) {
if ($key == $active_item) {
$link_url = clone $base_url;
$query_base['property_path'] = $parent_path;
$link_url->setOption('query', $query_base);
- $expand_link = array(
+ $item['expand_link'] = array(
'#type' => 'link',
'#title' => '(-) ',
'#url' => $link_url,
- '#attributes' => [
- 'class' => [
- 'use-ajax',
- ],
- ],
+ '#ajax' => array(
+ 'wrapper' => $this->formIdAttribute,
+ ),
);
- $nested_list = $this->getPropertiesList($nested_properties, $active_property_path, $base_url, $this_path, $label_prefix . $label . ' » ');
+ $nested_list = $this->getPropertiesList($nested_properties, $active_property_path, $base_url, $datasource_id, $this_path, $label_prefix . $label . ' » ');
}
else {
$link_url = clone $base_url;
$query_base['property_path'] = $this_path;
$link_url->setOption('query', $query_base);
- $expand_link = array(
+ $item['expand_link'] = array(
'#type' => 'link',
'#title' => '(+) ',
'#url' => $link_url,
- '#attributes' => [
- 'class' => [
- 'use-ajax',
- ],
- ],
+ '#ajax' => array(
+ 'wrapper' => $this->formIdAttribute,
+ ),
);
}
}
- $item = array(
- '#type' => 'container',
- '#attributes' => array(
- 'class' => array('container-inline'),
- ),
- );
-
- if ($expand_link) {
- $item['expand_link'] = $expand_link;
- }
-
$item['label']['#markup'] = Html::escape($label) . ' ';
if ($can_be_indexed) {
$item['add'] = array(
'#type' => 'submit',
- '#name' => Utility::createCombinedId($this->getParameter('datasource') ?: NULL, $this_path),
+ '#name' => Utility::createCombinedId($datasource_id, $this_path),
'#value' => $this->t('Add'),
'#submit' => array('::addField', '::save'),
'#property' => $property,
'#prefixed_label' => $label_prefix . $label,
'#data_type' => $type_mapping[$type],
+ '#ajax' => array(
+ 'wrapper' => $this->formIdAttribute,
+ ),
);
}
@@ -452,13 +379,29 @@ protected function getPropertiesList(array $properties, $active_property_path, U
$item['properties'] = $nested_list;
}
- $list[] = $item;
+ $list[$key] = $item;
}
return $list;
}
/**
+ * {@inheritdoc}
+ */
+ protected function actions(array $form, FormStateInterface $form_state) {
+ return array(
+ 'done' => array(
+ '#type' => 'link',
+ '#title' => $this->t('Done'),
+ '#url' => $this->entity->toUrl('fields'),
+ '#attributes' => array(
+ 'class' => array('button'),
+ ),
+ ),
+ );
+ }
+
+ /**
* Form submission handler for adding a new field to the index.
*
* @param array $form
@@ -485,7 +428,15 @@ public function addField(array $form, FormStateInterface $form_state) {
'search_api_index' => $this->entity->id(),
'field_id' => $field->getFieldIdentifier(),
);
- $form_state->setRedirect('entity.search_api_index.field_config', $parameters);
+ $options = array();
+ $route = $this->getRequest()->attributes->get('_route');
+ if ($route === 'entity.search_api_index.add_fields_ajax') {
+ $options['query'] = [
+ MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax',
+ 'modal_redirect' => 1,
+ ];
+ }
+ $form_state->setRedirect('entity.search_api_index.field_config', $parameters, $options);
}
$args['%label'] = $field->getLabel();
diff --git a/src/Form/IndexFieldsForm.php b/src/Form/IndexFieldsForm.php
index 58e85455..26910b29 100644
--- a/src/Form/IndexFieldsForm.php
+++ b/src/Form/IndexFieldsForm.php
@@ -12,6 +12,7 @@
use Drupal\Core\Url;
use Drupal\search_api\DataType\DataTypePluginManager;
use Drupal\search_api\Processor\ConfigurablePropertyInterface;
+use Drupal\search_api\SearchApiException;
use Drupal\search_api\UnsavedConfigurationInterface;
use Drupal\search_api\Utility\Utility;
use Drupal\user\SharedTempStoreFactory;
@@ -108,6 +109,8 @@ public function getDataTypePluginManager() {
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
+ $form['#attached']['library'][] = 'core/drupal.dialog.ajax';
+
$index = $this->entity;
// Do not allow the form to be cached. See
@@ -123,7 +126,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$form['add-field'] = [
'#type' => 'link',
'#title' => $this->t('Add fields'),
- '#url' => Url::fromRoute('entity.search_api_index.add_fields', ['search_api_index' => $index->id()]),
+ '#url' => $this->entity->toUrl('add-fields'),
'#attributes' => [
'class' => [
'use-ajax',
@@ -205,11 +208,17 @@ protected function buildFieldsTable(array $fields) {
}
}
- $fulltext_types = array('text');
+ $fulltext_types = array(
+ array(
+ 'value' => 'text',
+ ),
+ );
// Add all data types with fallback "text" to fulltext types as well.
- foreach ($data_type_plugin_manager->getInstances() as $id => $type) {
+ foreach ($data_type_plugin_manager->getInstances() as $type_id => $type) {
if ($type->getFallbackType() == 'text') {
- $fulltext_types[] = $id;
+ $fulltext_types[] = array(
+ 'value' => $type_id,
+ );
}
}
@@ -277,7 +286,6 @@ protected function buildFieldsTable(array $fields) {
);
}
- $css_key = '#edit-fields-' . Html::getId($key);
$build['fields'][$key]['type'] = array(
'#type' => 'select',
'#options' => $types,
@@ -291,10 +299,12 @@ protected function buildFieldsTable(array $fields) {
'#type' => 'select',
'#options' => $boosts,
'#default_value' => sprintf('%.1f', $field->getBoost()),
+ '#states' => array(
+ 'visible' => array(
+ ':input[name="fields[' . $key . '][type]"]' => $fulltext_types,
+ ),
+ ),
);
- foreach ($fulltext_types as $type) {
- $build['fields'][$key]['boost']['#states']['visible'][$css_key . '-type'][] = array('value' => $type);
- }
$route_parameters = array(
'search_api_index' => $this->entity->id(),
@@ -304,12 +314,26 @@ protected function buildFieldsTable(array $fields) {
// don't break the table structure. (theme_search_api_admin_fields_table()
// does not add empty cells.)
$build['fields'][$key]['edit']['#markup'] = '';
- if ($field->getDataDefinition() instanceof ConfigurablePropertyInterface) {
- $build['fields'][$key]['edit'] = array(
- '#type' => 'link',
- '#title' => $this->t('Edit'),
- '#url' => Url::fromRoute('entity.search_api_index.field_config', $route_parameters),
- );
+ try {
+ if ($field->getDataDefinition() instanceof ConfigurablePropertyInterface) {
+ $build['fields'][$key]['edit'] = array(
+ '#type' => 'link',
+ '#title' => $this->t('Edit'),
+ '#url' => Url::fromRoute('entity.search_api_index.field_config', $route_parameters),
+ '#attributes' => [
+ 'class' => [
+ 'use-ajax',
+ ],
+ 'data-dialog-type' => 'modal',
+ 'data-dialog-options' => Json::encode([
+ 'width' => 700,
+ ]),
+ ],
+ );
+ }
+ }
+ catch (SearchApiException $e) {
+ // Could not retrieve data definition: ignore.
}
$build['fields'][$key]['remove']['#markup'] = '';
if (!$field->isIndexedLocked()) {
@@ -317,6 +341,9 @@ protected function buildFieldsTable(array $fields) {
'#type' => 'link',
'#title' => $this->t('Remove'),
'#url' => Url::fromRoute('entity.search_api_index.remove_field', $route_parameters),
+ '#attributes' => array(
+ 'class' => array('use-ajax'),
+ ),
);
}
}
diff --git a/tests/src/Functional/IntegrationTest.php b/tests/src/Functional/IntegrationTest.php
index 3bfbd64f..32cb1507 100644
--- a/tests/src/Functional/IntegrationTest.php
+++ b/tests/src/Functional/IntegrationTest.php
@@ -1035,7 +1035,7 @@ protected function checkUnsavedChanges() {
$this->assertSession()->responseContains($message_parts[0]);
$this->assertSession()->responseContains($message_parts[1]);
$this->assertFalse($this->xpath('//input[not(@disabled)]'));
- $this->drupalGet($this->getIndexPath('fields/rendered_item/edit'));
+ $this->drupalGet($this->getIndexPath('fields/edit/rendered_item'));
$this->assertSession()->responseContains($message_parts[0]);
$this->assertSession()->responseContains($message_parts[1]);
$this->assertFalse($this->xpath('//input[not(@disabled)]'));
diff --git a/tests/src/Functional/ProcessorIntegrationTest.php b/tests/src/Functional/ProcessorIntegrationTest.php
index a8cdb021..1208b73e 100644
--- a/tests/src/Functional/ProcessorIntegrationTest.php
+++ b/tests/src/Functional/ProcessorIntegrationTest.php
@@ -307,7 +307,7 @@ public function checkAggregatedFieldsIntegration() {
$this->submitForm([], 'aggregated_field');
$args['%label'] = 'Aggregated field';
$this->assertSession()->responseContains(new FormattableMarkup('Field %label was added to the index.', $args));
- $this->assertSession()->addressEquals($this->getIndexPath('fields/aggregated_field/edit'));
+ $this->assertSession()->addressEquals($this->getIndexPath('fields/edit/aggregated_field'));
$edit = [
'type' => 'first',
'fields[entity:node/title]' => 'title',
@@ -500,7 +500,7 @@ public function checkRenderedItemIntegration() {
$this->submitForm([], 'rendered_item');
$args['%label'] = 'Rendered HTML output';
$this->assertSession()->responseContains(new FormattableMarkup('Field %label was added to the index.', $args));
- $this->assertSession()->addressEquals($this->getIndexPath('fields/rendered_item/edit'));
+ $this->assertSession()->addressEquals($this->getIndexPath('fields/edit/rendered_item'));
$edit = [
'roles[]' => ['authenticated'],
'view_mode[entity:node][article]' => 'default',