diff --git a/modules/islandora_advanced_search/README.md b/modules/islandora_advanced_search/README.md index b1f73a50..71eb6c53 100644 --- a/modules/islandora_advanced_search/README.md +++ b/modules/islandora_advanced_search/README.md @@ -7,6 +7,7 @@ - [Configuring Solr](#configuring-solr) - [Configure Collection Search](#configure-collection-search) - [Configure Views](#configure-views) + - [Exposed Form](#exposed-form) - [Collection Search](#collection-search) - [Paging](#paging) - [Sorting](#sorting) @@ -96,6 +97,21 @@ the [Drupal Documentation](https://www.drupal.org/docs/8/core/modules/views), as well as the [Search API Documentation](https://www.drupal.org/docs/contributed-modules/search-api). +### Exposed Form + +Solr views allow the user to configure an exposed form (_optionally as a +block_). This form / block is **different** from the +[Advanced Search Block](#advanced-search-block). This module does not make any +changes to the form, but this form can cause the Advanced Search Block to not +function if configured incorrectly. + +The Advanced Search Block requires that if present the Exposed forms +`Exposed form style` is set to `Basic` rather than `Input Required`. As +`Input Required` will prevent any search from occurring unless the user puts an +additional query in the Exposed form as well. + +![Form Style](./docs/basic-input.png) + ### Collection Search That being said it will be typical that you require the following @@ -194,6 +210,11 @@ checkbox. ![image](./docs/advanced_search_block_settings.png) +> N.B. Be aware that the Search views [Exposed Form](#exposed-form) can have an +> affect on the function of the +> [Advanced Search Block](#advanced-search-block). Please refer to that section +> to learn more. + ## Documentation Further documentation for this module is available on the diff --git a/modules/islandora_advanced_search/docs/basic-input.png b/modules/islandora_advanced_search/docs/basic-input.png new file mode 100644 index 00000000..758c2e83 Binary files /dev/null and b/modules/islandora_advanced_search/docs/basic-input.png differ diff --git a/modules/islandora_advanced_search/js/islandora_advanced_search.form.js b/modules/islandora_advanced_search/js/islandora_advanced_search.form.js index 7b068bb4..f81b3509 100644 --- a/modules/islandora_advanced_search/js/islandora_advanced_search.form.js +++ b/modules/islandora_advanced_search/js/islandora_advanced_search.form.js @@ -7,7 +7,8 @@ // Gets current parameters minus ones provided by the form. function getParams(query_parameter, recurse_parameter) { - var params = Drupal.Views.parseQueryString(window.location.href); + const url_search_params = new URLSearchParams(window.location.search); + const params = Object.fromEntries(url_search_params.entries()); // Remove Advanced Search Query Parameters. const param_match = "query\\[\\d+\\]\\[.+\\]".replace("query", query_parameter); const param_regex = new RegExp(param_match, "g"); @@ -97,13 +98,19 @@ // // Logic server side / client side should match to generate the // appropriate URL with javascript enabled or disable. - $form.submit(function (e) { - e.preventDefault(); - e.stopPropagation(); - const inputs = $form.serializeArray(); - const href = url(inputs, settings.islandora_advanced_search_form); - window.history.pushState(null, document.title, href); - }); + // + // If a route is set for the view display that this form is derived + // from, and we are not on the same page as that route, rely on the + // normal submit which will redirect to the appropriate page. + if (!settings.islandora_advanced_search_form.redirect) { + $form.submit(function (e) { + e.preventDefault(); + e.stopPropagation(); + const inputs = $form.serializeArray(); + const href = url(inputs, settings.islandora_advanced_search_form); + window.history.pushState(null, document.title, href); + }); + } // Reset should trigger refresh of AJAX Blocks / Views. $form.find('input[data-drupal-selector = "edit-reset"]').mousedown(function (e) { const inputs = []; diff --git a/modules/islandora_advanced_search/src/AdvancedSearchQuery.php b/modules/islandora_advanced_search/src/AdvancedSearchQuery.php index 45fe3ee0..f3083b32 100644 --- a/modules/islandora_advanced_search/src/AdvancedSearchQuery.php +++ b/modules/islandora_advanced_search/src/AdvancedSearchQuery.php @@ -3,6 +3,8 @@ namespace Drupal\islandora_advanced_search; use Drupal\block\Entity\Block; +use Drupal\Core\EventSubscriber\MainContentViewSubscriber; +use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Url; use Drupal\islandora_advanced_search\Form\SettingsForm; use Drupal\islandora_advanced_search\Plugin\Block\AdvancedSearchBlock; @@ -223,9 +225,18 @@ class AdvancedSearchQuery { * @return \Drupal\Core\Url * Url for the given request combined with search query parameters. */ - public function toUrl(Request $request, array $terms, bool $recurse) { - $url = Url::createFromRequest($request); + public function toUrl(Request $request, array $terms, bool $recurse, $route = NULL) { $query_params = $request->query->all(); + if ($route) { + $url = Url::fromRoute($route); + // The form that built the url may use AJAX, but we are redirecting to a + // new page, so it should be disabled. + unset($query_params[FormBuilderInterface::AJAX_FORM_REQUEST]); + unset($query_params[MainContentViewSubscriber::WRAPPER_FORMAT]); + } + else { + $url = Url::createFromRequest($request); + } unset($query_params[$this->queryParameter]); foreach ($terms as $term) { $query_params[$this->queryParameter][] = $term->toQueryParams(); diff --git a/modules/islandora_advanced_search/src/Form/AdvancedSearchForm.php b/modules/islandora_advanced_search/src/Form/AdvancedSearchForm.php index 7b0c6683..c00ce566 100644 --- a/modules/islandora_advanced_search/src/Form/AdvancedSearchForm.php +++ b/modules/islandora_advanced_search/src/Form/AdvancedSearchForm.php @@ -5,10 +5,15 @@ namespace Drupal\islandora_advanced_search\Form; use Drupal\Component\Utility\Html; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\islandora_advanced_search\AdvancedSearchQuery; use Drupal\islandora_advanced_search\AdvancedSearchQueryTerm; use Drupal\islandora_advanced_search\GetConfigTrait; +use Drupal\views\DisplayPluginCollection; +use Drupal\views\Entity\View; +use Drupal\views\Plugin\views\display\PathPluginBase; +use Drupal\views\Views; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; @@ -46,11 +51,19 @@ class AdvancedSearchForm extends FormBase { */ protected $request; + /** + * The current route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $currentRouteMatch; + /** * Class constructor. */ - public function __construct(Request $request) { + public function __construct(Request $request, RouteMatchInterface $current_route_match) { $this->request = $request; + $this->currentRouteMatch = $current_route_match; } /** @@ -58,7 +71,8 @@ class AdvancedSearchForm extends FormBase { */ public static function create(ContainerInterface $container) { return new static( - $container->get('request_stack')->getMasterRequest() + $container->get('request_stack')->getMasterRequest(), + $container->get('current_route_match') ); } @@ -186,13 +200,39 @@ class AdvancedSearchForm extends FormBase { return [$recursive, $term_values]; } + /** + * Gets the route name for the view display used to derive this forms block. + * + * @return string|null + * The route name for the view display that was used to create this + * forms block. + */ + protected function getRouteName(FormStateInterface $form_state) { + $view = $form_state->get('view'); + $display = $form_state->get('display'); + $display_handlers = new DisplayPluginCollection($view->getExecutable(), Views::pluginManager('display')); + $display_handler = $display_handlers->get($display['id']); + if ($display_handler instanceof PathPluginBase) { + return $display_handler->getRouteName(); + } + return NULL; + } + /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, array $fields = [], string $context_filter = NULL) { + public function buildForm(array $form, FormStateInterface $form_state, View $view = NULL, array $display = [], array $fields = [], string $context_filter = NULL) { + // Keep reference to view and display as the submit handler may use them + // to redirect the user to the search page. + $form_state->set('view', $view); + $form_state->set('display', $display); + $route_name = $this->getRouteName($form_state); + $requires_redirect = $route_name ? $this->currentRouteMatch->getRouteName() !== $route_name : FALSE; + $form['#attached']['library'][] = 'islandora_advanced_search/advanced.search.form'; $form['#attached']['drupalSettings']['islandora_advanced_search_form'] = [ 'id' => Html::getId($this->getFormId()), + 'redirect' => $requires_redirect, 'query_parameter' => AdvancedSearchQuery::getQueryParameter(), 'recurse_parameter' => AdvancedSearchQuery::getRecurseParameter(), 'mapping' => [ @@ -352,9 +392,10 @@ class AdvancedSearchForm extends FormBase { $terms[] = AdvancedSearchQueryTerm::fromUserInput($term); } $terms = array_filter($terms); - $recurse = filter_var($values['recursive'], FILTER_VALIDATE_BOOLEAN); + $recurse = filter_var(isset($values['recursive']) ? $values['recursive'] : FALSE, FILTER_VALIDATE_BOOLEAN); + $route = $this->getRouteName($form_state); $advanced_search_query = new AdvancedSearchQuery(); - return $advanced_search_query->toUrl($this->request, $terms, $recurse); + return $advanced_search_query->toUrl($this->request, $terms, $recurse, $route); } /** diff --git a/modules/islandora_advanced_search/src/Plugin/Block/AdvancedSearchBlock.php b/modules/islandora_advanced_search/src/Plugin/Block/AdvancedSearchBlock.php index 19e6a290..c5f5adb8 100644 --- a/modules/islandora_advanced_search/src/Plugin/Block/AdvancedSearchBlock.php +++ b/modules/islandora_advanced_search/src/Plugin/Block/AdvancedSearchBlock.php @@ -371,7 +371,7 @@ class AdvancedSearchBlock extends BlockBase implements ContainerFactoryPluginInt foreach ($this->configuration[self::SETTING_FIELDS] as $identifier) { $configured_fields[$identifier] = $fields[$identifier]; } - return $this->formBuilder->getForm('Drupal\islandora_advanced_search\Form\AdvancedSearchForm', $configured_fields, $this->configuration[self::SETTING_CONTEXTUAL_FILTER]); + return $this->formBuilder->getForm('Drupal\islandora_advanced_search\Form\AdvancedSearchForm', $this->view, $this->display, $configured_fields, $this->configuration[self::SETTING_CONTEXTUAL_FILTER]); } /**