You are here

public function JsonApiQueryString::buildUrls in JSON:API Search API 8

Adds urls to the results.

Parameters

\Drupal\facets\FacetInterface $facet: The facet.

\Drupal\facets\Result\ResultInterface[] $results: An array of results.

Return value

\Drupal\facets\Result\ResultInterface[] An array of results with added urls.

Overrides QueryString::buildUrls

File

modules/jsonapi_search_api_facets/src/Plugin/facets/url_processor/JsonApiQueryString.php, line 108

Class

JsonApiQueryString
Query string URL processor.

Namespace

Drupal\jsonapi_search_api_facets\Plugin\facets\url_processor

Code

public function buildUrls(FacetInterface $facet, array $results) {

  // No results are found for this facet, so don't try to create urls.
  if (empty($results)) {
    return [];
  }
  $facet_source = $facet
    ->getFacetSource();

  // This URL processor only works with JSON:API Facets.
  if (!$facet_source instanceof JsonApiFacets) {
    return [];
  }

  // First get the current list of get parameters.
  $get_params = $this->request->query;

  // When adding/removing a filter the number of pages may have changed,
  // possibly resulting in an invalid page parameter.
  if ($get_params
    ->has(OffsetPage::KEY_NAME)) {
    $page_params = $get_params
      ->get(OffsetPage::KEY_NAME);
    unset($page_params[OffsetPage::OFFSET_KEY]);
    $get_params
      ->set(OffsetPage::KEY_NAME, $page_params);
  }

  // Set the url alias from the facet object.
  $this->urlAlias = $facet
    ->getUrlAlias();
  $facet_source_path = $facet
    ->getFacetSource()
    ->getPath();
  $request = $this
    ->getRequestByFacetSourcePath($facet_source_path);
  $requestUrl = $this
    ->getUrlForRequest($facet_source_path, $request);
  $original_filter_params = [];
  foreach ($this
    ->getActiveFilters() as $facet_id => $value) {
    $facet_url_alias = $this
      ->getUrlAliasByFacetId($facet_id, $facet
      ->getFacetSourceId());
    $this
      ->addToFilter($facet_url_alias, $value, $original_filter_params);
  }
  foreach ($results as &$result) {

    // Reset the URL for each result.
    $url = clone $requestUrl;

    // Sets the url for children.
    if ($children = $result
      ->getChildren()) {
      $this
        ->buildUrls($facet, $children);
    }
    $filter_string = $result
      ->getRawValue();
    $result_get_params = clone $get_params;
    $filter_params = $original_filter_params;
    if ($filter_string !== NULL) {
      $this
        ->addToFilter($this->urlAlias, $filter_string, $filter_params);
    }
    if ($result
      ->isActive()) {

      // Facets' itself does not allow hierarchical settings to be configured
      // on anything that's not a view as of current. With that in mind this
      // code -will- still operate like the parent it inherits from if the
      // bogus check is bypassed.
      // @see: https://www.drupal.org/project/facets/issues/3157720
      if ($facet
        ->getEnableParentWhenChildGetsDisabled() && $facet
        ->getUseHierarchy()) {

        // Enable parent id again if exists.
        $parent_ids = $facet
          ->getHierarchyInstance()
          ->getParentIds($result
          ->getRawValue());
        if (isset($parent_ids[0]) && $parent_ids[0]) {

          // Get the parents children.
          $child_ids = $facet
            ->getHierarchyInstance()
            ->getNestedChildIds($parent_ids[0]);

          // Check if there are active siblings.
          $active_sibling = FALSE;
          if ($child_ids) {
            foreach ($results as $result2) {
              if ($result2
                ->isActive() && $result2
                ->getRawValue() != $result
                ->getRawValue() && in_array($result2
                ->getRawValue(), $child_ids)) {
                $active_sibling = TRUE;
                continue;
              }
            }
          }
          if (!$active_sibling) {
            $this
              ->addToFilter($this->urlAlias, $parent_ids[0], $filter_params);
          }
        }
      }
    }
    else {
      if ($facet
        ->getUseHierarchy()) {

        // If hierarchy is active, unset parent trail and every child when
        // building the enable-link to ensure those are not enabled anymore.
        $parent_ids = $facet
          ->getHierarchyInstance()
          ->getParentIds($result
          ->getRawValue());
        $child_ids = $facet
          ->getHierarchyInstance()
          ->getNestedChildIds($result
          ->getRawValue());
        $parents_and_child_ids = array_merge($parent_ids, $child_ids);
        foreach ($parents_and_child_ids as $id) {
          $filter_params = array_diff($filter_params, [
            $id,
          ]);
        }
      }

      // Exclude currently active results from the filter params if we are in
      // the show_only_one_result mode.
      if ($facet
        ->getShowOnlyOneResult()) {
        foreach ($results as $result2) {
          if ($result2
            ->isActive()) {
            $active_filter_string = $result2
              ->getRawValue();
            foreach ($filter_params as $filter_key => $filter_values) {
              if (in_array($active_filter_string, $filter_values)) {
                $filter_params[$filter_key] = array_diff($filter_values, [
                  $active_filter_string,
                ]);
              }
            }
          }
        }
      }
    }

    // Rewrite into JSON:API style filters now, start by removing all
    // existing filters as they will be re-created.
    $result_get_params
      ->remove('filter');
    $result_get_params
      ->set('filter', $this->originalFilters);
    foreach ($filter_params as $filter_path => $values) {
      $existing_params = $result_get_params
        ->all();

      // Simple facets can be done.
      if (count($values) === 1) {
        $value = reset($values);
        $params = array_merge_recursive($existing_params, [
          'filter' => [
            $filter_path => $value,
          ],
        ]);
      }
      else {

        // Build up "fancy" facets, handle other ops (NOT)?.
        $filter_key = strtr('!field-facet', [
          '!field' => $filter_path,
        ]);
        $params = array_merge_recursive($existing_params, [
          'filter' => [
            $filter_key => [
              'condition' => [
                'path' => $filter_path,
                'operator' => 'IN',
                'value' => [],
              ],
            ],
          ],
        ]);
        foreach ($values as $value) {
          $params['filter'][$filter_key]['condition']['value'][] = $value;
        }
      }
      $result_get_params
        ->add($params);
    }
    if ($result_get_params
      ->all() !== [
      $this->filterKey => [],
    ]) {
      $new_url_params = $result_get_params
        ->all();

      // Set the new url parameters.
      $url
        ->setOption('query', $new_url_params);
    }
    $result
      ->setUrl($url);
  }
  return $results;
}