displayPluginManager = $display_plugin_manager; [$view_id, $display_id] = preg_split('/__/', $this->getDerivativeId(), 2); $this->view = View::Load($view_id); $this->display = $this->view->getDisplay($display_id); $this->formBuilder = $form_builder; $this->request = clone $request; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('plugin.manager.search_api.display'), $container->get('form_builder'), $container->get('request_stack')->getMainRequest() ); } /** * {@inheritdoc} */ public function defaultConfiguration() { return [ self::SETTING_FIELDS => [], self::SETTING_CONTEXTUAL_FILTER => NULL, ]; } /** * Fields which can be enabled / disabled for display in the search form. * * @return \Drupal\search_api\Item\FieldInterface[] * The $fields sorted by label. */ protected function getFields() { $fields = $this->getIndex()->getFields(); // First pass sort on label, secondary sort will be used // when looking at existing configuration for this block. uasort($fields, function ($a, $b) { return strcmp($a->getLabel(), $b->getLabel()); }); return $fields; } /** * Get regions of table to display. * * @return array * The properties of each region used for building the table of fields. */ protected function getRegions() { // Classes for select fields like 'weight' and 'display' are hard-coded // and used in js/islandora-advanced-search.admin.js. return [ 'visible' => [ 'title' => $this->t('Visible'), 'invisible' => TRUE, 'message' => $this->t('No search field is visible.'), 'weight' => self::WEIGHT_FIELD_CLASS . '-visible', 'display' => self::DISPLAY_FIELD_CLASS . '-visible', ], 'hidden' => [ 'title' => $this->t('Hidden'), 'invisible' => FALSE, 'message' => $this->t('No search field is hidden.'), 'weight' => self::WEIGHT_FIELD_CLASS . '-hidden', 'display' => self::DISPLAY_FIELD_CLASS . '-hidden', ], ]; } /** * Options for field display derived from the available regions. * * @return array * Display select field options. */ protected function getDisplayOptions() { $options = []; foreach ($this->getRegions() as $region => $settings) { $options[$region] = $settings['title']; } return $options; } /** * {@inheritdoc} */ public function blockForm($form, FormStateInterface $form_state) { // At most we will have one row per field. $fields = $this->getFields(); $weight_delta = round(count($fields) / 2); // Group each field into a region given our current configuration. $visible_fields = $this->configuration[self::SETTING_FIELDS]; $regions = $this->getRegions(); $display_options = $this->getDisplayOptions(); // Field rows are grouped by the region in which they are displayed. $field_rows = array_fill_keys(array_keys($regions), []); foreach ($fields as $field) { // If a field exists in the blocks configuration than it is 'visible' and // its weight is equivalent to its order in the configuration, // i.e. its index. $identifier = $field->getFieldIdentifier(); $weight = array_search($identifier, $visible_fields); $visible = $weight !== FALSE; $region = $visible ? self::REGION_VISIBLE : self::REGION_HIDDEN; $field_rows[$region][$identifier] = [ '#attributes' => [ 'class' => ['draggable'], ], 'label' => ['#plain_text' => $field->getLabel()], 'identifier' => ['#plain_text' => $identifier], 'weight' => [ '#type' => 'weight', '#title' => $this->t('Weight'), '#title_display' => 'invisible', '#default_value' => $visible ? $weight : 0, '#delta' => $weight_delta, '#attributes' => [ 'class' => [self::WEIGHT_FIELD_CLASS, $regions[$region]['weight']], ], ], 'display' => [ '#type' => 'select', '#title' => $this->t('Display'), '#title_display' => 'invisible', '#options' => $display_options, '#default_value' => $region, '#attributes' => [ 'class' => [self::DISPLAY_FIELD_CLASS, $regions[$region]['display']], ], ], ]; } // Sort the visible rows by their weight. uasort($field_rows[self::REGION_VISIBLE], function ($a, $b) { $a = $a['weight']['#default_value']; $b = $b['weight']['#default_value']; if ($a == $b) { return 0; } return ($a < $b) ? -1 : 1; }); // Build Rows. $rows = []; $table_drag = []; foreach ($regions as $region => $properties) { $rows += [ // Conditionally display region title as a row. "region-$region" => $properties['invisible'] ? NULL : [ '#attributes' => [ 'class' => ['region-title', "region-title-$region"], ], 'label' => [ '#plain_text' => $properties['title'], '#wrapper_attributes' => [ 'colspan' => 4, ], ], ], // Will dynamically display if the region has fields or not controlled // by Drupal behaviors in js/islandora-advanced-search.admin.js. "region-$region-message" => [ '#attributes' => [ 'class' => [ 'region-message', "region-$region-message", empty($field_rows[$region]) ? 'region-empty' : 'region-populated', ], ], 'message' => [ '#markup' => '' . $properties['message'] . '', '#wrapper_attributes' => [ 'colspan' => 4, ], ], ], ]; // Include field rows in this region. $rows += $field_rows[$region]; // Configure order by weight field in region. $table_drag[] = [ 'action' => 'order', 'relationship' => 'sibling', 'group' => self::WEIGHT_FIELD_CLASS, 'subgroup' => $properties['weight'], 'source' => self::WEIGHT_FIELD_CLASS, ]; // Configure drag action for display field in region. $table_drag[] = [ 'action' => 'match', 'relationship' => 'sibling', 'group' => self::DISPLAY_FIELD_CLASS, 'subgroup' => $properties['display'], 'source' => self::DISPLAY_FIELD_CLASS, ]; } $form[self::SETTING_FIELDS] = [ '#type' => 'table', '#attributes' => [ // Identifier is hard-coded and used in // js/islandora-advanced-search.admin.js. 'id' => 'advanced-search-fields', ], '#header' => [ $this->t('Label'), $this->t('Field'), $this->t('Weight'), $this->t('Display'), ], '#empty' => $this->t('No search fields, please check search index configuration.'), '#tabledrag' => $table_drag, ] + $rows; // If there is contextual filters associated with the display that means // we can filter on collection / sub-collection. Allow the user to choose // which filters collections. $id = NULL; $field = NULL; $options = []; if (isset($this->display['display_options']['arguments'])) { foreach ($this->display['display_options']['arguments'] as $context_filter) { $id = $context_filter['id']; $field = $context_filter['field']; if (isset($fields[$field])) { $options[$id] = $fields[$field]->getLabel() . ':' . $id; } } } if (count($options) > 0) { $form[self::SETTING_CONTEXTUAL_FILTER] = [ '#type' => 'select', '#title' => $this->t('Context Filter'), '#description' => $this->t('If more than one Context Filter is defined, specify which is used to include only direct children of the Collection as it will disabled to allow recursive searching.'), '#options' => $options, '#default_value' => $this->configuration[self::SETTING_CONTEXTUAL_FILTER], '#multiple' => FALSE, '#required' => FALSE, '#size' => count($options) + 1, ]; } $form['#attributes']['class'][] = 'clearfix'; $form['#attached']['library'][] = 'advanced_search/advanced.search.admin'; return $form; } /** * {@inheritdoc} */ public function blockSubmit($form, FormStateInterface $form_state) { $values = $form_state->getValues(); $fields = array_filter($values[self::SETTING_FIELDS], function ($field) { return $field['display'] == 'visible'; }); uasort($fields, '\Drupal\Component\Utility\SortArray::sortByWeightElement'); $this->configuration[self::SETTING_FIELDS] = array_keys($fields); if (isset($values[self::SETTING_CONTEXTUAL_FILTER])) { $this->configuration[self::SETTING_CONTEXTUAL_FILTER] = $values[self::SETTING_CONTEXTUAL_FILTER]; } } /** * {@inheritdoc} */ public function build() { $fields = $this->getIndex()->getFields(); $configured_fields = []; foreach ($this->configuration[self::SETTING_FIELDS] as $identifier) { $configured_fields[$identifier] = $fields[$identifier]; } return $this->formBuilder->getForm('Drupal\advanced_search\Form\AdvancedSearchForm', $this->view, $this->display, $configured_fields, $this->configuration[self::SETTING_CONTEXTUAL_FILTER]); } /** * {@inheritdoc} */ public function getCacheMaxAge() { // The block cannot be cached, because it must always match the current // search results. return 0; } /** * Get Search Index. */ protected function getIndex() { $id = $this->getDerivativeId(); return $this->displayPluginManager->createInstance("views_{$this->display['display_plugin']}:{$id}")->getIndex(); } }