diff --git a/search_api.links.action.yml b/search_api.links.action.yml index 7d85b50..5b99f87 100644 --- a/search_api.links.action.yml +++ b/search_api.links.action.yml @@ -13,8 +13,3 @@ search_api.execute_tasks: title: 'Execute pending tasks' appears_on: - search_api.overview -entity.search_api_index.add_fields: - route_name: entity.search_api_index.add_fields - title: 'Add fields' - appears_on: - - entity.search_api_index.fields diff --git a/src/Form/IndexAddFieldsForm.php b/src/Form/IndexAddFieldsForm.php index 724409f..b534aac 100644 --- a/src/Form/IndexAddFieldsForm.php +++ b/src/Form/IndexAddFieldsForm.php @@ -2,9 +2,12 @@ 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\Datetime\DateFormatter; use Drupal\Core\Entity\EntityForm; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface; @@ -59,6 +62,15 @@ class IndexAddFieldsForm extends EntityForm { protected $unmappedFields = array(); /** + * REMOVE. + * + * Counter keeping track of the sequence of method invocation. + * + * @var int + */ + protected static $sequenceCounter = 0; + + /** * {@inheritdoc} */ public function getFormId() { @@ -92,6 +104,8 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager, Fie $this->renderer = $renderer; $this->dateFormatter = $date_formatter; $this->parameters = $parameters; + // REMOVE. + $this->displayMethodInvocation('__construct'); } /** @@ -128,6 +142,9 @@ public function getParameter($name, $default = NULL) { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { + + $this->displayMethodInvocation('buildForm'); + $index = $this->entity; // Do not allow the form to be cached. See @@ -136,19 +153,60 @@ public function buildForm(array $form, FormStateInterface $form_state) { $this->checkEntityEditable($form, $index); + // Set title. Strip html to accomodate modal title. $args['%index'] = $index->label(); - $form['#title'] = $this->t('Add fields to index %index', $args); + $form['#title'] = PlainTextOutput::renderFromHtml($this->t('Add fields to index %index', $args)); - $form['properties'] = array( - '#theme' => 'search_api_form_item_list', - ); - $datasources = array( - '' => NULL, + // Main container. + $form['index-fields'] = [ + '#type' => 'container', + '#attributes' => ['id' => 'index-fields'], + ]; + + // TEST. + $form['index-fields']['messages'] = [ + '#type' => 'container', + '#attributes' => ['id' => 'message-wrapper'], + ]; + + // We store the datasources we need to show in the form + // to accomodate the ajax magic. + // Create hidden form field to store datasources. + $form['datasources'] = array( + '#type' => 'hidden', ); - $datasources += $this->entity->getDatasources(); - foreach ($datasources as $datasource) { - $form['properties'][] = $this->getDatasourceListItem($datasource); + + // First set some defaults when nothing is set. + $form_state_datasources = $form_state->getValue('datasources'); + + dsm('form state at start of build form'); + dsm($form_state_datasources); + + if (empty($form_state_datasources)) { + dsm('leeg dus invullen'); + // 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; + } + $form['datasources']['#value'] = $datasources; + } + else { + dsm('niet leeg'); + $form['datasources']['#value'] = $form_state_datasources; } + dsm('deze datasources moeten we weergeven'); + dsm($form['datasources']['#value']); + + // Create form elementes 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); @@ -179,62 +237,197 @@ public function buildForm(array $form, FormStateInterface $form_state) { } /** - * Creates a list item for one datasource. + * Create form elements for each field. * - * @param \Drupal\search_api\Datasource\DatasourceInterface|null $datasource - * The datasource, or NULL for general properties. + * @param array $fields + * A nested array which defines what fields to show. This info is + * stored in the form. * * @return array - * A render array representing the given datasource and, possibly, its - * attached properties. + * Return form elements. */ - protected function getDatasourceListItem(DatasourceInterface $datasource = NULL) { - $item = array( - '#type' => 'container', - '#attributes' => array( - 'class' => array('container-inline'), - ), - ); + protected function createFieldContainers(array $fields) { + foreach (array_keys($fields) as $datasource_id) { - $active = FALSE; - $datasource_id = $datasource ? $datasource->getPluginId() : ''; - $active_datasource = $this->getParameter('datasource'); - if (isset($active_datasource)) { - $active = $active_datasource == $datasource_id; - } + // Each element get's a container so we can add children for subelements. + $item = array( + '#type' => 'container', + '#attributes' => array( + 'class' => array('container-inline'), + '#attributes' => ['id' => '' . $datasource_id], + ), + '#field-name' => $datasource_id, + ); - $url = $this->entity->toUrl('add-fields'); - if ($active) { - $expand_link = array( - '#type' => 'link', - '#title' => '(-) ', - '#url' => $url, + $item['test'] = array( + '#markup' => 'Show ' . $datasource_id . ' in ' . 'index-field-' . $datasource_id . ' container', ); + + $active = FALSE; + + $active_datasource = $this->getParameter('datasource'); + if (isset($active_datasource)) { + $active = $active_datasource == $datasource_id; + } + + $url = $this->entity->toUrl('add-fields'); + if ($active) { + $expand_link = array( + '#type' => 'link', + '#title' => '(-) ', + '#url' => $url, + ); + } + else { + $url->setOption('query', array('datasource' => $datasource_id)); + $expand_link = array( + '#type' => 'link', + '#title' => '(+) ', + '#url' => $url, + ); + $expand_button = array( + '#type' => 'submit', + '#name' => 'expand_datasource_' . $datasource_id, + '#value' => '(+)', + '#submit' => ['::expandDatasourceFormSubmit'], + '#ajax' => [ + 'callback' => '::expandDatasourceFormAjax', + 'wrapper' => 'index-fields', + 'effect' => 'fade', + 'method' => 'replace', + ], + ); + + } + $item['expand_link'] = $expand_link; + $item['expand_button'] = $expand_button; + + //$label = $fields[$datasource_id] ? $fields[$datasource_id] : $this->t('General'); + //$item['label']['#markup'] = $label; + + if ($active) { + $properties = $this->entity->getPropertyDefinitions($datasource_id == 'general' ? NULL: $datasource_id); + if ($properties) { + $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; + + // Add child elements. + if(is_array($fields[$datasource_id])){ + // Add new things. + $new_things = $this->createFieldContainers($fields[$datasource_id]); + foreach($new_things as $new_thing){ + $items[] = $new_thing; + } + } + + } - else { - $url->setOption('query', array('datasource' => $datasource_id)); - $expand_link = array( - '#type' => 'link', - '#title' => '(+) ', - '#url' => $url, - ); + return $items; + } + + /** + * Handles form submissions for expanding a datasource. + */ + public function expandDatasourceFormSubmit(&$form, FormStateInterface &$form_state) { + // REMOVE. + $this->displayMethodInvocation('expandDatasourceFormSubmit'); + + // 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); + + //dsm(array_keys($properties)); + dsm('opgevraagde datasources'); + dsm($datasources); + foreach(array_keys($properties) as $property){ + $datasources[$field_name][$property] = NULL; } - $item['expand_link'] = $expand_link; - - $label = $datasource ? Html::escape($datasource->label()) : $this->t('General'); - $item['label']['#markup'] = $label; - - if ($active) { - $properties = $this->entity->getPropertyDefinitions($datasource_id ?: NULL); - if ($properties) { - $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); - } + + dsm('datasources changes uit ajax submit'); + dsm($datasources); + $form_state->setValue('datasources', $datasources); + dsm('opgeslaan in datasources?'); + dsm($form_state->getValue('datasources')); + $form_state->setRebuild(); + } + + /** + * Return new datasource structure. + */ + public function expandDatasourceFormAjax(array $form, FormStateInterface &$form_state) { + + + $this->displayMethodInvocation('expandDatasourceFormAjax'); + //dsm($form_state->getValue('datasource')); + //$form = $form_state->getCompleteForm(); + //$button = $form_state->getTriggeringElement(); + + // Go one level up in the form, to the widgets container. + //dsm('array of button parrents'); + //dsm($button['#array_parents']); + //$element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -3)); + //echo 'Which element trigggered?'; + //dsm('Which element trigggered?'); + + //dsm(array_keys($element)); + //dsm($element['#type']); + //dsm($element['field-name']); + + $form['messages']['status'] = [ + '#type' => 'status_messages', + ]; +//dsm($form['datasources']['#value']); + + //$datasources = $form_state->getValue('datasources'); + //dsm($datasources); + //$form['datasources']['#value'] = $datasources; + //return $form['messages']; + //return $form['index-fields']; + //return $element; + return $form; + + /* + * $button = $form_state->getTriggeringElement(); + + + // Ensure the widget allows adding additional items. + if ($element['#cardinality'] != FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) { + return; } - return $item; + // Add a DIV around the delta receiving the Ajax effect. + $delta = $element['#max_delta']; + $element[$delta]['#prefix'] = '
The data type of a field determines how it can be used for searching and filtering. The boost is used to give additional weight to certain fields, for example titles or tags.
For information about the data types available for indexing, see the data types table at the bottom of the page.
', array('@url' => '#search-api-data-types-table')); if ($index->hasValidServer()) { $arguments = array(