Skip to content
Snippets Groups Projects
FacetBlock.php 6.6 KiB
Newer Older
namespace Drupal\facets\Plugin\Block;
Ted Cooper's avatar
Ted Cooper committed
use Drupal\Component\Utility\Html;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Form\FormStateInterface;
Ted Cooper's avatar
Ted Cooper committed
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\facets\FacetManager\DefaultFacetManager;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Exposes a facet rendered as a block.
Joris Vercammen's avatar
Joris Vercammen committed
 *   deriver = "Drupal\facets\Plugin\Block\FacetBlockDeriver"
 * )
 */
class FacetBlock extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * @var \Drupal\facets\FacetManager\DefaultFacetManager
   * The entity storage used for facets.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
Ted Cooper's avatar
Ted Cooper committed
   * The facet entity.
   *
  /**
   * Construct a FacetBlock instance.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param string $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\facets\FacetManager\DefaultFacetManager $facet_manager
   * @param \Drupal\Core\Entity\EntityStorageInterface $facet_storage
   *   The entity storage used for facets.
  public function __construct(array $configuration, $plugin_id, $plugin_definition, DefaultFacetManager $facet_manager, EntityStorageInterface $facet_storage) {
    $this->facetManager = $facet_manager;
    $this->facetStorage = $facet_storage;
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('facets.manager'),
      $container->get('entity_type.manager')->getStorage('facets_facet')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    // Do not build the facet if the block is being previewed.
    if ($this->getContextValue('in_preview')) {
      return [];
    }

    // Let the facet_manager build the facets.
    $facet_build = $this->facetManager->build($facet);

Ted Cooper's avatar
Ted Cooper committed
    if ($facet_build) {
      CacheableMetadata::createFromObject($this)->applyTo($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 */
      $facet_source = $facet->getFacetSource();
      $facet_build += $facet_source->buildFacet();

      $build = [
        '#type' => 'container',
        '#contextual_links' => [
          'facets_facet' => [
            'route_parameters' => ['facets_facet' => $facet->id()],
          ],
        ],
        '#attributes' => [
          'class' => ['block-facet__wrapper'],
        ],
        0 => $facet_build,
      ];

      // 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';
Ted Cooper's avatar
Ted Cooper committed
        else {
          $build['#attributes']['class'][] = 'facet-inactive';
Ted Cooper's avatar
Ted Cooper committed
        // 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($facet_build['#use_ajax'])) {
        $build['#attributes']['class'][] = 'block-facets-ajax';
        $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 \Drupal\facets\FacetInterface
   *   The facet entity.
   */
  protected function getFacet(): FacetInterface {
    if (!$this->facet) {
      $this->facet = $this->facetStorage->load($this->getDerivativeId());
    }
    return $this->facet;
    return Cache::mergeTags(parent::getCacheTags(), $this->getFacet()->getCacheTags());
    return Cache::mergeContexts(parent::getCacheContexts(), $this->getFacet()->getCacheContexts());
  /**
   * {@inheritdoc}
   */
  public function getCacheMaxAge() {
    return Cache::mergeMaxAges(parent::getCacheMaxAge(), $this->getFacet()->getCacheMaxAge());
  /**
   * {@inheritdoc}
   */
  public function calculateDependencies() {
    return ['config' => [$this->getFacet()->getConfigDependencyName()]];
  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    // Checks for a valid form id. Panelizer does not generate one.
    if (isset($form['id']['#value'])) {
      // Save block id to configuration, we do this for loading the original
      // block with ajax.
      $block_id = $form['id']['#value'];
      $this->configuration['block_id'] = $block_id;
    }
  /**
   * {@inheritdoc}
   */
  public function getPreviewFallbackString() {
    return $this->t('Placeholder for the "@facet" facet', ['@facet' => $this->getDerivativeId()]);
  }

  /**
   * {@inheritDoc}
   *
   * Allow to render facet block if one of the following conditions are met:
   * - facet is allowed to be displayed regardless of the source visibility
   * - facet source is rendered in the same request as facet.
   */
  public function blockAccess(AccountInterface $account) {
    $facet = $this->getFacet();
    return AccessResult::allowedIf(
      !$facet->getOnlyVisibleWhenFacetSourceIsVisible()
      || ($facet->getFacetSource() && $facet->getFacetSource()->isRenderedInCurrentRequest())
    )->addCacheableDependency($facet);
  }