From e379ad72d96f7b07560b47218af0f9d1bf9982f4 Mon Sep 17 00:00:00 2001 From: Nigel Banks Date: Tue, 20 Jul 2021 13:59:13 +0000 Subject: [PATCH] Allow page view derived Advanced Search blocks on any page Allows the Advanced Search block to be used on pages where its corresponding view is not present. Now it will redirect to the route associated with the view it was generated from. This is not valid for Advanced Search blocks that are derived from non-page based views, as there is no known location in which to redirect the query. --- .../js/islandora_advanced_search.form.js | 23 ++++++--- .../src/AdvancedSearchQuery.php | 15 +++++- .../src/Form/AdvancedSearchForm.php | 49 +++++++++++++++++-- .../src/Plugin/Block/AdvancedSearchBlock.php | 2 +- 4 files changed, 74 insertions(+), 15 deletions(-) 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..513f20b6 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' => [ @@ -353,8 +393,9 @@ class AdvancedSearchForm extends FormBase { } $terms = array_filter($terms); $recurse = filter_var($values['recursive'], 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]); } /**