diff --git a/config/schema/facets.facet.schema.yml b/config/schema/facets.facet.schema.yml index 238de7f..d5a5095 100644 --- a/config/schema/facets.facet.schema.yml +++ b/config/schema/facets.facet.schema.yml @@ -38,6 +38,9 @@ facets.facet.*: expand_hierarchy: type: boolean label: 'Expand hierarchy' + enable_parent_when_child_gets_disabled: + type: boolean + label: 'Enable parent when child gets disabled' widget: type: mapping label: 'Facet widget' diff --git a/core_search_facets/src/Plugin/facets/query_type/CoreNodeSearchDate.php b/core_search_facets/src/Plugin/facets/query_type/CoreNodeSearchDate.php index 7a83fb4..9312f34 100644 --- a/core_search_facets/src/Plugin/facets/query_type/CoreNodeSearchDate.php +++ b/core_search_facets/src/Plugin/facets/query_type/CoreNodeSearchDate.php @@ -114,7 +114,8 @@ class CoreNodeSearchDate extends QueryTypePluginBase { $result->setActiveState(TRUE); // Sets the children for the current parent.. if ($parent) { - $parent->setChildren($result); + $children = array_merge($parent->getChildren(), [$result]); + $parent->setChildren($children); } else { $parent = $parent_facet_results[] = $result; @@ -180,7 +181,8 @@ class CoreNodeSearchDate extends QueryTypePluginBase { $parent = end($parent_facet_results); if ($parent instanceof ResultInterface) { foreach ($facet_results as $result) { - $parent->setChildren($result); + $children = array_merge($parent->getChildren(), [$result]); + $parent->setChildren($children); $this->facet->setResults($parent_facet_results); } } diff --git a/css/hierarchical.css b/css/hierarchical.css new file mode 100644 index 0000000..1f26cbb --- /dev/null +++ b/css/hierarchical.css @@ -0,0 +1,7 @@ +.block-facets ul ul li { + margin-left: 10px; +} + +.facet-item--active-trail > a, .facet-item > a.is-active { + font-weight: bold; +} \ No newline at end of file diff --git a/facets.libraries.yml b/facets.libraries.yml index 643be6f..8e08f96 100644 --- a/facets.libraries.yml +++ b/facets.libraries.yml @@ -30,6 +30,12 @@ drupal.facets.checkbox-widget: - core/drupal - core/jquery.once +drupal.facets.hierarchical: + version: VERSION + css: + theme: + css/hierarchical.css: {} + drupal.facets.dropdown-widget: version: VERSION js: diff --git a/js/checkbox-widget.js b/js/checkbox-widget.js index 7506685..7ca1934 100644 --- a/js/checkbox-widget.js +++ b/js/checkbox-widget.js @@ -21,6 +21,8 @@ // Find all checkbox facet links and give them a checkbox. var $links = $('.js-facets-checkbox-links .facet-item a'); $links.once('facets-checkbox-transform').each(Drupal.facets.makeCheckbox); + // Set indeterminate value on parents having an active trail + $('.facet-item--expanded.facet-item--active-trail > input').prop("indeterminate", true); }; /** diff --git a/src/Entity/Facet.php b/src/Entity/Facet.php index ab15cb9..650d91b 100644 --- a/src/Entity/Facet.php +++ b/src/Entity/Facet.php @@ -43,6 +43,7 @@ use Drupal\facets\FacetInterface; * "query_operator", * "use_hierarchy", * "expand_hierarchy", + * "enable_parent_when_child_gets_disabled", * "exclude", * "only_visible_when_facet_source_is_visible", * "processor_configs", @@ -137,6 +138,13 @@ class Facet extends ConfigEntityBase implements FacetInterface { protected $expand_hierarchy; /** + * Wether or not parents should be enabled when a child gets disabled. + * + * @var bool + */ + protected $enable_parent_when_child_gets_disabled; + + /** * A boolean flag indicating if search should exclude selected facets. * * @var bool @@ -500,6 +508,20 @@ class Facet extends ConfigEntityBase implements FacetInterface { /** * {@inheritdoc} */ + public function setEnableParentWhenChildGetsDisabled($enable_parent_when_child_gets_disabled) { + return $this->enable_parent_when_child_gets_disabled = $enable_parent_when_child_gets_disabled; + } + + /** + * {@inheritdoc} + */ + public function getEnableParentWhenChildGetsDisabled() { + return isset($this->enable_parent_when_child_gets_disabled) ? $this->enable_parent_when_child_gets_disabled : true; + } + + /** + * {@inheritdoc} + */ public function setExclude($exclude) { return $this->exclude = $exclude; } diff --git a/src/FacetInterface.php b/src/FacetInterface.php index d4755a3..8c9d4ba 100644 --- a/src/FacetInterface.php +++ b/src/FacetInterface.php @@ -250,6 +250,25 @@ interface FacetInterface extends ConfigEntityInterface { public function setExpandHierarchy($expand_hierarchy); /** + * Returns the value of the enable_parent_when_child_gets_disabled boolean. + * + * This will return true when the parent item in the facet should be enabled + * in an hierarchical structure, when a child facet item gets disabled. + * + * @return bool + * Wether or not parents should be enabled when a child gets disabled. + */ + public function getEnableParentWhenChildGetsDisabled(); + + /** + * Sets the enable_parent_when_child_gets_disabled. + * + * @param bool $enable_parent_when_child_gets_disabled + * Wether or not parents should be enabled when a child gets disabled. + */ + public function setEnableParentWhenChildGetsDisabled($enable_parent_when_child_gets_disabled); + + /** * Returns the plugin name for the url processor. * * @return string diff --git a/src/Form/FacetForm.php b/src/Form/FacetForm.php index 97919ce..3fb5999 100644 --- a/src/Form/FacetForm.php +++ b/src/Form/FacetForm.php @@ -399,6 +399,18 @@ class FacetForm extends EntityForm { ), ]; + $form['facet_settings']['enable_parent_when_child_gets_disabled'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Enable parent when child gets disabled'), + '#description' => $this->t('Uncheck this if you want to allow de-activating an entire hierarchical trail by clicking an active child.'), + '#default_value' => $facet->getExpandHierarchy(), + '#states' => array( + 'visible' => array( + ':input[name="facet_settings[use_hierarchy]"]' => array('checked' => TRUE), + ), + ), + ]; + $form['facet_settings']['weight'] = [ '#type' => 'number', '#title' => $this->t('Weight'), @@ -602,6 +614,7 @@ class FacetForm extends EntityForm { $facet->setExclude($form_state->getValue(['facet_settings', 'exclude'])); $facet->setUseHierarchy($form_state->getValue(['facet_settings', 'use_hierarchy'])); $facet->setExpandHierarchy($form_state->getValue(['facet_settings', 'expand_hierarchy'])); + $facet->setEnableParentWhenChildGetsDisabled($form_state->getValue(['facet_settings', 'enable_parent_when_child_gets_disabled'])); $facet->save(); drupal_set_message(t('Facet %name has been updated.', ['%name' => $facet->getName()])); diff --git a/src/Plugin/facets/url_processor/QueryString.php b/src/Plugin/facets/url_processor/QueryString.php index 1cbfcfd..5240c42 100644 --- a/src/Plugin/facets/url_processor/QueryString.php +++ b/src/Plugin/facets/url_processor/QueryString.php @@ -93,6 +93,13 @@ class QueryString extends UrlProcessorPluginBase { unset($filter_params[$key]); } } + if($facet->getEnableParentWhenChildGetsDisabled() && $facet->getUseHierarchy()){ + // Enable parent id again if exists. + $parent_ids = $facet->getHierarchyInstance()->getParentIds($result->getRawValue()); + if($parent_ids[0]){ + $filter_params[] = $this->urlAlias . self::SEPARATOR . $parent_ids[0]; + } + } } // If the value is not active, add the filter string. else { diff --git a/src/Plugin/facets/widget/LinksWidget.php b/src/Plugin/facets/widget/LinksWidget.php index fe8cba0..7898812 100644 --- a/src/Plugin/facets/widget/LinksWidget.php +++ b/src/Plugin/facets/widget/LinksWidget.php @@ -34,6 +34,9 @@ class LinksWidget extends WidgetPluginBase { $build['#attached']['library'][] = 'facets/soft-limit'; $build['#attached']['drupalSettings']['facets']['softLimit'][$facet->id()] = $soft_limit; } + if($facet->getUseHierarchy()){ + $build['#attached']['library'][] = 'facets/drupal.facets.hierarchical'; + } return $build; } diff --git a/tests/src/Unit/Plugin/widget/LinksWidgetTest.php b/tests/src/Unit/Plugin/widget/LinksWidgetTest.php index 027b83a..1ea7d00 100644 --- a/tests/src/Unit/Plugin/widget/LinksWidgetTest.php +++ b/tests/src/Unit/Plugin/widget/LinksWidgetTest.php @@ -179,7 +179,7 @@ class LinksWidgetTest extends UnitTestCase { $child = new Result('snake', 'Snake', 5); $original_results[1]->setActiveState(TRUE); - $original_results[1]->setChildren($child); + $original_results[1]->setChildren([$child]); $facet = new Facet([], 'facets_facet'); $facet->setResults($original_results); @@ -201,8 +201,8 @@ class LinksWidgetTest extends UnitTestCase { $this->assertEquals($value, $output['#items'][$index]['#title']); $this->assertEquals('link', $output['#items'][$index]['#type']); if ($index === 1) { - $this->assertEquals('active-trail', $output['#items'][$index]['#attributes']['class']); - $this->assertEquals(['facet-item', 'expanded'], $output['#items'][$index]['#wrapper_attributes']['class']); + $this->assertEquals('is-active', $output['#items'][$index]['#attributes']['class']); + $this->assertEquals(['facet-item', 'facet-item--expanded'], $output['#items'][$index]['#wrapper_attributes']['class']); } else { $this->assertEquals(['facet-item'], $output['#items'][$index]['#wrapper_attributes']['class']);