diff --git a/src/Entity/Facet.php b/src/Entity/Facet.php index 889a074..3c6e1ce 100644 --- a/src/Entity/Facet.php +++ b/src/Entity/Facet.php @@ -215,13 +215,19 @@ class Facet extends ConfigEntityBase implements FacetInterface { /** * {@inheritdoc} */ - public function getDescription() { - return $this->description; + protected function urlRouteParameters($rel) { + $parameters = parent::urlRouteParameters($rel); + return $parameters; } /** * {@inheritdoc} */ + public function getDescription() { + return $this->description; + } /** + * {@inheritdoc} + */ public function setWidget($widget) { $this->widget = $widget; return $this; @@ -230,11 +236,49 @@ class Facet extends ConfigEntityBase implements FacetInterface { /** * {@inheritdoc} */ + public function getQueryTypes() { + return $this->query_type_name; + } /** + * {@inheritdoc} + */ public function getWidget() { return $this->widget; } /** + * 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'); + $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. + $settings = empty($processor_settings[$name]['settings']) ? [] : $processor_settings[$name]['settings']; + $settings['facet'] = $this; + + /* @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'] + )); + } + } + } + + return $this->processors; + } /** * {@inheritdoc} */ public function getQueryType() { @@ -252,6 +296,13 @@ class Facet extends ConfigEntityBase implements FacetInterface { /** * {@inheritdoc} */ + public function getQueryOperator() { + return $this->getOption('query_operator', 'OR'); + } + + /** + * {@inheritdoc} + */ public function getFieldAlias() { // For now, create the field alias based on the field identifier. $field_alias = preg_replace('/[:\/]+/', '_', $this->field_identifier); @@ -319,12 +370,7 @@ class Facet extends ConfigEntityBase implements FacetInterface { return $this; } - /** - * {@inheritdoc} - */ - public function getQueryTypes() { - return $this->query_type_name; - } + /** * {@inheritdoc} @@ -370,44 +416,9 @@ class Facet extends ConfigEntityBase implements FacetInterface { 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'); - $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. - $settings = empty($processor_settings[$name]['settings']) ? [] : $processor_settings[$name]['settings']; - $settings['facet'] = $this; - /* @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'])); - } - } - } - return $this->processors; - } - - /** - * {@inheritdoc} - */ - protected function urlRouteParameters($rel) { - $parameters = parent::urlRouteParameters($rel); - return $parameters; - } /** * {@inheritdoc} @@ -463,7 +474,11 @@ class Facet extends ConfigEntityBase implements FacetInterface { $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']]); + \Drupal::logger('facets') + ->warning('Facet Source @id specifies a non-existing @class.', [ + '@id' => $name, + '@class' => $facet_source_definition['class'] + ]); } } } diff --git a/src/FacetInterface.php b/src/FacetInterface.php index 7e39f2a..fdbdc80 100644 --- a/src/FacetInterface.php +++ b/src/FacetInterface.php @@ -122,6 +122,14 @@ interface FacetInterface extends ConfigEntityInterface { public function getQueryType(); /** + * Get the query operator. + * + * @return string + * The query operator being used. + */ + public function getQueryOperator(); + + /** * Get the plugin name for the url processor. * * @return string diff --git a/src/Form/FacetDisplayForm.php b/src/Form/FacetDisplayForm.php index d55dfe1..a138309 100644 --- a/src/Form/FacetDisplayForm.php +++ b/src/Form/FacetDisplayForm.php @@ -352,6 +352,15 @@ class FacetDisplayForm extends EntityForm { '#default_value' => isset($empty_behavior_config['text_format']) ? $empty_behavior_config['text'] : '', ]; + // Query operator. + $form['facet_settings']['query_operator'] = [ + '#type' => 'radios', + '#title' => $this->t('Operator'), + '#options' => ['OR' => $this->t('OR'), 'AND' => $this->t('AND')], + '#description' => $this->t('AND filters are exclusive and narrow the result set. OR filters are inclusive and widen the result set.'), + '#default_value' => $facet->getQueryOperator(), + ]; + $form['weights'] = array( '#type' => 'details', '#title' => t('Advanced settings'), @@ -529,6 +538,8 @@ class FacetDisplayForm extends EntityForm { } $facet->setOption('empty_behavior', $empty_behavior_config); + $facet->setOption('query_operator', $form_state->getValue(['facet_settings', 'query_operator'])); + $facet->save(); drupal_set_message(t('Facet %name has been updated.', ['%name' => $facet->getName()])); } diff --git a/src/Plugin/facets/query_type/SearchApiString.php b/src/Plugin/facets/query_type/SearchApiString.php index c44d0bb..fab8010 100644 --- a/src/Plugin/facets/query_type/SearchApiString.php +++ b/src/Plugin/facets/query_type/SearchApiString.php @@ -44,6 +44,7 @@ class SearchApiString extends QueryTypePluginBase { // Alter the query here. if (!empty($query)) { $options = &$query->getOptions(); + $operator = $this->facet->getQueryOperator(); $field_identifier = $this->facet->getFieldIdentifier(); $options['search_api_facets'][$field_identifier] = array( @@ -56,12 +57,13 @@ class SearchApiString extends QueryTypePluginBase { // Add the filter to the query if there are active values. $active_items = $this->facet->getActiveItems(); + if (count($active_items)) { + $filter = $query->createConditionGroup($operator); foreach ($active_items as $value) { - $filter = $query->createConditionGroup(); $filter->addCondition($this->facet->getFieldIdentifier(), $value); - $query->addConditionGroup($filter); } + $query->addConditionGroup($filter); } } }