Skip to content
Facet.php 13.5 KiB
Newer Older
<?php

/**
 * @file
 * Contains \Drupal\facets\Entity\Facet.
namespace Drupal\facets\Entity;

use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\facets\FacetInterface;

/**
 * Defines the search index configuration entity.
 *
 * @ConfigEntityType(
 *   label = @Translation("Facet"),
 *   handlers = {
 *     "storage" = "Drupal\Core\Config\Entity\ConfigEntityStorage",
 *     "list_builder" = "Drupal\facets\FacetListBuilder",
 *     "form" = {
 *       "default" = "Drupal\facets\Form\FacetForm",
 *       "edit" = "Drupal\facets\Form\FacetForm",
 *       "display" = "Drupal\facets\Form\FacetDisplayForm",
 *       "delete" = "Drupal\facets\Form\FacetDeleteConfirmForm",
 *   admin_permission = "administer facets",
 *   config_prefix = "facet",
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "name",
 *     "uuid" = "uuid",
 *     "status" = "status"
 *   },
 *   config_export = {
 *     "id",
 *     "name",
 *     "query_type_name",
 *     "widget",
 *     "only_visible_when_facet_source_is_visible",
 *   },
 *   links = {
 *     "canonical" = "/admin/config/search/facets",
 *     "add-form" = "/admin/config/search/facets/add-facet",
 *     "edit-form" = "/admin/config/search/facets/{facets_facet}/edit",
 *     "display-form" = "/admin/config/search/facets/{facets_facet}/display",
 *     "delete-form" = "/admin/config/search/facets/{facets_facet}/delete",
 *   }
 * )
 */
class Facet extends ConfigEntityBase implements FacetInterface {

  /**
   * The ID of the index.
   *
   * @var string
   */
  protected $id;

  /**
   * A name to be displayed for the index.
   *
   * @var string
   */
  protected $name;

  /**
   * A string describing the index.
   *
   * @var string
   */
  protected $description;

  /**
   * A string describing the widget.
   *
   * @var string
   */
  protected $widget;

  /**
   * Configuration for the widget. This is a key-value stored array.
   *
   * @var string
   */
  protected $widget_configs;

  /**
   * An array of options configuring this index.
   *
   * @var array
   *
   * @see getOptions()
   */
  protected $options = array();

  /**
   * The field identifier.
   *
   * @var string
   */
  protected $field_identifier;

  /**
   * The query type name.
   *
   * @var string
   */
  protected $query_type_name;

  /**
   * The plugin name of the url processor.
  protected $url_processor_name;
   *
   * @var string
   */
   * @var \Drupal\facets\FacetSourceInterface
  /**
   * The path all the links should point to.
   *
   * @var string
   */
  protected $path;

Jur de Vries's avatar
Jur de Vries committed
  /**
   * The results.
   *
   * @var \Drupal\facets\Result\ResultInterface[]
Jur de Vries's avatar
Jur de Vries committed
   */
  protected $results = [];
Jur de Vries's avatar
Jur de Vries committed

  protected $active_values = [];
  /**
   * An array containing the facet source plugins.
   *
   * @var array
   */
  protected $facetSourcePlugins;

