You are here

public function CustomSearchBlockForm::submitForm in Custom Search 8

Form submission handler.

Parameters

array $form: An associative array containing the structure of the form.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

Overrides FormInterface::submitForm

File

src/Form/CustomSearchBlockForm.php, line 378

Class

CustomSearchBlockForm
Builds the search form for the search block.

Namespace

Drupal\custom_search\Form

Code

public function submitForm(array &$form, FormStateInterface $form_state) {
  $config = $form_state
    ->get('config');
  $filters = [];

  // Keywords.
  $keys = trim($form_state
    ->getValue('keys'));

  // Filter Types.
  $types = $form_state
    ->hasValue('types') ? $form_state
    ->getValue('types') : [];
  if (!is_array($types)) {
    $types = [
      $types,
    ];
  }

  // Check if we're using another search (ie. Users).
  $first_type = current($types);
  if (substr($first_type, 0, 2) == 'o-') {
    $search_page_id = substr($first_type, 2);
    $search_pages = $this->entityTypeManager
      ->getStorage('search_page')
      ->loadMultiple([
      $search_page_id,
    ]);
    if (!empty($search_pages)) {
      $route = 'search.view_' . $search_page_id;
    }
  }
  else {

    // Build route.
    $route = 'search.view_' . $config['content']['page'];

    // Types filters.
    $types = array_map(function ($val) {
      return $this
        ->filterKeys($val);
    }, array_filter($types));
    $excluded = array_map(function ($val) {
      return $this
        ->filterKeys($val);
    }, array_filter($config['content']['excluded']));
    if (count($types)) {
      if (in_array('all', $types)) {

        // If - Any - is set to restrict the search, grab the content types.
        if ($config['content']['any']['restricts']) {
          $types = array_keys(array_filter($config['content']['types']));
        }

        // If exclusion has to be made, specify all the other types.
        if (!empty($excluded)) {
          $types = array_keys(node_type_get_names());
        }
        $types = array_diff($types, $excluded);
        if (!in_array('all', $types)) {
          foreach ($types as $type) {
            $filters[] = 'type:' . $type;
          }
        }
      }
      else {
        $types = array_diff($types, $excluded);
        foreach ($types as $type) {
          $filters[] = 'type:' . $type;
        }
      }
    }
    elseif (!empty($excluded)) {
      $types = array_diff(array_keys(node_type_get_names()), $excluded);
      foreach ($types as $type) {
        $filters[] = 'type:' . $type;
      }
    }

    // Taxonomy filters.
    if ($this->moduleHandler
      ->moduleExists('taxonomy')) {
      $terms = [];
      $vocabularies = $this->entityTypeManager
        ->getStorage('taxonomy_vocabulary')
        ->loadMultiple();
      foreach ($vocabularies as $voc) {
        $vid = $voc
          ->id();
        if ($form_state
          ->hasValue('vocabulary_' . $vid)) {
          $vterms = $form_state
            ->getValue('vocabulary_' . $vid);
          if (!is_array($vterms)) {
            $vterms = [
              $vterms,
            ];
          }
          $terms = array_merge($terms, $vterms);
        }
      }

      // Uses array_values() to filter here to get numerical index, so we can
      // splice the array later if needed (see line below the array_map()).
      $terms = array_map(function ($val) {
        return $this
          ->filterKeys($val);
      }, array_values(array_filter($terms)));

      // If one or more -Any- is selected, delete them.
      while (($index = array_search('all', $terms)) !== FALSE) {
        array_splice($terms, $index, 1);
      }
      if (count($terms)) {
        foreach ($terms as $term) {
          $filters[] = 'term:' . $term;
        }
      }
    }

    // Criteria filters.
    if ($form_state
      ->hasValue('criteria_or') && trim($form_state
      ->getValue('criteria_or')) != '') {
      $keys .= ' ' . str_replace(' ', ' OR ', trim($form_state
        ->getValue('criteria_or')));
    }
    if ($form_state
      ->hasValue('criteria_negative') && trim($form_state
      ->getValue('criteria_negative')) != '') {
      $keys .= ' -' . str_replace(' ', ' -', trim($form_state
        ->getValue('criteria_negative')));
    }
    if ($form_state
      ->hasValue('criteria_phrase') && trim($form_state
      ->getValue('criteria_phrase')) != '') {
      $keys .= ' "' . trim($form_state
        ->getValue('criteria_phrase')) . '"';
    }

    // Language filters.
    $languages = $form_state
      ->hasValue('languages') ? $form_state
      ->getValue('languages') : [];
    if (!is_array($languages)) {
      $languages = [
        $languages,
      ];
    }
    $languages = array_map(function ($val) {
      return $this
        ->filterKeys($val);
    }, array_filter($languages));
    if (count($languages)) {

      // If - Any - is selected and - Any - is set to restrict the search,
      // grab the languages.
      if (in_array('all', $languages) && $config['languages']['any']['restricts']) {
        $languages = array_keys(array_filter($config['languages']['languages']));
      }

      // If it's not - Any -, search for that language.
      if (!in_array('all', $languages)) {
        foreach ($languages as $language) {
          if ($language == 'current') {
            $filters[] = 'language:' . \Drupal::languageManager()
              ->getCurrentLanguage()
              ->getId();
          }
          else {
            $filters[] = 'language:' . $language;
          }
        }
      }
    }
  }

  // Build a custom path if needed.
  if ($form_state
    ->hasValue('paths') && $form_state
    ->getValue('paths') != '') {
    $route = $form_state
      ->getValue('paths');
    $route = str_replace('[current_path]', \Drupal::service('path.current')
      ->getPath(), $route);
    $route = str_replace('[key]', $keys, $route);
    if (strpos($route, '[types]') !== FALSE) {
      $route = str_replace('[types]', isset($types) && count($types) ? implode($config['paths']['separator'], $types) : '', $route);
    }
    if (strpos($route, '[terms]') !== FALSE) {
      $route = str_replace('[terms]', isset($terms) && count($terms) ? implode($config['paths']['separator'], $terms) : '', $route);
    }

    // Check for a query string.
    $query = [];
    $route_query_position = strpos($route, '?');
    if ($route_query_position !== FALSE) {
      $query_tmp = substr($route, 1 + $route_query_position);
      $query_tmp = str_replace('&', '&', $query_tmp);
      $query_tmp = explode('&', $query_tmp);
      foreach ($query_tmp as $param) {
        $param_exploded = explode('=', $param);
        $query[$param_exploded[0]] = $param_exploded[1];
      }
      $route = substr($route, 0, $route_query_position);
    }

    // If not an external URL, add the base url scheme.
    if (substr($route, 0, 4) != 'http') {
      $route = 'base://' . $route;
    }

    // Generate the final url.
    $url = Url::fromUri($route, [
      'query' => $query,
    ]);

    // Redirect.
    if ($url
      ->isExternal()) {
      $form_state
        ->setResponse(new TrustedRedirectResponse($url
        ->toUriString(), 302));
    }
    else {
      $form_state
        ->setRedirectUrl($url);
    }
  }
  else {
    $query['keys'] = $keys;
    if (count($filters)) {
      $query['f'] = $filters;
    }
    $form_state
      ->setRedirect($route, [], [
      'query' => $query,
    ]);
  }
}