You are here

function template_preprocess_bef_links in Better Exposed Filters 8.4

Same name and namespace in other branches
  1. 8.5 includes/better_exposed_filters.theme.inc \template_preprocess_bef_links()
  2. 8.3 better_exposed_filters.module \template_preprocess_bef_links()

Prepares variables for bef-links template.

Default template: bef-links.html.twig.

Parameters

array $variables: An associative array containing:

  • element: An associative array containing the exposed form element.

File

includes/better_exposed_filters.theme.inc, line 183
Theme hooks, preprocessor, and suggestions.

Code

function template_preprocess_bef_links(array &$variables) {

  // Collect some variables before we start tweaking the element.
  $element =& $variables['element'];
  $options = $element['#options'];
  $name = $element['#name'];

  // Set element name.
  $variables['attributes']['name'] = $name;

  // Get the query string arguments from the current request.
  $existing_query = \Drupal::service('request_stack')
    ->getCurrentRequest()->query
    ->all();

  // Remove page parameter from query.
  unset($existing_query['page']);

  // Store selected values.
  $selectedValues = $element['#value'];
  if (!is_array($selectedValues)) {
    $selectedValues = [
      $selectedValues,
    ];
  }
  $variables['links'] = [];
  foreach ($options as $optionValue => $optionLabel) {

    // Build a new Url object for each link since the query string changes with
    // each option.

    /** @var Drupal\Core\Url $url */
    $url = clone $element['#bef_path'];

    // Allow visitors to toggle a filter setting on and off. This is not as
    // simple as setOptions('foo', '') as that still leaves an entry which is
    // rendered rather than removing the entry from the query string altogether.
    // Calling $url->setOption() still leaves a value behind. Instead we work
    // with the entire options array and remove items from it as needed.
    $urlOptions = $url
      ->getOptions();
    if (isset($element['#multiple']) && $element['#multiple']) {
      $newQuery = isset($existing_query[$name]) ? $existing_query[$name] : [];
      if (in_array($optionValue, $selectedValues)) {

        // Allow users to toggle an option using the same link.
        $newQuery = array_filter($newQuery, function ($value) use ($selectedValues) {
          return !in_array($value, $selectedValues);
        });
      }
      else {
        $newQuery[] = $optionValue;
      }
      if (empty($newQuery)) {
        unset($urlOptions['query'][$name]);
      }
      else {
        $urlOptions['query'][$name] = $newQuery;
      }
    }
    else {
      if (strval($optionValue) === $element['#value']) {

        // Allow toggle link functionality -- click the same link to turn an
        // option on or off.
        $newQuery = $existing_query;
        unset($newQuery[$name]);
        if (empty($newQuery)) {

          // Remove the query string completely.
          unset($urlOptions['query']);
        }
        else {
          $urlOptions['query'] = $newQuery;
        }
      }
      else {
        $urlOptions['query'] = $existing_query;
        $urlOptions['query'][$name] = $optionValue;
      }
    }

    // Add our updated options to the Url object.
    $url
      ->setOptions($urlOptions);

    // Provide the Twig template with an array of links.
    $variables['links'][$optionValue] = [
      '#attributes' => [
        'id' => Html::getUniqueId('edit-' . implode('-', [
          $name,
          $optionValue,
        ])),
        'name' => $name . '[' . $optionValue . ']',
        'class' => [
          'bef-link',
        ],
      ],
      '#type' => 'link',
      '#title' => $optionLabel,
      '#url' => $url,
    ];

    /*
     * @see https://stackoverflow.com/questions/13846769/php-in-array-0-value
     */
    if (in_array(strval($optionValue), $selectedValues)) {
      $variables['links'][$optionValue]['#attributes']['class'][] = 'bef-link--selected';
    }
  }

  // Handle nested links. But first add the links as children to the element
  // for consistent processing between checkboxes/radio buttons and links.
  $variables['element'] = array_replace($variables['element'], $variables['links']);
  $variables['children'] = Element::children($variables['element']);
  if (!empty($variables['element']['#bef_nested'])) {
    _bef_preprocess_nested_elements($variables);
  }
}