  /**
   * Cached information about the processors available for this facet.
   *
   * @var \Drupal\facets\Processor\ProcessorInterface[]|null

  /**
   * A boolean that defines whether or not the facet is only visible when the
   * facet source is visible.
   *
   * @var boolean
   */
  protected $only_visible_when_facet_source_is_visible;

Joris Vercammen's avatar
Joris Vercammen committed
   * The widget plugin manager.
   *
   * @var object
   */
  protected $widget_plugin_manager;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $values, $entity_type) {
    parent::__construct($values, $entity_type);
   * @return \Drupal\facets\Widget\WidgetPluginManager
   */
  public function getWidgetManager() {
    return $this->widget_plugin_manager ? : $container->get('plugin.manager.facets.widget');
  }

  /**
   * {@inheritdoc}
   */
  public function id() {
    return $this->id;
  }

  /**
   * {@inheritdoc}
   */
  public function getDescription() {
    return $this->description;
  }

   */
  public function setWidget($widget) {
    $this->widget = $widget;
    return $this;
  }

  /**
   */
  public function getWidget() {
    return $this->widget;
  }

  /**
   * {@inheritdoc}
   */
  public function getQueryType() {
    $facet_source = $this->getFacetSource();
    $query_types = $facet_source->getQueryTypesForFacet($this);

    // Get our widget configured for this facet.
    /** @var \Drupal\facets\Widget\WidgetInterface $widget */
    $widget = $this->getWidgetManager()->createInstance($this->getWidget());
    // Give the widget the chance to select a preferred query type. This is
    // useful with a date widget, as it needs to select the date query type.
    return $widget->getQueryType($query_types);
  }

  /**
   * Get the field alias used to identify the facet in the url.
   *
   * @return mixed
   */
  public function getFieldAlias() {
    // For now, create the field alias based on the field identifier.
    $field_alias = preg_replace('/[:\/]+/', '_', $this->field_identifier);
    return $field_alias;
  }

  /**
   * Sets an item with value to active.
   *
   * @param $value
   */
  public function setActiveItem($value) {
    if (!in_array($value, $this->active_values)) {
      $this->active_values[] = $value;
    }
  }

  /**
   * Get all the active items in the facet.
   *
   * @return mixed
   */
  public function getActiveItems() {
Jur de Vries's avatar
Jur de Vries committed
    return $this->active_values;
  }

  /**
   * {@inheritdoc}
   */
  public function getOption($name, $default = NULL) {
    return isset($this->options[$name]) ? $this->options[$name] : $default;
  }

  /**
   * {@inheritdoc}
   */
  public function getOptions() {
    return $this->options;
  }

  /**
   * {@inheritdoc}
   */
  public function setOption($name, $option) {
    $this->options[$name] = $option;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setOptions(array $options) {
    $this->options = $options;
    return $this;
  }

Joris Vercammen's avatar
Joris Vercammen committed
   * {@inheritdoc}
  public function getFieldIdentifier() {
    return $this->field_identifier;
Joris Vercammen's avatar
Joris Vercammen committed
   * {@inheritdoc}
  public function setFieldIdentifier($field_identifier) {
    $this->field_identifier = $field_identifier;
    return $this;
  }

Joris Vercammen's avatar
Joris Vercammen committed
   * {@inheritdoc}
  public function getQueryTypes() {
Joris Vercammen's avatar
Joris Vercammen committed
   * {@inheritdoc}
  public function getUrlProcessorName() {
    // @Todo: for now if the url processor is not set, defualt to query_string.
    return isset($this->url_processor_name) ? $this->url_processor_name : 'query_string';
Joris Vercammen's avatar
Joris Vercammen committed
   * {@inheritdoc}
  public function getName() {
    return $this->name;
  }
  public function setFacetSourceId($facet_source_id) {
    $this->facet_source_id = $facet_source_id;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getFacetSource() {
    if (!$this->facet_source_instance && $this->facet_source_id) {
      /** @var $facet_source_plugin_manager \Drupal\facets\FacetSource\FacetSourcePluginManager */
      $facet_source_plugin_manager = \Drupal::service('plugin.manager.facets.facet_source');
      $this->facet_source_instance = $facet_source_plugin_manager->createInstance($this->facet_source_id);
    }

    return $this->facet_source_instance;
  }

  /**
   * {@inheritdoc}
   */
  public function getFacetSourceId() {
    return $this->facet_source_id;
  /**
   * Retrieves all processors supported by this facet.
   *
   * @return \Drupal\facets\Processor\ProcessorInterface[]
   *   The loaded processors, keyed by processor ID.
   */
  protected function loadProcessors() {
    if (!isset($this->processors)) {
      /** @var $processor_plugin_manager \Drupal\facets\Processor\ProcessorPluginManager */
      $processor_plugin_manager = \Drupal::service('plugin.manager.facets.processor');
Joris Vercammen's avatar
Joris Vercammen committed
      $processor_settings = $this->getOption('processors', []);

      foreach ($processor_plugin_manager->getDefinitions() as $name => $processor_definition) {
        if (class_exists($processor_definition['class']) && empty($this->processors[$name])) {
          // Create our settings for this processor.
Joris Vercammen's avatar
Joris Vercammen committed
          $settings = empty($processor_settings[$name]['settings']) ? [] : $processor_settings[$name]['settings'];
          /** @var $processor \Drupal\facets\Processor\ProcessorInterface */
          $processor = $processor_plugin_manager->createInstance($name, $settings);
          $this->processors[$name] = $processor;
        }
        elseif (!class_exists($processor_definition['class'])) {
          \Drupal::logger('facets')->warning('Processor @id specifies a non-existing @class.', array('@id' => $name, '@class' => $processor_definition['class']));
  /**
   * {@inheritdoc}
   */
  protected function urlRouteParameters($rel) {
    $parameters = parent::urlRouteParameters($rel);
    return $parameters;
  }
Jur de Vries's avatar
Jur de Vries committed

Joris Vercammen's avatar
Joris Vercammen committed
   * {@inheritdoc}
Jur de Vries's avatar
Jur de Vries committed
  public function getResults() {
    return $this->results;
Jur de Vries's avatar
Jur de Vries committed
  }

Joris Vercammen's avatar
Joris Vercammen committed
  /**
   * Set an array of Result objects.
   *
   * @param array $results
   *   Array containing \Drupal\facets\Result\Result objects.
Joris Vercammen's avatar
Joris Vercammen committed
   */
Jur de Vries's avatar
Jur de Vries committed
  public function setResults(array $results) {
    $this->results = $results;
    // If there are active values,
    // set the results which are active to active.
    if (count($this->active_values)) {
      foreach ($this->results as $result) {
        if (in_array($result->getRawValue(), $this->active_values)) {
          $result->setActiveState(TRUE);
        }
      }
    }
Jur de Vries's avatar
Jur de Vries committed
  }
   * Until facets supports more than just search api, this is enough.

  /**
   * @inheritdoc
   */
  public function isActiveValue($value) {
    $is_active = FALSE;
    if (in_array($value, $this->active_values)) {
      $is_active = TRUE;
    }
    return $is_active;
  }
  public function getFacetSources($only_enabled = FALSE) {
    if (!isset($this->facetSourcePlugins)) {
      $this->facetSourcePlugins = [];

      /** @var $facet_source_plugin_manager \Drupal\facets\FacetSource\FacetSourcePluginManager */
      $facet_source_plugin_manager = \Drupal::service('plugin.manager.facets.facet_source');

      foreach ($facet_source_plugin_manager->getDefinitions() as $name => $facet_source_definition) {
        if (class_exists($facet_source_definition['class']) && empty($this->facetSourcePlugins[$name])) {
          // Create our settings for this facet source..
          $config = isset($this->facetSourcePlugins[$name]) ? $this->facetSourcePlugins[$name] : [];

          /** @var $facet_source \Drupal\facets\FacetSource\FacetSourceInterface */
          $facet_source = $facet_source_plugin_manager->createInstance($name, $config);
          $this->facetSourcePlugins[$name] = $facet_source;
        }
        elseif (!class_exists($facet_source_definition['class'])) {
          \Drupal::logger('facets')->warning('Facet Source @id specifies a non-existing @class.', ['@id' => $name, '@class' => $facet_source_definition['class']]);
        }
      }
    }

    // Filter datasources by status if required.
    if (!$only_enabled) {
      return $this->facetSourcePlugins;
    }

    return array_intersect_key($this->facetSourcePlugins, array_flip($this->facetSourcePlugins));
  }

  /**
   * {@inheritdoc}
   */
  public function getProcessors($only_enabled = TRUE) {
    $processors = $this->loadProcessors();

    // Filter processors by status if required. Enabled processors are those
    // which have settings in the "processors" option.
    if ($only_enabled) {
      $processors_settings = $this->getOption('processors', array());
      $processors = array_intersect_key($processors, $processors_settings);
    }

    return $processors;
  }

  /**
   * {@inheritdoc}
   */
  public function getProcessorsByStage($stage, $only_enabled = TRUE) {
    $processors = $this->loadProcessors();
    $processor_settings = $this->getOption('processors', array());
    $processor_weights = array();

    // Get a list of all processors meeting the criteria (stage and, optionally,
    // enabled) along with their effective weights (user-set or default).
    foreach ($processors as $name => $processor) {
      if ($processor->supportsStage($stage) && !($only_enabled && empty($processor_settings[$name]))) {
        if (!empty($processor_settings[$name]['weights'][$stage])) {
          $processor_weights[$name] = $processor_settings[$name]['weights'][$stage];
        }
        else {
          $processor_weights[$name] = $processor->getDefaultWeight($stage);
        }
      }
    }

    // Sort requested processors by weight.
    asort($processor_weights);

    $return_processors = array();
    foreach ($processor_weights as $name => $weight) {
      $return_processors[$name] = $processors[$name];
    }
    return $return_processors;
  }

  /**
   * {@inheritdoc}
   */
  public function setOnlyVisibleWhenFacetSourceIsVisible($only_visible_when_facet_source_is_visible) {
    $this->only_visible_when_facet_source_is_visible = $only_visible_when_facet_source_is_visible;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getOnlyVisibleWhenFacetSourceIsVisible() {
    return $this->only_visible_when_facet_source_is_visible;
  }