Skip to content
Snippets Groups Projects
Commit 2f438310 authored by Dalibor Matura's avatar Dalibor Matura Committed by eduardo morales alberti
Browse files

Issue #3052574 by dabbor, Mschudders, czigor, ctrlADel, matiasmiranda,...

Issue #3052574 by dabbor, Mschudders, czigor, ctrlADel, matiasmiranda, raman.b, MPetkovFFW, dealancer, allaprishchepa, lukasss, Oleksiy, amoebanath, KarlShea, balis_m, silajit, yuraosn, p-neyens: Facets with AJAX not working in most of situations
parent 3c3fe248
No related branches found
No related tags found
No related merge requests found
diff --git a/facets.module b/facets.module
index 6c04f21..7b43909 100644
--- a/facets.module
+++ b/facets.module
@@ -124,20 +124,27 @@ function facets_entity_presave(EntityInterface $entity) {
/**
* Implements hook_preprocess_block().
*
- * Adds a class for the widget to the facet block to allow for more specific
- * styling.
+ * Adds some classes for hiding empty blocks, working ajax, and more.
*/
function facets_preprocess_block(&$variables) {
if ($variables['configuration']['provider'] == 'facets') {
// Hide the block if it's empty.
- if (!empty($variables['elements']['content'][0]['#attributes']['class']) && in_array('facet-hidden', $variables['elements']['content'][0]['#attributes']['class'])) {
- // Add the Drupal class for hiding this for everyone, including screen
- // readers. See hidden.module.css in the core system module.
- $variables['attributes']['class'][] = 'hidden';
+ if (!empty($variables['content']['facet_block']['#attributes'])) {
+ $attributes = $variables['content']['facet_block']['#attributes'];
+ if (isset($attributes['class'])) {
+ if (in_array('hidden', $attributes['class'])) {
+ // Add the Drupal class for hiding this for everyone, including screen
+ // readers. See hidden.module.css in the core system module.
+ $variables['attributes']['class'][] = 'hidden';
+ }
+ }
}
+
if (!empty($variables['derivative_plugin_id'])) {
$facet = Facet::load($variables['derivative_plugin_id']);
$variables['attributes']['class'][] = 'block-facet--' . Html::cleanCssIdentifier($facet->getWidget()['type']);
+ // For use ajax.
+ $variables['attributes']['data-drupal-block-facet-id'] = $facet->id();
}
}
}
diff --git a/js/facets-views-ajax.js b/js/facets-views-ajax.js
index e0e4f2c..0af8c8e 100644
--- a/js/facets-views-ajax.js
+++ b/js/facets-views-ajax.js
@@ -37,17 +37,72 @@
return;
}
- // Update view on summary block click.
- if (updateFacetsSummaryBlock() && (facetId === 'facets_summary_ajax')) {
- $('[data-drupal-facets-summary-id=' + facetSettings.facets_summary_id + ']').children('ul').children('li').once().click(function (e) {
- e.preventDefault();
- var facetLink = $(this).find('a');
- updateFacetsView(facetLink.attr('href'), current_dom_id, view_path);
- });
+ // Update view on range slider stop event
+ if (typeof settings.facets !== "undefined" && settings.facets.sliders && settings.facets.sliders[facetId]) {
+ settings.facets.sliders[facetId].stop = function (e, ui) {
+ var href = settings.facets.sliders[facetId].url.replace('__range_slider_min__', ui.values[0]).replace('__range_slider_max__', ui.values[1]);
+
+ // Update facet query params on the request.
+ var currentHref = window.location.href;
+ var currentQueryParams = Drupal.Views.parseQueryString(currentHref);
+ var newQueryParams = Drupal.Views.parseQueryString(href);
+
+ var queryParams = {};
+ var facetPositions = [];
+ var fCount = 0;
+ var value = '';
+ var facetKey = '';
+ for (var paramName in currentQueryParams) {
+ if (paramName.substr(0, 1) === 'f') {
+ value = currentQueryParams[paramName];
+ // Store the facet position so we can override it later.
+ facetKey = value.substr(0, value.indexOf(':'));
+ facetPositions[facetKey] = fCount;
+ queryParams['f[' + fCount + ']'] = value;
+ fCount++;
+ }
+ else {
+ queryParams[paramName] = currentQueryParams[paramName];
+ }
+ }
+
+ var paramKey = '';
+ for (let paramName in newQueryParams) {
+ if (paramName.substr(0, 1) === 'f') {
+ value = newQueryParams[paramName];
+ // replace
+ facetKey = value.substr(0, value.indexOf(':'));
+ if (typeof facetPositions[facetKey] !== 'undefined') {
+ paramKey = 'f[' + facetPositions[facetKey] + ']';
+ }
+ else {
+ paramKey = 'f[' + fCount + ']';
+ fCount++;
+ }
+ queryParams[paramKey] = newQueryParams[paramName];
+ }
+ else {
+ queryParams[paramName] = newQueryParams[paramName];
+ }
+ }
+
+ href = '/' + Drupal.Views.getPath(href) + '?' + $.param(queryParams);
+
+ updateFacetsView(href, current_dom_id, view_path);
+ };
+ }
+ else if (facetId == 'facets_summary_ajax_summary' || facetId == 'facets_summary_ajax_summary_count') {
+ if (updateFacetsSummaryBlock()) {
+ $('[data-drupal-facets-summary-id=' + facetSettings.facets_summary_id + ']').children('ul').children('li').once().click(function (e) {
+ e.preventDefault();
+ var facetLink = $(this).find('a');
+ updateFacetsView(facetLink.attr('href'), current_dom_id, view_path);
+ });
+ }
}
// Update view on facet item click.
else {
- $('[data-drupal-facet-id=' + facetId + ']').each(function (index, facet_item) {
+ $('[data-drupal-facet-id |= ' + facetId + ']').each(function (index, facet_item) {
if ($(facet_item).hasClass('js-facets-widget')) {
$(facet_item).unbind('facets_filter.facets');
$(facet_item).on('facets_filter.facets', function (event, url) {
@@ -104,8 +159,8 @@
var facets_blocks = facetsBlocks();
// Remove All Range Input Form Facet Blocks from being updated.
- if(settings.facets && settings.facets.rangeInput) {
- $.each(settings.facets.rangeInput, function (index, value){
+ if (settings.facets && settings.facets.rangeInput) {
+ $.each(settings.facets.rangeInput, function (index, value) {
delete facets_blocks[value.facetId];
});
}
@@ -121,17 +176,17 @@
// Update facets summary block.
if (updateFacetsSummaryBlock()) {
- var facet_summary_wrapper_id = $('[data-drupal-facets-summary-id=' + settings.facets_views_ajax.facets_summary_ajax.facets_summary_id + ']').attr('id');
- var facet_summary_block_id = '';
- if (facet_summary_wrapper_id.indexOf('--') !== -1) {
- facet_summary_block_id = facet_summary_wrapper_id.substring(0, facet_summary_wrapper_id.indexOf('--')).replace('block-', '');
- }
- else {
- facet_summary_block_id = facet_summary_wrapper_id.replace('block-', '');
- }
facet_settings.submit.update_summary_block = true;
- facet_settings.submit.facet_summary_block_id = facet_summary_block_id;
- facet_settings.submit.facet_summary_wrapper_id = settings.facets_views_ajax.facets_summary_ajax.facets_summary_id;
+ facet_settings.submit.facet_summary_plugin_ids = {};
+ let summary_selector = '[data-drupal-facets-summary-id=' + settings.facets_views_ajax.facets_summary_ajax_summary.facets_summary_id + ']';
+ if (settings.facets_views_ajax.facets_summary_ajax_summary_count !== undefined) {
+ summary_selector += ', [data-drupal-facets-summary-id=' + settings.facets_views_ajax.facets_summary_ajax_summary_count.facets_summary_id + ']';
+ }
+ $(summary_selector).each(function (index, summaryWrapper) {
+ let summaryPluginId = $(summaryWrapper).attr('data-drupal-facets-summary-plugin-id');
+ let summaryPluginIdWrapper = $(summaryWrapper).attr('id');
+ facet_settings.submit.facet_summary_plugin_ids[summaryPluginIdWrapper] = summaryPluginId;
+ });
}
Drupal.ajax(facet_settings).execute();
@@ -143,7 +198,7 @@
var settings = drupalSettings;
var update_summary = false;
- if (settings.facets_views_ajax.facets_summary_ajax) {
+ if (settings.facets_views_ajax.facets_summary_ajax_summary || settings.facets_views_ajax.facets_summary_ajax_summary_count) {
update_summary = true;
}
@@ -162,8 +217,8 @@
return v.slice(block_id_start.length, v.length);
}
}).join();
- var block_selector = '#' + $(this).attr('id');
- facets_blocks[block_id] = block_selector;
+ var block_selector = $(this).attr('id');
+ facets_blocks[block_selector] = block_id;
});
return facets_blocks;
@@ -204,12 +259,12 @@
}
// Helper function to add exposed form data to facets url
- var addExposedFiltersToFacetsUrl = function(href, view_name, view_display_id) {
+ var addExposedFiltersToFacetsUrl = function (href, view_name, view_display_id) {
var $exposed_form = $('form#views-exposed-form-' + view_name.replace(/_/g, '-') + '-' + view_display_id.replace(/_/g, '-'));
var params = Drupal.Views.parseQueryString(href);
- $.each($exposed_form.serializeArray(), function() {
+ $.each($exposed_form.serializeArray(), function () {
params[this.name] = this.value;
});
diff --git a/modules/facets_summary/facets_summary.module b/modules/facets_summary/facets_summary.module
index 6720862..af2dc3f 100644
--- a/modules/facets_summary/facets_summary.module
+++ b/modules/facets_summary/facets_summary.module
@@ -98,3 +98,26 @@ function facets_summary_theme_suggestions_facets_summary_item_list(array $variab
function facets_summary_preprocess_facets_summary_item_list(array &$variables) {
template_preprocess_item_list($variables);
}
+
+/**
+ * Implements hook_preprocess_block().
+ *
+ * Adds some classes for hiding empty blocks, working ajax, and more.
+ */
+function facets_summary_preprocess_block(&$variables) {
+ if ($variables['configuration']['provider'] == 'facets_summary') {
+ // Hide the block if it's empty.
+ if (!empty($variables['content']['facets_summary']['#attributes'])) {
+ $attributes = $variables['content']['facets_summary']['#attributes'];
+ if (isset($attributes['class'])) {
+ if (in_array('hidden', $attributes['class'])) {
+ // Add the Drupal class for hiding this for everyone, including screen
+ // readers. See hidden.module.css in the core system module.
+ $variables['attributes']['class'][] = 'hidden';
+ }
+ }
+ }
+ // For use ajax.
+ $variables['attributes']['data-drupal-block-facet-summary-id'] = $variables['configuration']['id'];
+ }
+}
diff --git a/modules/facets_summary/facets_summary.services.yml b/modules/facets_summary/facets_summary.services.yml
index ba1a6f5..bd8f14e 100644
--- a/modules/facets_summary/facets_summary.services.yml
+++ b/modules/facets_summary/facets_summary.services.yml
@@ -8,6 +8,8 @@ services:
- '@plugin.manager.facets.facet_source'
- '@plugin.manager.facets_summary.processor'
- '@facets.manager'
+ - '@plugin.manager.facets.url_processor'
+ - '@facets.utility.url_generator'
facets_summary.search_api_subscriber:
class: Drupal\facets_summary\EventSubscriber\SearchApiSubscriber
arguments: ['@entity_type.manager']
diff --git a/modules/facets_summary/src/FacetsSummaryManager/DefaultFacetsSummaryManager.php b/modules/facets_summary/src/FacetsSummaryManager/DefaultFacetsSummaryManager.php
index 105c438..0adafc0 100644
--- a/modules/facets_summary/src/FacetsSummaryManager/DefaultFacetsSummaryManager.php
+++ b/modules/facets_summary/src/FacetsSummaryManager/DefaultFacetsSummaryManager.php
@@ -4,13 +4,17 @@ namespace Drupal\facets_summary\FacetsSummaryManager;
use Drupal\Core\Link;
use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\Url;
use Drupal\facets\Exception\InvalidProcessorException;
use Drupal\facets\FacetManager\DefaultFacetManager;
use Drupal\facets\FacetSource\FacetSourcePluginManager;
+use Drupal\facets\Result\Result;
use Drupal\facets_summary\Processor\BuildProcessorInterface;
use Drupal\facets_summary\Processor\ProcessorInterface;
use Drupal\facets_summary\Processor\ProcessorPluginManager;
use Drupal\facets_summary\FacetsSummaryInterface;
+use Drupal\facets\UrlProcessor\UrlProcessorPluginManager;
+use Drupal\facets\Utility\FacetsUrlGenerator;
/**
* The facet summary manager.
@@ -45,6 +49,20 @@ class DefaultFacetsSummaryManager {
*/
protected $facetManager;
+ /**
+ * The url processor plugin manager.
+ *
+ * @var \Drupal\facets\UrlProcessor\UrlProcessorPluginManager
+ */
+ protected $urlProcessorPluginManager;
+
+ /**
+ * The facets url generator.
+ *
+ * @var \Drupal\facets\Utility\FacetsUrlGenerator
+ */
+ protected $facetsUrlGenerator;
+
/**
* Constructs a new instance of the DefaultFacetManager.
*
@@ -54,11 +72,17 @@ class DefaultFacetsSummaryManager {
* The facets summary processor plugin manager.
* @param \Drupal\facets\FacetManager\DefaultFacetManager $facet_manager
* The facet manager service.
+ * @param \Drupal\facets\UrlProcessor\UrlProcessorPluginManager $url_processor_plugin_manager
+ * The url processor plugin manager.
+ * @param \Drupal\facets\Utility\FacetsUrlGenerator $facets_url_generator
+ * The facets url generator.
*/
- public function __construct(FacetSourcePluginManager $facet_source_manager, ProcessorPluginManager $processor_plugin_manager, DefaultFacetManager $facet_manager) {
+ public function __construct(FacetSourcePluginManager $facet_source_manager, ProcessorPluginManager $processor_plugin_manager, DefaultFacetManager $facet_manager, UrlProcessorPluginManager $url_processor_plugin_manager, FacetsUrlGenerator $facets_url_generator) {
$this->facetSourcePluginManager = $facet_source_manager;
$this->processorPluginManager = $processor_plugin_manager;
$this->facetManager = $facet_manager;
+ $this->urlProcessorPluginManager = $url_processor_plugin_manager;
+ $this->facetsUrlGenerator = $facets_url_generator;
}
/**
@@ -117,16 +141,48 @@ class DefaultFacetsSummaryManager {
'#theme' => 'facets_summary_item_list',
'#facet_summary_id' => $facets_summary->id(),
'#attributes' => [
- 'data-drupal-facets-summary-id' => $facets_summary->id(),
+ 'class' => ['facet-summary__items'],
],
];
$results = [];
foreach ($facets as $facet) {
- $show_count = $facets_config[$facet->id()]['show_count'];
- $results = array_merge($results, $this->buildResultTree($show_count, $facet->getResults()));
+ $enabled_processors = $facet->getProcessors(TRUE);
+ if (isset($enabled_processors["range_slider"])) {
+ $active_values = $facet->getActiveItems();
+ if ($active_values) {
+ $min = $active_values[0][0];
+ $max = $active_values[0][1];
+ $url_processor = $this->urlProcessorPluginManager->createInstance($facet->getFacetSourceConfig()->getUrlProcessorName(), ['facet' => $facet]);
+ $active_filters = $url_processor->getActiveFilters();
+ if (isset($active_filters[''])) {
+ unset($active_filters['']);
+ }
+ unset($active_filters[$facet->id()]);
+ // Only if there are still active filters, use url generator.
+ if ($active_filters) {
+ $url = $this->facetsUrlGenerator->getUrl($active_filters, FALSE);
+ }
+ else {
+ // @todo Keep non-facet related get params.
+ $url = Url::fromUserInput($facets_summary->getFacetSource()->getPath());
+ }
+ $result_without_current_rangeslider = new Result($facet, "(min:$min,max:$max)", " $min - $max", 1);
+ $result_without_current_rangeslider->setActiveState(TRUE);
+ $result_without_current_rangeslider->setUrl($url);
+ $results = array_merge($results, $this->buildResultTree(FALSE, [$result_without_current_rangeslider]));
+ }
+ }
+ else {
+ $show_count = $facets_config[$facet->id()]['show_count'];
+ $results = array_merge($results, $this->buildResultTree($show_count, $facet->getResults()));
+ }
+
+ }
+
+ if ($results) {
+ $build['#items'] = $results;
}
- $build['#items'] = $results;
// Allow our Facets Summary processors to alter the build array in a
// configured order.
diff --git a/modules/facets_summary/src/Plugin/Block/FacetsSummaryBlock.php b/modules/facets_summary/src/Plugin/Block/FacetsSummaryBlock.php
index 5b9255a..4ace992 100644
--- a/modules/facets_summary/src/Plugin/Block/FacetsSummaryBlock.php
+++ b/modules/facets_summary/src/Plugin/Block/FacetsSummaryBlock.php
@@ -6,6 +6,7 @@ use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\UncacheableDependencyTrait;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Url;
+use Drupal\Component\Utility\Html;
use Drupal\facets_summary\Entity\FacetsSummary;
use Drupal\facets_summary\FacetsSummaryBlockInterface;
use Drupal\facets_summary\FacetsSummaryManager\DefaultFacetsSummaryManager;
@@ -88,25 +89,46 @@ class FacetsSummaryBlock extends BlockBase implements FacetsSummaryBlockInterfac
$facets_summary = $this->getEntity();
// Let the facet_manager build the facets.
- $build = $this->facetsSummaryManager->build($facets_summary);
+ $build = [];
- // Add contextual links only when we have results.
- if (!empty($build)) {
- $build['#contextual_links']['facets_summary'] = [
- 'route_parameters' => ['facets_summary' => $facets_summary->id()],
+ // Let the facet_manager build the facets.
+ $summary_build = $this->facetsSummaryManager->build($facets_summary);
+
+ if ($summary_build) {
+ $build = [
+ 'facets_summary' => [
+ '#type' => 'container',
+ '#contextual_links' => [
+ 'facets_summary' => [
+ 'route_parameters' => ['facets_summary' => $facets_summary->id()],
+ ],
+ ],
+ '#attributes' => [
+ 'data-drupal-facets-summary-id' => $facets_summary->id(),
+ 'data-drupal-facets-summary-plugin-id' => $this->getPluginId(),
+ 'id' => Html::getUniqueId(str_replace(':', '-', $this->getPluginId())),
+ 'class' => [
+ 'facets-summary-block__wrapper',
+ ],
+ ],
+ 'summary_build' => $summary_build,
+ ],
];
- }
- /** @var \Drupal\views\ViewExecutable $view */
- if ($view = $facets_summary->getFacetSource()->getViewsDisplay()) {
- $build['#attached']['drupalSettings']['facets_views_ajax'] = [
- 'facets_summary_ajax' => [
+ // Hidden empty result.
+ if (!isset($summary_build['#items']) && !isset($summary_build['#message'])) {
+ $build['facets_summary']['#attributes']['class'][] = 'hidden';
+ }
+
+ /** @var \Drupal\views\ViewExecutable $view */
+ if ($view = $facets_summary->getFacetSource()->getViewsDisplay()) {
+ $build['#attached']['drupalSettings']['facets_views_ajax']['facets_summary_ajax_' . $facets_summary->id()] = [
'facets_summary_id' => $facets_summary->id(),
'view_id' => $view->id(),
'current_display_id' => $view->current_display,
'ajax_path' => Url::fromRoute('views.ajax')->toString(),
- ],
- ];
+ ];
+ }
}
return $build;
diff --git a/src/Controller/FacetBlockAjaxController.php b/src/Controller/FacetBlockAjaxController.php
index d1d446d..9b2cf1a 100644
--- a/src/Controller/FacetBlockAjaxController.php
+++ b/src/Controller/FacetBlockAjaxController.php
@@ -5,10 +5,10 @@ namespace Drupal\facets\Controller;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\ReplaceCommand;
+use Drupal\Core\Block\BlockManager;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\PathProcessor\PathProcessorManager;
-use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Routing\CurrentRouteMatch;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
@@ -28,13 +28,6 @@ class FacetBlockAjaxController extends ControllerBase {
*/
protected $storage;
- /**
- * The renderer.
- *
- * @var \Drupal\Core\Render\RendererInterface
- */
- protected $renderer;
-
/**
* The current path.
*
@@ -63,11 +56,16 @@ class FacetBlockAjaxController extends ControllerBase {
*/
protected $currentRouteMatch;
+ /**
+ * The block manager service.
+ *
+ * @var \Drupal\Core\Block\BlockManager
+ */
+ protected $blockManager;
+
/**
* Constructs a FacetBlockAjaxController object.
*
- * @param \Drupal\Core\Render\RendererInterface $renderer
- * The renderer service.
* @param \Drupal\Core\Path\CurrentPathStack $currentPath
* The current path service.
* @param \Symfony\Component\Routing\RouterInterface $router
@@ -76,14 +74,16 @@ class FacetBlockAjaxController extends ControllerBase {
* The path processor manager.
* @param \Drupal\Core\Routing\CurrentRouteMatch $currentRouteMatch
* The current route match service.
+ * @param \Drupal\Core\Block\BlockManager $blockManager
+ * The block manager service.
*/
- public function __construct(RendererInterface $renderer, CurrentPathStack $currentPath, RouterInterface $router, PathProcessorManager $pathProcessor, CurrentRouteMatch $currentRouteMatch) {
+ public function __construct(CurrentPathStack $currentPath, RouterInterface $router, PathProcessorManager $pathProcessor, CurrentRouteMatch $currentRouteMatch, BlockManager $blockManager) {
$this->storage = $this->entityTypeManager()->getStorage('block');
- $this->renderer = $renderer;
$this->currentPath = $currentPath;
$this->router = $router;
$this->pathProcessor = $pathProcessor;
$this->currentRouteMatch = $currentRouteMatch;
+ $this->blockManager = $blockManager;
}
/**
@@ -91,11 +91,11 @@ class FacetBlockAjaxController extends ControllerBase {
*/
public static function create(ContainerInterface $container) {
return new static(
- $container->get('renderer'),
$container->get('path.current'),
$container->get('router'),
$container->get('path_processor_manager'),
- $container->get('current_route_match')
+ $container->get('current_route_match'),
+ $container->get('plugin.manager.block')
);
}
@@ -122,9 +122,6 @@ class FacetBlockAjaxController extends ControllerBase {
throw new NotFoundHttpException('No facet link or facet blocks found.');
}
- // Make sure we are not updating blocks multiple times.
- $facets_blocks = array_unique($facets_blocks);
-
$new_request = Request::create($path);
$request_stack = new RequestStack();
$processed = $this->pathProcessor->processInbound($path, $new_request);
@@ -136,40 +133,56 @@ class FacetBlockAjaxController extends ControllerBase {
$container = \Drupal::getContainer();
$container->set('request_stack', $request_stack);
- $active_facet = $request->request->get('active_facet');
-
- // Build the facets blocks found for the current request and update.
- foreach ($facets_blocks as $block_id => $block_selector) {
- $block_entity = $this->storage->load($block_id);
-
- if ($block_entity) {
- // Render a block, then add it to the response as a replace command.
- $block_view = $this->entityTypeManager
- ->getViewBuilder('block')
- ->view($block_entity);
-
- $block_view = (string) $this->renderer->renderPlain($block_view);
- $response->addCommand(new ReplaceCommand($block_selector, $block_view));
+ foreach ($facets_blocks as $block_selector => $block_id) {
+ // Facet block render array.
+ $block_view = NULL;
+ // Re prepare from css standarts.
+ $block_id = str_replace(['--', '-'], [':', '_'], $block_id);
+
+ // @todo We should not create an instance if we have already created one.
+ $block_instance = $this->blockManager->createInstance($block_id);
+ if ($block_instance) {
+ $block_view = $block_instance->build();
+ if ($block_view) {
+ // Replace content current ID selector.
+ $response->addCommand(new ReplaceCommand('#' . $block_selector, $block_view));
+ // Hide or show block.
+ $facet_id = explode(':', $block_id)[1];
+ $hide_show_selector = '[data-drupal-block-facet-id = "' . $facet_id . '"]';
+ if (!empty($block_view['facet_block']['#attributes']['class']) && in_array('hidden', $block_view['facet_block']['#attributes']['class'])) {
+ $response->addCommand(new InvokeCommand($hide_show_selector, 'addClass', ['hidden']));
+ }
+ else {
+ $response->addCommand(new InvokeCommand($hide_show_selector, 'removeClass', ['hidden']));
+ }
+ }
}
}
- $response->addCommand(new InvokeCommand('[data-block-plugin-id="' . $active_facet . '"]', 'addClass', ['facet-active']));
-
// Update filter summary block.
$update_summary_block = $request->request->get('update_summary_block');
if ($update_summary_block) {
- $facet_summary_block_id = $request->request->get('facet_summary_block_id');
- $facet_summary_wrapper_id = $request->request->get('facet_summary_wrapper_id');
- $facet_summary_block_id = str_replace('-', '_', $facet_summary_block_id);
-
- if ($facet_summary_block_id) {
- $block_entity = $this->storage->load($facet_summary_block_id);
- $block_view = $this->entityTypeManager
- ->getViewBuilder('block')
- ->view($block_entity);
- $block_view = (string) $this->renderer->renderPlain($block_view);
-
- $response->addCommand(new ReplaceCommand('[data-drupal-facets-summary-id=' . $facet_summary_wrapper_id . ']', $block_view));
+ $facet_summary_plugin_ids = $request->request->get('facet_summary_plugin_ids');
+ foreach ($facet_summary_plugin_ids as $block_selector => $summary_plugin_id) {
+ // Facet summary block render array.
+ $block_view = NULL;
+ // @todo We should not create an instance if we have already created one.
+ $block_instance = $this->blockManager->createInstance($summary_plugin_id);
+ if ($block_instance) {
+ $block_view = $block_instance->build();
+ if ($block_view) {
+ // Replace content facets summary plugin ID selector.
+ $response->addCommand(new ReplaceCommand('[data-drupal-facets-summary-plugin-id = "' . $summary_plugin_id . '"]', $block_view));
+ // Hide or show block.
+ $hide_show_selector = '[data-drupal-block-facet-summary-id = "' . $summary_plugin_id . '"]';
+ if (!empty($block_view['facets_summary']['#attributes']['class']) && in_array('hidden', $block_view['facets_summary']['#attributes']['class'])) {
+ $response->addCommand(new InvokeCommand($hide_show_selector, 'addClass', ['hidden']));
+ }
+ else {
+ $response->addCommand(new InvokeCommand($hide_show_selector, 'removeClass', ['hidden']));
+ }
+ }
+ }
}
}
diff --git a/src/Plugin/Block/FacetBlock.php b/src/Plugin/Block/FacetBlock.php
index 676c573..509552f 100644
--- a/src/Plugin/Block/FacetBlock.php
+++ b/src/Plugin/Block/FacetBlock.php
@@ -3,6 +3,7 @@
namespace Drupal\facets\Plugin\Block;
use Drupal\Core\Block\BlockBase;
+use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Form\FormStateInterface;
@@ -79,39 +80,60 @@ class FacetBlock extends BlockBase implements ContainerFactoryPluginInterface {
return [];
}
+ $build = [];
+
// Let the facet_manager build the facets.
- $build = $this->facetManager->build($facet);
+ $facet_build = $this->facetManager->build($facet);
- if (!empty($build)) {
+ if ($facet_build) {
// Add extra elements from facet source, for example, ajax scripts.
// @see Drupal\facets\Plugin\facets\facet_source\SearchApiDisplay
- /* @var \Drupal\facets\FacetSource\FacetSourcePluginInterface $facet_source */
+ /** @var \Drupal\facets\FacetSource\FacetSourcePluginInterface $facet_source */
$facet_source = $facet->getFacetSource();
- $build += $facet_source->buildFacet();
-
- // Add contextual links only when we have results.
- $build['#contextual_links']['facets_facet'] = [
- 'route_parameters' => ['facets_facet' => $facet->id()],
+ $facet_build += $facet_source->buildFacet();
+
+ $build = [
+ '#type' => 'container',
+ '#contextual_links' => [
+ 'facets_facet' => [
+ 'route_parameters' => ['facets_facet' => $facet->id()],
+ ],
+ ],
+ '#attributes' => [
+ 'class' => ['block-facet__wrapper'],
+ ],
+ $facet_build,
];
- if (!empty($build[0]['#attributes']['class']) && in_array('facet-active', $build[0]['#attributes']['class'], TRUE)) {
- $build['#attributes']['class'][] = 'facet-active';
- }
- else {
- $build['#attributes']['class'][] = 'facet-inactive';
+ // Add css classes.
+ if (!empty($facet_build[0]['#attributes']['class'])) {
+ $css_classes = $facet_build[0]['#attributes']['class'];
+ // Active/inactive css classes.
+ if (in_array('facet-active', $css_classes)) {
+ $build['#attributes']['class'][] = 'facet-active';
+ }
+ else {
+ $build['#attributes']['class'][] = 'facet-inactive';
+ }
+ // Whether it is necessary to add hide css class.
+ if (in_array('facet-hidden', $css_classes)) {
+ $build['#attributes']['class'][] = 'hidden';
+ }
}
// Add classes needed for ajax.
- if (!empty($build['#use_ajax'])) {
+ if (!empty($facet_build['#use_ajax'])) {
$build['#attributes']['class'][] = 'block-facets-ajax';
- // The configuration block id isn't always set in the configuration.
- if (isset($this->configuration['block_id'])) {
- $build['#attributes']['class'][] = 'js-facet-block-id-' . $this->configuration['block_id'];
- }
- else {
- $build['#attributes']['class'][] = 'js-facet-block-id-' . $this->pluginId;
- }
+ $block_id = str_replace(':', '--', $this->pluginId);
+ $block_id = Html::cleanCssIdentifier($block_id);
+ $build['#attributes']['class'][] = 'js-facet-block-id-' . $block_id;
+ $build['#attributes']['id'] = Html::getUniqueId($block_id);
}
+
+ // To render correctly in different situations.
+ $build = [
+ 'facet_block' => $build,
+ ];
}
return $build;
...@@ -124,20 +124,27 @@ function facets_entity_presave(EntityInterface $entity) { ...@@ -124,20 +124,27 @@ function facets_entity_presave(EntityInterface $entity) {
/** /**
* Implements hook_preprocess_block(). * Implements hook_preprocess_block().
* *
* Adds a class for the widget to the facet block to allow for more specific * Adds some classes for hiding empty blocks, working ajax, and more.
* styling.
*/ */
function facets_preprocess_block(&$variables) { function facets_preprocess_block(&$variables) {
if ($variables['configuration']['provider'] == 'facets') { if ($variables['configuration']['provider'] == 'facets') {
// Hide the block if it's empty. // Hide the block if it's empty.
if (!empty($variables['elements']['content'][0]['#attributes']['class']) && in_array('facet-hidden', $variables['elements']['content'][0]['#attributes']['class'])) { if (!empty($variables['content']['facet_block']['#attributes'])) {
// Add the Drupal class for hiding this for everyone, including screen $attributes = $variables['content']['facet_block']['#attributes'];
// readers. See hidden.module.css in the core system module. if (isset($attributes['class'])) {
$variables['attributes']['class'][] = 'hidden'; if (in_array('hidden', $attributes['class'])) {
// Add the Drupal class for hiding this for everyone, including screen
// readers. See hidden.module.css in the core system module.
$variables['attributes']['class'][] = 'hidden';
}
}
} }
if (!empty($variables['derivative_plugin_id'])) { if (!empty($variables['derivative_plugin_id'])) {
$facet = Facet::load($variables['derivative_plugin_id']); $facet = Facet::load($variables['derivative_plugin_id']);
$variables['attributes']['class'][] = 'block-facet--' . Html::cleanCssIdentifier($facet->getWidget()['type']); $variables['attributes']['class'][] = 'block-facet--' . Html::cleanCssIdentifier($facet->getWidget()['type']);
// For use ajax.
$variables['attributes']['data-drupal-block-facet-id'] = $facet->id();
} }
} }
} }
......
...@@ -37,17 +37,72 @@ ...@@ -37,17 +37,72 @@
return; return;
} }
// Update view on summary block click. // Update view on range slider stop event
if (updateFacetsSummaryBlock() && (facetId === 'facets_summary_ajax')) { if (typeof settings.facets !== "undefined" && settings.facets.sliders && settings.facets.sliders[facetId]) {
$('[data-drupal-facets-summary-id=' + facetSettings.facets_summary_id + ']').children('ul').children('li').once().click(function (e) { settings.facets.sliders[facetId].stop = function (e, ui) {
e.preventDefault(); var href = settings.facets.sliders[facetId].url.replace('__range_slider_min__', ui.values[0]).replace('__range_slider_max__', ui.values[1]);
var facetLink = $(this).find('a');
updateFacetsView(facetLink.attr('href'), current_dom_id, view_path); // Update facet query params on the request.
}); var currentHref = window.location.href;
var currentQueryParams = Drupal.Views.parseQueryString(currentHref);
var newQueryParams = Drupal.Views.parseQueryString(href);
var queryParams = {};
var facetPositions = [];
var fCount = 0;
var value = '';
var facetKey = '';
for (var paramName in currentQueryParams) {
if (paramName.substr(0, 1) === 'f') {
value = currentQueryParams[paramName];
// Store the facet position so we can override it later.
facetKey = value.substr(0, value.indexOf(':'));
facetPositions[facetKey] = fCount;
queryParams['f[' + fCount + ']'] = value;
fCount++;
}
else {
queryParams[paramName] = currentQueryParams[paramName];
}
}
var paramKey = '';
for (let paramName in newQueryParams) {
if (paramName.substr(0, 1) === 'f') {
value = newQueryParams[paramName];
// replace
facetKey = value.substr(0, value.indexOf(':'));
if (typeof facetPositions[facetKey] !== 'undefined') {
paramKey = 'f[' + facetPositions[facetKey] + ']';
}
else {
paramKey = 'f[' + fCount + ']';
fCount++;
}
queryParams[paramKey] = newQueryParams[paramName];
}
else {
queryParams[paramName] = newQueryParams[paramName];
}
}
href = '/' + Drupal.Views.getPath(href) + '?' + $.param(queryParams);
updateFacetsView(href, current_dom_id, view_path);
};
}
else if (facetId == 'facets_summary_ajax_summary' || facetId == 'facets_summary_ajax_summary_count') {
if (updateFacetsSummaryBlock()) {
$('[data-drupal-facets-summary-id=' + facetSettings.facets_summary_id + ']').children('ul').children('li').once().click(function (e) {
e.preventDefault();
var facetLink = $(this).find('a');
updateFacetsView(facetLink.attr('href'), current_dom_id, view_path);
});
}
} }
// Update view on facet item click. // Update view on facet item click.
else { else {
$('[data-drupal-facet-id=' + facetId + ']').each(function (index, facet_item) { $('[data-drupal-facet-id |= ' + facetId + ']').each(function (index, facet_item) {
if ($(facet_item).hasClass('js-facets-widget')) { if ($(facet_item).hasClass('js-facets-widget')) {
$(facet_item).unbind('facets_filter.facets'); $(facet_item).unbind('facets_filter.facets');
$(facet_item).on('facets_filter.facets', function (event, url) { $(facet_item).on('facets_filter.facets', function (event, url) {
...@@ -104,8 +159,8 @@ ...@@ -104,8 +159,8 @@
var facets_blocks = facetsBlocks(); var facets_blocks = facetsBlocks();
// Remove All Range Input Form Facet Blocks from being updated. // Remove All Range Input Form Facet Blocks from being updated.
if(settings.facets && settings.facets.rangeInput) { if (settings.facets && settings.facets.rangeInput) {
$.each(settings.facets.rangeInput, function (index, value){ $.each(settings.facets.rangeInput, function (index, value) {
delete facets_blocks[value.facetId]; delete facets_blocks[value.facetId];
}); });
} }
...@@ -121,17 +176,17 @@ ...@@ -121,17 +176,17 @@
// Update facets summary block. // Update facets summary block.
if (updateFacetsSummaryBlock()) { if (updateFacetsSummaryBlock()) {
var facet_summary_wrapper_id = $('[data-drupal-facets-summary-id=' + settings.facets_views_ajax.facets_summary_ajax.facets_summary_id + ']').attr('id');
var facet_summary_block_id = '';
if (facet_summary_wrapper_id.indexOf('--') !== -1) {
facet_summary_block_id = facet_summary_wrapper_id.substring(0, facet_summary_wrapper_id.indexOf('--')).replace('block-', '');
}
else {
facet_summary_block_id = facet_summary_wrapper_id.replace('block-', '');
}
facet_settings.submit.update_summary_block = true; facet_settings.submit.update_summary_block = true;
facet_settings.submit.facet_summary_block_id = facet_summary_block_id; facet_settings.submit.facet_summary_plugin_ids = {};
facet_settings.submit.facet_summary_wrapper_id = settings.facets_views_ajax.facets_summary_ajax.facets_summary_id; let summary_selector = '[data-drupal-facets-summary-id=' + settings.facets_views_ajax.facets_summary_ajax_summary.facets_summary_id + ']';
if (settings.facets_views_ajax.facets_summary_ajax_summary_count !== undefined) {
summary_selector += ', [data-drupal-facets-summary-id=' + settings.facets_views_ajax.facets_summary_ajax_summary_count.facets_summary_id + ']';
}
$(summary_selector).each(function (index, summaryWrapper) {
let summaryPluginId = $(summaryWrapper).attr('data-drupal-facets-summary-plugin-id');
let summaryPluginIdWrapper = $(summaryWrapper).attr('id');
facet_settings.submit.facet_summary_plugin_ids[summaryPluginIdWrapper] = summaryPluginId;
});
} }
Drupal.ajax(facet_settings).execute(); Drupal.ajax(facet_settings).execute();
...@@ -143,7 +198,7 @@ ...@@ -143,7 +198,7 @@
var settings = drupalSettings; var settings = drupalSettings;
var update_summary = false; var update_summary = false;
if (settings.facets_views_ajax.facets_summary_ajax) { if (settings.facets_views_ajax.facets_summary_ajax_summary || settings.facets_views_ajax.facets_summary_ajax_summary_count) {
update_summary = true; update_summary = true;
} }
...@@ -162,8 +217,8 @@ ...@@ -162,8 +217,8 @@
return v.slice(block_id_start.length, v.length); return v.slice(block_id_start.length, v.length);
} }
}).join(); }).join();
var block_selector = '#' + $(this).attr('id'); var block_selector = $(this).attr('id');
facets_blocks[block_id] = block_selector; facets_blocks[block_selector] = block_id;
}); });
return facets_blocks; return facets_blocks;
...@@ -204,12 +259,12 @@ ...@@ -204,12 +259,12 @@
} }
// Helper function to add exposed form data to facets url // Helper function to add exposed form data to facets url
var addExposedFiltersToFacetsUrl = function(href, view_name, view_display_id) { var addExposedFiltersToFacetsUrl = function (href, view_name, view_display_id) {
var $exposed_form = $('form#views-exposed-form-' + view_name.replace(/_/g, '-') + '-' + view_display_id.replace(/_/g, '-')); var $exposed_form = $('form#views-exposed-form-' + view_name.replace(/_/g, '-') + '-' + view_display_id.replace(/_/g, '-'));
var params = Drupal.Views.parseQueryString(href); var params = Drupal.Views.parseQueryString(href);
$.each($exposed_form.serializeArray(), function() { $.each($exposed_form.serializeArray(), function () {
params[this.name] = this.value; params[this.name] = this.value;
}); });
......
...@@ -98,3 +98,26 @@ function facets_summary_theme_suggestions_facets_summary_item_list(array $variab ...@@ -98,3 +98,26 @@ function facets_summary_theme_suggestions_facets_summary_item_list(array $variab
function facets_summary_preprocess_facets_summary_item_list(array &$variables) { function facets_summary_preprocess_facets_summary_item_list(array &$variables) {
template_preprocess_item_list($variables); template_preprocess_item_list($variables);
} }
/**
* Implements hook_preprocess_block().
*
* Adds some classes for hiding empty blocks, working ajax, and more.
*/
function facets_summary_preprocess_block(&$variables) {
if ($variables['configuration']['provider'] == 'facets_summary') {
// Hide the block if it's empty.
if (!empty($variables['content']['facets_summary']['#attributes'])) {
$attributes = $variables['content']['facets_summary']['#attributes'];
if (isset($attributes['class'])) {
if (in_array('hidden', $attributes['class'])) {
// Add the Drupal class for hiding this for everyone, including screen
// readers. See hidden.module.css in the core system module.
$variables['attributes']['class'][] = 'hidden';
}
}
}
// For use ajax.
$variables['attributes']['data-drupal-block-facet-summary-id'] = $variables['configuration']['id'];
}
}
...@@ -8,6 +8,8 @@ services: ...@@ -8,6 +8,8 @@ services:
- '@plugin.manager.facets.facet_source' - '@plugin.manager.facets.facet_source'
- '@plugin.manager.facets_summary.processor' - '@plugin.manager.facets_summary.processor'
- '@facets.manager' - '@facets.manager'
- '@plugin.manager.facets.url_processor'
- '@facets.utility.url_generator'
facets_summary.search_api_subscriber: facets_summary.search_api_subscriber:
class: Drupal\facets_summary\EventSubscriber\SearchApiSubscriber class: Drupal\facets_summary\EventSubscriber\SearchApiSubscriber
arguments: ['@entity_type.manager'] arguments: ['@entity_type.manager']
......
...@@ -4,13 +4,17 @@ namespace Drupal\facets_summary\FacetsSummaryManager; ...@@ -4,13 +4,17 @@ namespace Drupal\facets_summary\FacetsSummaryManager;
use Drupal\Core\Link; use Drupal\Core\Link;
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\facets\Exception\InvalidProcessorException; use Drupal\facets\Exception\InvalidProcessorException;
use Drupal\facets\FacetManager\DefaultFacetManager; use Drupal\facets\FacetManager\DefaultFacetManager;
use Drupal\facets\FacetSource\FacetSourcePluginManager; use Drupal\facets\FacetSource\FacetSourcePluginManager;
use Drupal\facets\Result\Result;
use Drupal\facets_summary\Processor\BuildProcessorInterface; use Drupal\facets_summary\Processor\BuildProcessorInterface;
use Drupal\facets_summary\Processor\ProcessorInterface; use Drupal\facets_summary\Processor\ProcessorInterface;
use Drupal\facets_summary\Processor\ProcessorPluginManager; use Drupal\facets_summary\Processor\ProcessorPluginManager;
use Drupal\facets_summary\FacetsSummaryInterface; use Drupal\facets_summary\FacetsSummaryInterface;
use Drupal\facets\UrlProcessor\UrlProcessorPluginManager;
use Drupal\facets\Utility\FacetsUrlGenerator;
/** /**
* The facet summary manager. * The facet summary manager.
...@@ -45,6 +49,20 @@ class DefaultFacetsSummaryManager { ...@@ -45,6 +49,20 @@ class DefaultFacetsSummaryManager {
*/ */
protected $facetManager; protected $facetManager;
/**
* The url processor plugin manager.
*
* @var \Drupal\facets\UrlProcessor\UrlProcessorPluginManager
*/
protected $urlProcessorPluginManager;
/**
* The facets url generator.
*
* @var \Drupal\facets\Utility\FacetsUrlGenerator
*/
protected $facetsUrlGenerator;
/** /**
* Constructs a new instance of the DefaultFacetManager. * Constructs a new instance of the DefaultFacetManager.
* *
...@@ -54,11 +72,17 @@ class DefaultFacetsSummaryManager { ...@@ -54,11 +72,17 @@ class DefaultFacetsSummaryManager {
* The facets summary processor plugin manager. * The facets summary processor plugin manager.
* @param \Drupal\facets\FacetManager\DefaultFacetManager $facet_manager * @param \Drupal\facets\FacetManager\DefaultFacetManager $facet_manager
* The facet manager service. * The facet manager service.
* @param \Drupal\facets\UrlProcessor\UrlProcessorPluginManager $url_processor_plugin_manager
* The url processor plugin manager.
* @param \Drupal\facets\Utility\FacetsUrlGenerator $facets_url_generator
* The facets url generator.
*/ */
public function __construct(FacetSourcePluginManager $facet_source_manager, ProcessorPluginManager $processor_plugin_manager, DefaultFacetManager $facet_manager) { public function __construct(FacetSourcePluginManager $facet_source_manager, ProcessorPluginManager $processor_plugin_manager, DefaultFacetManager $facet_manager, UrlProcessorPluginManager $url_processor_plugin_manager, FacetsUrlGenerator $facets_url_generator) {
$this->facetSourcePluginManager = $facet_source_manager; $this->facetSourcePluginManager = $facet_source_manager;
$this->processorPluginManager = $processor_plugin_manager; $this->processorPluginManager = $processor_plugin_manager;
$this->facetManager = $facet_manager; $this->facetManager = $facet_manager;
$this->urlProcessorPluginManager = $url_processor_plugin_manager;
$this->facetsUrlGenerator = $facets_url_generator;
} }
/** /**
...@@ -117,16 +141,48 @@ class DefaultFacetsSummaryManager { ...@@ -117,16 +141,48 @@ class DefaultFacetsSummaryManager {
'#theme' => 'facets_summary_item_list', '#theme' => 'facets_summary_item_list',
'#facet_summary_id' => $facets_summary->id(), '#facet_summary_id' => $facets_summary->id(),
'#attributes' => [ '#attributes' => [
'data-drupal-facets-summary-id' => $facets_summary->id(), 'class' => ['facet-summary__items'],
], ],
]; ];
$results = []; $results = [];
foreach ($facets as $facet) { foreach ($facets as $facet) {
$show_count = $facets_config[$facet->id()]['show_count']; $enabled_processors = $facet->getProcessors(TRUE);
$results = array_merge($results, $this->buildResultTree($show_count, $facet->getResults())); if (isset($enabled_processors["range_slider"])) {
$active_values = $facet->getActiveItems();
if ($active_values) {
$min = $active_values[0][0];
$max = $active_values[0][1];
$url_processor = $this->urlProcessorPluginManager->createInstance($facet->getFacetSourceConfig()->getUrlProcessorName(), ['facet' => $facet]);
$active_filters = $url_processor->getActiveFilters();
if (isset($active_filters[''])) {
unset($active_filters['']);
}
unset($active_filters[$facet->id()]);
// Only if there are still active filters, use url generator.
if ($active_filters) {
$url = $this->facetsUrlGenerator->getUrl($active_filters, FALSE);
}
else {
// @todo Keep non-facet related get params.
$url = Url::fromUserInput($facets_summary->getFacetSource()->getPath());
}
$result_without_current_rangeslider = new Result($facet, "(min:$min,max:$max)", " $min - $max", 1);
$result_without_current_rangeslider->setActiveState(TRUE);
$result_without_current_rangeslider->setUrl($url);
$results = array_merge($results, $this->buildResultTree(FALSE, [$result_without_current_rangeslider]));
}
}
else {
$show_count = $facets_config[$facet->id()]['show_count'];
$results = array_merge($results, $this->buildResultTree($show_count, $facet->getResults()));
}
}
if ($results) {
$build['#items'] = $results;
} }
$build['#items'] = $results;
// Allow our Facets Summary processors to alter the build array in a // Allow our Facets Summary processors to alter the build array in a
// configured order. // configured order.
......
...@@ -6,6 +6,7 @@ use Drupal\Core\Block\BlockBase; ...@@ -6,6 +6,7 @@ use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\UncacheableDependencyTrait; use Drupal\Core\Cache\UncacheableDependencyTrait;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Url; use Drupal\Core\Url;
use Drupal\Component\Utility\Html;
use Drupal\facets_summary\Entity\FacetsSummary; use Drupal\facets_summary\Entity\FacetsSummary;
use Drupal\facets_summary\FacetsSummaryBlockInterface; use Drupal\facets_summary\FacetsSummaryBlockInterface;
use Drupal\facets_summary\FacetsSummaryManager\DefaultFacetsSummaryManager; use Drupal\facets_summary\FacetsSummaryManager\DefaultFacetsSummaryManager;
...@@ -88,25 +89,46 @@ class FacetsSummaryBlock extends BlockBase implements FacetsSummaryBlockInterfac ...@@ -88,25 +89,46 @@ class FacetsSummaryBlock extends BlockBase implements FacetsSummaryBlockInterfac
$facets_summary = $this->getEntity(); $facets_summary = $this->getEntity();
// Let the facet_manager build the facets. // Let the facet_manager build the facets.
$build = $this->facetsSummaryManager->build($facets_summary); $build = [];
// Add contextual links only when we have results. // Let the facet_manager build the facets.
if (!empty($build)) { $summary_build = $this->facetsSummaryManager->build($facets_summary);
$build['#contextual_links']['facets_summary'] = [
'route_parameters' => ['facets_summary' => $facets_summary->id()], if ($summary_build) {
$build = [
'facets_summary' => [
'#type' => 'container',
'#contextual_links' => [
'facets_summary' => [
'route_parameters' => ['facets_summary' => $facets_summary->id()],
],
],
'#attributes' => [
'data-drupal-facets-summary-id' => $facets_summary->id(),
'data-drupal-facets-summary-plugin-id' => $this->getPluginId(),
'id' => Html::getUniqueId(str_replace(':', '-', $this->getPluginId())),
'class' => [
'facets-summary-block__wrapper',
],
],
'summary_build' => $summary_build,
],
]; ];
}
/** @var \Drupal\views\ViewExecutable $view */ // Hidden empty result.
if ($view = $facets_summary->getFacetSource()->getViewsDisplay()) { if (!isset($summary_build['#items']) && !isset($summary_build['#message'])) {
$build['#attached']['drupalSettings']['facets_views_ajax'] = [ $build['facets_summary']['#attributes']['class'][] = 'hidden';
'facets_summary_ajax' => [ }
/** @var \Drupal\views\ViewExecutable $view */
if ($view = $facets_summary->getFacetSource()->getViewsDisplay()) {
$build['#attached']['drupalSettings']['facets_views_ajax']['facets_summary_ajax_' . $facets_summary->id()] = [
'facets_summary_id' => $facets_summary->id(), 'facets_summary_id' => $facets_summary->id(),
'view_id' => $view->id(), 'view_id' => $view->id(),
'current_display_id' => $view->current_display, 'current_display_id' => $view->current_display,
'ajax_path' => Url::fromRoute('views.ajax')->toString(), 'ajax_path' => Url::fromRoute('views.ajax')->toString(),
], ];
]; }
} }
return $build; return $build;
......
...@@ -5,10 +5,10 @@ namespace Drupal\facets\Controller; ...@@ -5,10 +5,10 @@ namespace Drupal\facets\Controller;
use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\InvokeCommand; use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\ReplaceCommand; use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Block\BlockManager;
use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Path\CurrentPathStack; use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\PathProcessor\PathProcessorManager; use Drupal\Core\PathProcessor\PathProcessorManager;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Routing\CurrentRouteMatch; use Drupal\Core\Routing\CurrentRouteMatch;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
...@@ -28,13 +28,6 @@ class FacetBlockAjaxController extends ControllerBase { ...@@ -28,13 +28,6 @@ class FacetBlockAjaxController extends ControllerBase {
*/ */
protected $storage; protected $storage;
/**
* The renderer.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/** /**
* The current path. * The current path.
* *
...@@ -63,11 +56,16 @@ class FacetBlockAjaxController extends ControllerBase { ...@@ -63,11 +56,16 @@ class FacetBlockAjaxController extends ControllerBase {
*/ */
protected $currentRouteMatch; protected $currentRouteMatch;
/**
* The block manager service.
*
* @var \Drupal\Core\Block\BlockManager
*/
protected $blockManager;
/** /**
* Constructs a FacetBlockAjaxController object. * Constructs a FacetBlockAjaxController object.
* *
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
* @param \Drupal\Core\Path\CurrentPathStack $currentPath * @param \Drupal\Core\Path\CurrentPathStack $currentPath
* The current path service. * The current path service.
* @param \Symfony\Component\Routing\RouterInterface $router * @param \Symfony\Component\Routing\RouterInterface $router
...@@ -76,14 +74,16 @@ class FacetBlockAjaxController extends ControllerBase { ...@@ -76,14 +74,16 @@ class FacetBlockAjaxController extends ControllerBase {
* The path processor manager. * The path processor manager.
* @param \Drupal\Core\Routing\CurrentRouteMatch $currentRouteMatch * @param \Drupal\Core\Routing\CurrentRouteMatch $currentRouteMatch
* The current route match service. * The current route match service.
* @param \Drupal\Core\Block\BlockManager $blockManager
* The block manager service.
*/ */
public function __construct(RendererInterface $renderer, CurrentPathStack $currentPath, RouterInterface $router, PathProcessorManager $pathProcessor, CurrentRouteMatch $currentRouteMatch) { public function __construct(CurrentPathStack $currentPath, RouterInterface $router, PathProcessorManager $pathProcessor, CurrentRouteMatch $currentRouteMatch, BlockManager $blockManager) {
$this->storage = $this->entityTypeManager()->getStorage('block'); $this->storage = $this->entityTypeManager()->getStorage('block');
$this->renderer = $renderer;
$this->currentPath = $currentPath; $this->currentPath = $currentPath;
$this->router = $router; $this->router = $router;
$this->pathProcessor = $pathProcessor; $this->pathProcessor = $pathProcessor;
$this->currentRouteMatch = $currentRouteMatch; $this->currentRouteMatch = $currentRouteMatch;
$this->blockManager = $blockManager;
} }
/** /**
...@@ -91,11 +91,11 @@ class FacetBlockAjaxController extends ControllerBase { ...@@ -91,11 +91,11 @@ class FacetBlockAjaxController extends ControllerBase {
*/ */
public static function create(ContainerInterface $container) { public static function create(ContainerInterface $container) {
return new static( return new static(
$container->get('renderer'),
$container->get('path.current'), $container->get('path.current'),
$container->get('router'), $container->get('router'),
$container->get('path_processor_manager'), $container->get('path_processor_manager'),
$container->get('current_route_match') $container->get('current_route_match'),
$container->get('plugin.manager.block')
); );
} }
...@@ -122,9 +122,6 @@ class FacetBlockAjaxController extends ControllerBase { ...@@ -122,9 +122,6 @@ class FacetBlockAjaxController extends ControllerBase {
throw new NotFoundHttpException('No facet link or facet blocks found.'); throw new NotFoundHttpException('No facet link or facet blocks found.');
} }
// Make sure we are not updating blocks multiple times.
$facets_blocks = array_unique($facets_blocks);
$new_request = Request::create($path); $new_request = Request::create($path);
$request_stack = new RequestStack(); $request_stack = new RequestStack();
$processed = $this->pathProcessor->processInbound($path, $new_request); $processed = $this->pathProcessor->processInbound($path, $new_request);
...@@ -136,40 +133,56 @@ class FacetBlockAjaxController extends ControllerBase { ...@@ -136,40 +133,56 @@ class FacetBlockAjaxController extends ControllerBase {
$container = \Drupal::getContainer(); $container = \Drupal::getContainer();
$container->set('request_stack', $request_stack); $container->set('request_stack', $request_stack);
$active_facet = $request->request->get('active_facet'); foreach ($facets_blocks as $block_selector => $block_id) {
// Facet block render array.
// Build the facets blocks found for the current request and update. $block_view = NULL;
foreach ($facets_blocks as $block_id => $block_selector) { // Re prepare from css standarts.
$block_entity = $this->storage->load($block_id); $block_id = str_replace(['--', '-'], [':', '_'], $block_id);
if ($block_entity) { // @todo We should not create an instance if we have already created one.
// Render a block, then add it to the response as a replace command. $block_instance = $this->blockManager->createInstance($block_id);
$block_view = $this->entityTypeManager if ($block_instance) {
->getViewBuilder('block') $block_view = $block_instance->build();
->view($block_entity); if ($block_view) {
// Replace content current ID selector.
$block_view = (string) $this->renderer->renderPlain($block_view); $response->addCommand(new ReplaceCommand('#' . $block_selector, $block_view));
$response->addCommand(new ReplaceCommand($block_selector, $block_view)); // Hide or show block.
$facet_id = explode(':', $block_id)[1];
$hide_show_selector = '[data-drupal-block-facet-id = "' . $facet_id . '"]';
if (!empty($block_view['facet_block']['#attributes']['class']) && in_array('hidden', $block_view['facet_block']['#attributes']['class'])) {
$response->addCommand(new InvokeCommand($hide_show_selector, 'addClass', ['hidden']));
}
else {
$response->addCommand(new InvokeCommand($hide_show_selector, 'removeClass', ['hidden']));
}
}
} }
} }
$response->addCommand(new InvokeCommand('[data-block-plugin-id="' . $active_facet . '"]', 'addClass', ['facet-active']));
// Update filter summary block. // Update filter summary block.
$update_summary_block = $request->request->get('update_summary_block'); $update_summary_block = $request->request->get('update_summary_block');
if ($update_summary_block) { if ($update_summary_block) {
$facet_summary_block_id = $request->request->get('facet_summary_block_id'); $facet_summary_plugin_ids = $request->request->get('facet_summary_plugin_ids');
$facet_summary_wrapper_id = $request->request->get('facet_summary_wrapper_id'); foreach ($facet_summary_plugin_ids as $block_selector => $summary_plugin_id) {
$facet_summary_block_id = str_replace('-', '_', $facet_summary_block_id); // Facet summary block render array.
$block_view = NULL;
if ($facet_summary_block_id) { // @todo We should not create an instance if we have already created one.
$block_entity = $this->storage->load($facet_summary_block_id); $block_instance = $this->blockManager->createInstance($summary_plugin_id);
$block_view = $this->entityTypeManager if ($block_instance) {
->getViewBuilder('block') $block_view = $block_instance->build();
->view($block_entity); if ($block_view) {
$block_view = (string) $this->renderer->renderPlain($block_view); // Replace content facets summary plugin ID selector.
$response->addCommand(new ReplaceCommand('[data-drupal-facets-summary-plugin-id = "' . $summary_plugin_id . '"]', $block_view));
$response->addCommand(new ReplaceCommand('[data-drupal-facets-summary-id=' . $facet_summary_wrapper_id . ']', $block_view)); // Hide or show block.
$hide_show_selector = '[data-drupal-block-facet-summary-id = "' . $summary_plugin_id . '"]';
if (!empty($block_view['facets_summary']['#attributes']['class']) && in_array('hidden', $block_view['facets_summary']['#attributes']['class'])) {
$response->addCommand(new InvokeCommand($hide_show_selector, 'addClass', ['hidden']));
}
else {
$response->addCommand(new InvokeCommand($hide_show_selector, 'removeClass', ['hidden']));
}
}
}
} }
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace Drupal\facets\Plugin\Block; namespace Drupal\facets\Plugin\Block;
use Drupal\Core\Block\BlockBase; use Drupal\Core\Block\BlockBase;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
...@@ -79,39 +80,60 @@ class FacetBlock extends BlockBase implements ContainerFactoryPluginInterface { ...@@ -79,39 +80,60 @@ class FacetBlock extends BlockBase implements ContainerFactoryPluginInterface {
return []; return [];
} }
$build = [];
// Let the facet_manager build the facets. // Let the facet_manager build the facets.
$build = $this->facetManager->build($facet); $facet_build = $this->facetManager->build($facet);
if (!empty($build)) { if ($facet_build) {
// Add extra elements from facet source, for example, ajax scripts. // Add extra elements from facet source, for example, ajax scripts.
// @see Drupal\facets\Plugin\facets\facet_source\SearchApiDisplay // @see Drupal\facets\Plugin\facets\facet_source\SearchApiDisplay
/* @var \Drupal\facets\FacetSource\FacetSourcePluginInterface $facet_source */ /** @var \Drupal\facets\FacetSource\FacetSourcePluginInterface $facet_source */
$facet_source = $facet->getFacetSource(); $facet_source = $facet->getFacetSource();
$build += $facet_source->buildFacet(); $facet_build += $facet_source->buildFacet();
// Add contextual links only when we have results. $build = [
$build['#contextual_links']['facets_facet'] = [ '#type' => 'container',
'route_parameters' => ['facets_facet' => $facet->id()], '#contextual_links' => [
'facets_facet' => [
'route_parameters' => ['facets_facet' => $facet->id()],
],
],
'#attributes' => [
'class' => ['block-facet__wrapper'],
],
$facet_build,
]; ];
if (!empty($build[0]['#attributes']['class']) && in_array('facet-active', $build[0]['#attributes']['class'], TRUE)) { // Add css classes.
$build['#attributes']['class'][] = 'facet-active'; if (!empty($facet_build[0]['#attributes']['class'])) {
} $css_classes = $facet_build[0]['#attributes']['class'];
else { // Active/inactive css classes.
$build['#attributes']['class'][] = 'facet-inactive'; if (in_array('facet-active', $css_classes)) {
$build['#attributes']['class'][] = 'facet-active';
}
else {
$build['#attributes']['class'][] = 'facet-inactive';
}
// Whether it is necessary to add hide css class.
if (in_array('facet-hidden', $css_classes)) {
$build['#attributes']['class'][] = 'hidden';
}
} }
// Add classes needed for ajax. // Add classes needed for ajax.
if (!empty($build['#use_ajax'])) { if (!empty($facet_build['#use_ajax'])) {
$build['#attributes']['class'][] = 'block-facets-ajax'; $build['#attributes']['class'][] = 'block-facets-ajax';
// The configuration block id isn't always set in the configuration. $block_id = str_replace(':', '--', $this->pluginId);
if (isset($this->configuration['block_id'])) { $block_id = Html::cleanCssIdentifier($block_id);
$build['#attributes']['class'][] = 'js-facet-block-id-' . $this->configuration['block_id']; $build['#attributes']['class'][] = 'js-facet-block-id-' . $block_id;
} $build['#attributes']['id'] = Html::getUniqueId($block_id);
else {
$build['#attributes']['class'][] = 'js-facet-block-id-' . $this->pluginId;
}
} }
// To render correctly in different situations.
$build = [
'facet_block' => $build,
];
} }
return $build; return $build;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment