View source
<?php
namespace Drupal\facets\Plugin\facets\url_processor;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Url;
use Drupal\facets\Event\QueryStringCreated;
use Drupal\facets\FacetInterface;
use Drupal\facets\UrlProcessor\UrlProcessorPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
class QueryString extends UrlProcessorPluginBase {
protected $urlAlias;
protected $eventDispatcher;
public function __construct(array $configuration, $plugin_id, $plugin_definition, Request $request, EntityTypeManagerInterface $entity_type_manager, EventDispatcherInterface $eventDispatcher) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $request, $entity_type_manager);
$this->eventDispatcher = $eventDispatcher;
$this
->initializeActiveFilters();
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('request_stack')
->getMasterRequest(), $container
->get('entity_type.manager'), $container
->get('event_dispatcher'));
}
public function buildUrls(FacetInterface $facet, array $results) {
if (empty($results)) {
return [];
}
$get_params = $this->request->query;
if ($get_params
->has('page')) {
$current_page = $get_params
->get('page');
$get_params
->remove('page');
}
$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 => $values) {
$values = array_filter($values, static function ($it) {
return $it !== NULL;
});
foreach ($values as $value) {
$original_filter_params[] = $this
->getUrlAliasByFacetId($facet_id, $facet
->getFacetSourceId()) . ":" . $value;
}
}
foreach ($results as &$result) {
$url = clone $requestUrl;
if ($children = $result
->getChildren()) {
$this
->buildUrls($facet, $children);
}
if ($result
->getRawValue() === NULL) {
$filter_string = NULL;
}
else {
$filter_string = $this->urlAlias . $this
->getSeparator() . $result
->getRawValue();
}
$result_get_params = clone $get_params;
$filter_params = $original_filter_params;
if ($result
->isActive()) {
foreach ($filter_params as $key => $filter_param) {
if ($filter_param == $filter_string) {
unset($filter_params[$key]);
}
}
if ($facet
->getUseHierarchy()) {
$id = $result
->getRawValue();
foreach ($facet
->getHierarchyInstance()
->getNestedChildIds($id) as $child_id) {
$filter_params = array_diff($filter_params, [
$this->urlAlias . $this
->getSeparator() . $child_id,
]);
}
if ($facet
->getEnableParentWhenChildGetsDisabled()) {
$parent_ids = $facet
->getHierarchyInstance()
->getParentIds($id);
if (isset($parent_ids[0]) && $parent_ids[0]) {
$child_ids = $facet
->getHierarchyInstance()
->getNestedChildIds($parent_ids[0]);
$active_sibling = FALSE;
if ($child_ids) {
foreach ($results as $result2) {
if ($result2
->isActive() && $result2
->getRawValue() != $id && in_array($result2
->getRawValue(), $child_ids)) {
$active_sibling = TRUE;
continue;
}
}
}
if (!$active_sibling) {
$filter_params[] = $this->urlAlias . $this
->getSeparator() . $parent_ids[0];
}
}
}
}
}
else {
if ($filter_string !== NULL) {
$filter_params[] = $filter_string;
}
$parents_and_child_ids = [];
if ($facet
->getUseHierarchy()) {
$parent_ids = $facet
->getHierarchyInstance()
->getParentIds($result
->getRawValue());
$child_ids = $facet
->getHierarchyInstance()
->getNestedChildIds($result
->getRawValue());
$parents_and_child_ids = array_merge($parent_ids, $child_ids);
if (!$facet
->getKeepHierarchyParentsActive()) {
foreach ($parents_and_child_ids as $id) {
$filter_params = array_diff($filter_params, [
$this->urlAlias . $this
->getSeparator() . $id,
]);
}
}
}
if ($facet
->getShowOnlyOneResult()) {
foreach ($results as $result2) {
if ($result2
->isActive()) {
$id = $result2
->getRawValue();
if (!in_array($id, $parents_and_child_ids)) {
$active_filter_string = $this->urlAlias . $this
->getSeparator() . $id;
foreach ($filter_params as $key2 => $filter_param2) {
if ($filter_param2 == $active_filter_string) {
unset($filter_params[$key2]);
}
}
}
}
}
}
}
$event = new QueryStringCreated($result_get_params, $filter_params, $result, $this->activeFilters, $facet);
$this->eventDispatcher
->dispatch(QueryStringCreated::NAME, $event);
$filter_params = $event
->getFilterParameters();
asort($filter_params, \SORT_NATURAL);
$result_get_params
->set($this->filterKey, array_values($filter_params));
if ($result_get_params
->all() !== [
$this->filterKey => [],
]) {
$new_url_params = $result_get_params
->all();
if (empty($new_url_params[$this->filterKey])) {
unset($new_url_params[$this->filterKey]);
}
unset($new_url_params['page']);
unset($new_url_params[MainContentViewSubscriber::WRAPPER_FORMAT]);
$url
->setOption('query', $new_url_params);
}
$result
->setUrl($url);
}
if (isset($current_page)) {
$get_params
->set('page', $current_page);
}
return $results;
}
protected function getRequestByFacetSourcePath($facet_source_path) {
$requestsByPath =& drupal_static(__CLASS__ . __FUNCTION__, []);
if (!$facet_source_path) {
return $this->request;
}
if (array_key_exists($facet_source_path, $requestsByPath)) {
return $requestsByPath[$facet_source_path];
}
$request = Request::create($facet_source_path);
$request->attributes
->set('_format', $this->request
->get('_format'));
$requestsByPath[$facet_source_path] = $request;
return $request;
}
protected function getUrlForRequest($facet_source_path, Request $request) {
$requestUrlsByPath =& drupal_static(__CLASS__ . __FUNCTION__, []);
if (array_key_exists($facet_source_path, $requestUrlsByPath)) {
return $requestUrlsByPath[$facet_source_path];
}
try {
$requestUrl = Url::createFromRequest($request);
} catch (ResourceNotFoundException $e) {
if (!$facet_source_path) {
throw $e;
}
$requestUrl = Url::fromUserInput($facet_source_path, [
'query' => [
'_format' => $this->request
->get('_format'),
],
]);
}
$requestUrl
->setOption('attributes', [
'rel' => 'nofollow',
]);
$requestUrlsByPath[$facet_source_path] = $requestUrl;
return $requestUrl;
}
protected function initializeActiveFilters() {
$url_parameters = $this->request->query;
$active_params = $url_parameters
->get($this->filterKey, [], TRUE);
$facet_source_id = $this->configuration['facet']
->getFacetSourceId();
if (!is_array($active_params)) {
return;
}
foreach ($active_params as $param) {
$explosion = explode($this
->getSeparator(), $param);
$url_alias = array_shift($explosion);
$facet_id = $this
->getFacetIdByUrlAlias($url_alias, $facet_source_id);
$value = '';
while (count($explosion) > 0) {
$value .= array_shift($explosion);
if (count($explosion) > 0) {
$value .= $this
->getSeparator();
}
}
if (!isset($this->activeFilters[$facet_id])) {
$this->activeFilters[$facet_id] = [
$value,
];
}
else {
$this->activeFilters[$facet_id][] = $value;
}
}
}
protected function getFacetIdByUrlAlias($url_alias, $facet_source_id) {
$mapping =& drupal_static(__FUNCTION__);
if (!isset($mapping[$facet_source_id][$url_alias])) {
$storage = $this->entityTypeManager
->getStorage('facets_facet');
$facet = current($storage
->loadByProperties([
'url_alias' => $url_alias,
'facet_source_id' => $facet_source_id,
]));
if (!$facet) {
return NULL;
}
$mapping[$facet_source_id][$url_alias] = $facet
->id();
}
return $mapping[$facet_source_id][$url_alias];
}
protected function getUrlAliasByFacetId($facet_id, $facet_source_id) {
$mapping =& drupal_static(__FUNCTION__);
if (!isset($mapping[$facet_source_id][$facet_id])) {
$storage = $this->entityTypeManager
->getStorage('facets_facet');
$facet = current($storage
->loadByProperties([
'id' => $facet_id,
'facet_source_id' => $facet_source_id,
]));
if (!$facet) {
return FALSE;
}
$mapping[$facet_source_id][$facet_id] = $facet
->getUrlAlias();
}
return $mapping[$facet_source_id][$facet_id];
}
}