Skip to content
Snippets Groups Projects
Commit 0392c570 authored by Mark Fullmer's avatar Mark Fullmer
Browse files

Issue #3418134 by mark_fullmer, afsch, jenna.tollerson: Make the query...

Issue #3418134 by mark_fullmer, afsch, jenna.tollerson: Make the query parameter key a configurable setting
parent fe398e25
No related branches found
No related tags found
1 merge request!5Issue #3418134 by mark_fullmer, jenna.tollerson: Make the query parameter key...
Pipeline #136796 passed with warnings
......@@ -6,10 +6,11 @@
*/
use Drupal\Core\Entity\EntityInterface;
use Drupal\search\Entity\SearchPage;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\google_cse\Plugin\Search\GoogleSearch;
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
use Drupal\search\Entity\SearchPage;
/**
* Alter the core-provided search input block primarily for stylistic purposes.
......@@ -28,6 +29,11 @@ function google_cse_form_search_block_form_alter(&$form, &$form_state, $form_id)
return;
}
$config = $implementation->getPlugin()->getConfiguration();
$query_key = $config['query_key'] ?? GoogleSearch::$defaultQueryKey;
if ($query_key !== 'keys') {
$form[$query_key] = $form['keys'];
unset($form['keys']);
}
$form['#attached']['library'][] = 'google_cse/googlecseWatermark';
$form['#attributes']['class'][] = 'google-cse';
$language = \Drupal::languageManager()->getCurrentLanguage()->getId();
......@@ -40,7 +46,7 @@ function google_cse_form_search_block_form_alter(&$form, &$form_state, $form_id)
$form['#attached']['library'][] = 'google_cse/noWatermark';
}
if (intval($config['results_searchbox_width']) > 0) {
$form['keys']['#size'] = intval($config['results_searchbox_width']);
$form[$query_key]['#size'] = intval($config['results_searchbox_width']);
}
if ($config['results_display'] === 'google') {
// This search has been configured to display results on Google.
......@@ -50,8 +56,8 @@ function google_cse_form_search_block_form_alter(&$form, &$form_state, $form_id)
'#type' => 'hidden',
'#value' => $config['cx'],
];
$form['q'] = $form['keys'];
unset($form['keys']);
$form['q'] = $form[$query_key];
unset($form[$query_key]);
}
}
......
services:
google_cse.route_subscriber:
class: Drupal\google_cse\Routing\RouteSubscriber
tags:
- { name: event_subscriber }
<?php
namespace Drupal\google_cse\Controller;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\google_cse\Plugin\Search\GoogleSearch;
use Drupal\search\Controller\SearchController;
use Drupal\search\Form\SearchPageForm;
use Drupal\search\SearchPageInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Override the Route controller for search.
*/
class GoogleCseSearchController extends SearchController {
/**
* Creates a render array for the search page.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
* @param \Drupal\search\SearchPageInterface $entity
* The search page entity.
*
* @return array
* The search form and search results build array.
*/
public function view(Request $request, SearchPageInterface $entity) {
$configuration = $entity->get('configuration');
$query_key = $configuration['query_key'] ?? GoogleSearch::$defaultQueryKey;
// If the query parameter key hasn't been customized, use the parent class.
if ($query_key === 'keys') {
$build = parent::view($request, $entity);
return $build;
}
$build = [];
$plugin = $entity->getPlugin();
// Build the form first, because it may redirect during the submit,
// and we don't want to build the results based on last time's request.
$build['#cache']['contexts'][] = 'url.query_args:' . $query_key;
if ($request->query->has($query_key)) {
$keys = trim($request->query->get($query_key));
$plugin->setSearch($keys, $request->query->all(), $request->attributes->all());
}
$build['#title'] = $plugin->suggestedTitle();
$build['search_form'] = $this->formBuilder()->getForm(SearchPageForm::class, $entity);
// Build search results, if keywords or other search parameters are in the
// GET parameters.
$results = [];
if ($request->query->has($query_key)) {
if ($plugin->isSearchExecutable()) {
// Log the search.
if ($this->config('search.settings')->get('logging')) {
$this->logger->notice('Searched %type for %keys.', ['%keys' => $keys, '%type' => $entity->label()]);
}
// Collect the search results.
$results = $plugin->buildResults();
}
else {
// The search not being executable means that no keywords or other
// conditions were entered.
$this->messenger()->addError($this->t('Please enter some keywords.'));
}
}
if (count($results)) {
$build['search_results_title'] = [
'#markup' => '<h2>' . $this->t('Search results') . '</h2>',
];
}
$build['search_results'] = [
'#theme' => ['item_list__search_results__' . $plugin->getPluginId(), 'item_list__search_results'],
'#items' => $results,
'#empty' => [
'#markup' => '<h3>' . $this->t('Your search yielded no results.') . '</h3>',
],
'#list_type' => 'ol',
'#context' => [
'plugin' => $plugin->getPluginId(),
],
];
$this->renderer->addCacheableDependency($build, $entity);
if ($plugin instanceof CacheableDependencyInterface) {
$this->renderer->addCacheableDependency($build, $plugin);
}
// If this plugin uses a search index, then also add the cache tag tracking
// that search index, so that cached search result pages are invalidated
// when necessary.
if ($plugin->getType()) {
$build['search_results']['#cache']['tags'][] = 'search_index';
$build['search_results']['#cache']['tags'][] = 'search_index:' . $plugin->getType();
}
$build['pager'] = [
'#type' => 'pager',
];
return $build;
}
}
......@@ -4,6 +4,7 @@ namespace Drupal\google_cse\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\google_cse\Plugin\Search\GoogleSearch;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
......@@ -57,25 +58,25 @@ class GoogleCSESearchBoxForm extends FormBase {
'#type' => 'hidden',
'#value' => $settings['cx'],
];
$query = 'keys';
$query_key = $settings['query_key'] ?? GoogleSearch::$defaultQueryKey;
if ($settings['results_display'] === 'google') {
$form['#action'] = 'https://cse.google.com/cse';
// If the results are to be displayed on this site, use the query
// parameter 'keys'. If on Google, use 'q'.
$query = 'q';
// If the results are to be displayed on this site, use the site query
// parameter. If on Google, use 'q'.
$query_key = 'q';
}
$form[$query] = [
$form[$query_key] = [
'#type' => 'textfield',
'#id' => 'google-cse-query',
'#default_value' => $this->requestStack->getCurrentRequest()->query->has('query') ? $this->requestStack->getCurrentRequest()->query->get('query') : '',
'#default_value' => $this->requestStack->getCurrentRequest()->query->has($query_key) ? $this->requestStack->getCurrentRequest()->query->get($query_key) : '',
];
$form['sa'] = [
'#type' => 'submit',
'#id' => 'google-cse-submit',
'#value' => $this->t('Search'),
];
$form['keys']['#size'] = intval($settings['results_searchbox_width']);
$form['keys']['#title'] = $this->t('Enter your keywords');
$form[$query_key]['#size'] = intval($settings['results_searchbox_width']);
$form[$query_key]['#title'] = $this->t('Enter your keywords');
return $form;
}
......
......@@ -8,10 +8,11 @@ use Drupal\Core\Cache\Cache;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\google_cse\Plugin\Search\GoogleSearch;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -181,8 +182,10 @@ class GoogleSearchBlock extends BlockBase implements ContainerFactoryPluginInter
$google_markup = $plugin->buildResults();
$config = $this->configFactory->get('search.page.' . $search_id);
$settings = $config->get('configuration');
$query = $settings['query_key'] ?? GoogleSearch::$defaultQueryKey;
$form['search'] = ['#markup' => '<div class="gcse-searchbox-only" data-resultsUrl="/search/' . $entity->get('path') . '" data-queryParameterName="' . $query . '"></div>'];
if ($search_type === 'google') {
$form['search'] = ['#markup' => '<div class="gcse-searchbox-only" data-resultsUrl="/search/' . $entity->get('path') . '" data-queryParameterName="keys"></div>'];
$form['search'] = ['#markup' => '<div class="gcse-searchbox-only" data-resultsUrl="/search/' . $entity->get('path') . '" data-queryParameterName="' . $query . '"></div>'];
// Add the Google Programmable Search library itself, with ID as a param.
$form['#attached']['html_head'][] = [
[
......
......@@ -31,6 +31,13 @@ class GoogleSearch extends ConfigurableSearchPluginBase implements AccessibleInt
*/
protected $configuration;
/**
* The default query parameter key for searchs
*
* @var string
*/
public static $defaultQueryKey = 'keys';
/**
* RequestStack object for getting requests.
*
......@@ -98,6 +105,7 @@ class GoogleSearch extends ConfigurableSearchPluginBase implements AccessibleInt
'results_display' => 'here',
'custom_results_display' => 'results-only',
'custom_css' => '',
'query_key' => self::$defaultQueryKey,
'watermark' => FALSE,
'data_attributes' => [],
];
......@@ -194,6 +202,14 @@ class GoogleSearch extends ConfigurableSearchPluginBase implements AccessibleInt
'#default_value' => $this->configuration['results_searchbox_width'] ?? $default['results_searchbox_width'],
];
$form['query_key'] = [
'#title' => $this->t('Query parameter key'),
'#type' => 'textfield',
'#default_value' => $this->configuration['query_key'] ?? $default['query_key'],
'#description' => $this->t('Optionally change the query parameter displayed in the URL. For example, change <code>https://example.com/search/google?keys=streets</code> to <code>https://example.com/search/google?query=streets</code>.',),
'#required' => TRUE,
];
$form['custom_css'] = [
'#title' => $this->t('Stylesheet Override'),
'#type' => 'textfield',
......@@ -296,6 +312,7 @@ class GoogleSearch extends ConfigurableSearchPluginBase implements AccessibleInt
$this->configuration['results_searchbox_width'] = intval($values['results_searchbox_width']);
$this->configuration['results_display'] = $values['results_display'];
$this->configuration['custom_css'] = $values['custom_css'];
$this->configuration['query_key'] = $values['query_key'];
$this->configuration['custom_results_display'] = $values['custom_results_display'];
$this->configuration['watermark'] = $values['watermark'];
$this->configuration['display_drupal_search'] = $values['display_drupal_search'];
......@@ -315,6 +332,17 @@ class GoogleSearch extends ConfigurableSearchPluginBase implements AccessibleInt
parent::setSearch($keywords, $parameters, $attributes);
}
/**
* {@inheritdoc}
*/
public function buildSearchUrlQuery(FormStateInterface $form_state) {
// Grab the keywords entered in the form and put them as 'keys' in the GET.
$query_key = $this->configuration['query_key'] ?? self::$defaultQueryKey;
$keys = trim($form_state->getValue($query_key));
$query = [$query_key => $keys];
return $query;
}
/**
* {@inheritdoc}
*/
......@@ -400,10 +428,11 @@ class GoogleSearch extends ConfigurableSearchPluginBase implements AccessibleInt
$output['#attached']['library'][] = 'google_cse/customCSS_' . md5($this->configuration['custom_css']);
}
// Noscript message.
$query_key = $this->configuration['query_key'] ?? self::$defaultQueryKey;
$url = Url::fromUri('https://cse.google.com/cse', [
'query' => [
'cx' => $this->configuration['cx'],
'q' => \Drupal::request()->query->get('keys'),
'q' => \Drupal::request()->query->get($query_key),
],
]);
$output['#noscript'] = $this->t('@google, or enable JavaScript to view them here.', [
......@@ -434,7 +463,8 @@ class GoogleSearch extends ConfigurableSearchPluginBase implements AccessibleInt
// Tell Google to use Drupal core search's 'keys' query parameter.
// This is relevant for all choices except 'Google Hosted,' which
// changes this value, below.
$output['#primary_attributes']['data-queryParameterName'] = 'keys';
$query_key = $this->configuration['query_key'] ?? self::$defaultQueryKey;
$output['#primary_attributes']['data-queryParameterName'] = $query_key;
if (!empty($this->configuration['data_attributes'])) {
foreach ($this->configuration['data_attributes'] as $attribute) {
$output['#primary_attributes'][$attribute['key']] = $attribute['value'];
......@@ -516,6 +546,7 @@ class GoogleSearch extends ConfigurableSearchPluginBase implements AccessibleInt
// core search *block* form.
if ($this->pluginId == 'google_cse_search') {
if (!isset($this->configuration['display_drupal_search']) || $this->configuration['display_drupal_search'] === 1) {
$query_key = $this->configuration['query_key'] ?? self::$defaultQueryKey;
$form['#attributes']['class'][] = 'google-cse';
$form['basic']['keys']['#title'] = $this->t('Enter your keywords');
if ($this->configuration['results_searchbox_width']) {
......@@ -534,6 +565,11 @@ class GoogleSearch extends ConfigurableSearchPluginBase implements AccessibleInt
$form['basic']['q']['#weight'] = -10;
unset($form['basic']['keys']);
}
elseif ($query_key !== 'keys') {
// Customize query key, if configured.
$form['basic'][$query_key] = $form['basic']['keys'];
unset($form['basic']['keys']);
}
}
else {
// The configuration says the Drupal search input should not display.
......
<?php
/**
* @file
* Contains \Drupal\google_cse\Routing\RouteSubscriber.
*/
namespace Drupal\google_cse\Routing;
use Drupal\Core\Routing\RouteSubscriberBase;
use Drupal\search\Entity\SearchPage;
use Symfony\Component\Routing\RouteCollection;
/**
* Listens to the dynamic route events.
*/
class RouteSubscriber extends RouteSubscriberBase {
/**
* {@inheritdoc}
*/
public function alterRoutes(RouteCollection $collection) {
// The route for Google CSE is dynamically created. Substitute a custom
// controller that extends Drupal\search\Controller\SearchController.
$applicable_routes = [];
$search_implementations = SearchPage::loadMultiple();
foreach ($search_implementations as $search) {
if ($search->getPlugin()->getPluginId() !== 'google_cse_search') {
continue;
}
$applicable_routes[] = $search->id();
}
foreach ($applicable_routes as $google_cse_search) {
if ($route = $collection->get('search.view_' . $google_cse_search)) {
$route->setDefault('_controller', '\Drupal\google_cse\Controller\GoogleCseSearchController::view');
}
}
}
}
......@@ -152,6 +152,20 @@ class DisplayTest extends WebDriverTestBase {
$session->elementAttributeContains('css', '#search-block-form #edit-keys', 'size', '10');
$session->responseContains('<link rel="stylesheet" media="all" href="/sites/default/files/custom.css">');
// 4. Query parameter can be customized.
$this->drupalGet($config_form_path);
$custom_query_key = 'customquery';
$page->fillField('edit-query-key', $custom_query_key);
$page->pressButton('Save search page');
$this->assertNotEmpty($session->waitForText('The Google Programmable Search search page has been updated.'));
$search_page_with_query = Url::fromRoute('search.view_' . $entity_id, [], [
'query' => [
$custom_query_key => $terms['keys'],
],
'absolute' => TRUE,
])->toString();
$this->drupalGet($search_page_with_query);
// 4. Configuration can display Google search form and suppress core form.
$this->drupalGet($config_form_path);
$page->uncheckField('edit-display-drupal-search');
......@@ -159,7 +173,7 @@ class DisplayTest extends WebDriverTestBase {
$page->pressButton('Save search page');
$this->drupalGet($search_page_with_query);
// The Drupal search box is removed.
$session->elementNotExists('css', '#search-form #edit-keys');
$session->elementNotExists('css', '#search-form #edit-' . $custom_query_key);
// The Google search box is now visible.
$session->elementNotContains('css', 'form.gsc-search-box', 'display: none;');
......@@ -215,9 +229,10 @@ class DisplayTest extends WebDriverTestBase {
// The Google search box is not visible.
$session->elementAttributeContains('css', 'form.gsc-search-box', 'style', 'display: none;');
// The Drupal search box is visible.
$session->elementAttributeContains('css', '#google-cse-search-box-form .form-item-keys input', 'size', '10');
$session->elementAttributeContains('css', '#google-cse-search-box-form .form-item-' . $custom_query_key . ' input', 'size', '10');
// Search using the Google Search block.
$this->drupalGet('');
$terms = [$custom_query_key => '"dearest morsel of the earth"'];
$this->submitForm($terms, 'Search', 'google-cse-search-box-form');
// Module-provided block renders results on same page.
$this->assertEquals(\Drupal::request()->getBasePath() . '/user/2', parse_url($this->getUrl(), PHP_URL_PATH), 'Submitted to correct URL.');
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment