1

I want to alter the input typed into the default search block in a way that when users search for "möp" (with a German umlaut) the search should be broadened to "möp OR moep" automatically.

So I simply tried to append a custom form submit to the search_block_form and simply expand the string by a certain logic. But then I found out that the search_block_form seems to be a little bit special. In core/modules/search/src/Form/SearchBlockForm.php I found the following comment.

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // This form submits to the search page, so processing happens there.
  }

My question now is: Where do I actually add the logic exactly if not in the form submit? I don't find any redirect or controller that would help here. Could you please point me in the right direction? Or maybe, you even have a better idea than appending the logic this way?


I removed the D8 tag as I guess the logic behind this is pretty equal amongst all common Drupal versions.

2
  • Submit handler is in core/modules/search/src/Form/SearchPageForm.php. Also Plugins with additional search parameters will need to provide their own form submit handler to replace this.
    – developer
    Commented Mar 23, 2017 at 10:41
  • @sarika - I see it and can change it when I hack the code in the search module. Can you give me a rough outline on how to override this from a custom module?
    – leymannx
    Commented Mar 24, 2017 at 14:15

3 Answers 3

1

You can do this in hook_search_preprocess():

Preprocess text for search.

This hook is called to preprocess both the text added to the search index and the keywords users have submitted for searching. The same processing needs to be applied to both so that searches will find matches.

This is not part of the preprocess in theming. This hook is called directly from the search module. Btw. German umlauts are already replaced by default.

2
  • Brilliant! Yeah, German Umlauts are already replaced by their equivalent letters without the dots. But the equivalent with the e appended to it is missing, as far as I observed it.
    – leymannx
    Commented Mar 23, 2017 at 14:10
  • Hm, this function doesn't seem to do what it's supposed to do. Even the sample code on the function's page doesn't return the proposed output. Filed an issue for now drupal.org/node/2863687
    – leymannx
    Commented Mar 24, 2017 at 14:01
1

I am not certain if this will help, but I found from the module documentation the following

search_invoke_preprocess() is deprecated in drupal:9.1.0 and is removed from drupal:10.0.0. Use a custom implementation of SearchTextProcessorInterface instead. See https://www.drupal.org/node/3078162

According to which preprocessing is moved to an internal method https://www.drupal.org/project/drupal/issues/3075703

I guess the last resort I found was creating a preprocess plugin as described in https://www.drupal.org/docs/8/modules/search-api/getting-started/processors

0

As hook_preprocess_search() currently is not preprocessing (issue here) I found a workaround for now. In the end I had to have the logic in two places.

First, I created a custom block that contains a custom form that roughly mimics the search block form by sending/redirecting the search string (after my desired preprocessing) to the search page. That's how my submit function looks like.

public function submitForm(array &$form, FormStateInterface $form_state) {

  $input = $form_state->getValue('MYTEXTFIELD');

  // Trim whitespaces.
  $input = trim($input);
  $input = preg_replace('/\s+/', ' ', $input);

  // Rewrite search string to match my logic.
  // Searching for 'Müller' rewrites to 'Müller OR Mueller'
  $processed = _rewrite_search_string($input);

  // The rest now is routine as Drupal replaces spaces with plus
  // signs between two words in a multiple word string.
  // Let's do the same.
  $keys         = explode(' ', $processed);
  $max          = sizeof($keys);
  $search_query = '';

  if ($max == 1) {
    $search_query = $keys[0];
  }

  else {
    for ($i = 0; $i < $max - 1; $i++) {
      $search_query .= $keys[$i] . '+';
    }
    $search_query .= $keys[$max - 1];
  }

  // Finally, redirect to the search page with the expected
  // query pattern. For example 'Müller+OR+Mueller'.
  $url = Url::fromUserInput('/search/content?keys=' .
    $search_query);
  $form_state->setRedirectUrl($url);

}

Second, the same logic but in a different way needed to get appended to the real 'search_form' on the search page. So I added a custom submit function that looks the same as the original search form submit function except for the little addition that adds the desired logic.

function MYMODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  if ($form_id == 'search_form') {

    $form['#submit'][] = 'MYCUSTOMSUBMIT';
  }
}

function MYCUSTOMSUBMIT(&$form, FormStateInterface $form_state) {

  $input = $form_state->getValue('keys');

  // Here the same as above. 'Müller' gets rewritten to 'Müller OR Mueller'.
  $processed = _rewrite_search_string($input);

  $query['keys'] = $processed;

  // Rest is just c/p.
  $route = 'search.view_' . $form_state->get('search_page_id');
  $form_state->setRedirect(
    $route,
    [],
    ['query' => $query]
  );
}

As soon as hook_search_preprocess() gets fixed I mark @4k4's answer as the correct one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.