diff --git a/composer.json b/composer.json index e5a7c02..cb295c8 100644 --- a/composer.json +++ b/composer.json @@ -10,5 +10,7 @@ "issues": "http://drupal.org/project/taxonomy_menu", "source": "http://cgit.drupalcode.org/taxonomy_menu" }, - "require": { } + "require": { + "drupal/taxonomy_entity_index": "^1.7" + } } diff --git a/config/schema/taxonomy_menu.schema.yml b/config/schema/taxonomy_menu.schema.yml index 91f73c0..ebdd60d 100644 --- a/config/schema/taxonomy_menu.schema.yml +++ b/config/schema/taxonomy_menu.schema.yml @@ -29,3 +29,6 @@ taxonomy_menu.taxonomy_menu.*: use_term_weight_order: type: boolean label: 'Use term weight order' + hide_empty_terms: + type: boolean + label: 'Hide empty terms' diff --git a/src/Entity/TaxonomyMenu.php b/src/Entity/TaxonomyMenu.php index c46593d..e307099 100644 --- a/src/Entity/TaxonomyMenu.php +++ b/src/Entity/TaxonomyMenu.php @@ -43,7 +43,8 @@ use Drupal\taxonomy_menu\TaxonomyMenuInterface; * "expanded", * "menu_parent", * "description_field_name", - * "use_term_weight_order" + * "use_term_weight_order", + * "hide_empty_terms" * } * ) */ @@ -108,6 +109,13 @@ class TaxonomyMenu extends ConfigEntityBase implements TaxonomyMenuInterface { */ protected $description_field_name; + /** + * The hide empty mode. + * + * @var bool + */ + public $hide_empty_terms; + /** * {@inheritdoc} */ @@ -202,7 +210,6 @@ class TaxonomyMenu extends ConfigEntityBase implements TaxonomyMenuInterface { $terms = $termStorage->loadTree($this->getVocabulary(), 0, $this->getDepth() + 1); $links = []; - // Create menu links for each term in the vocabulary. foreach ($terms as $term) { if (!$term instanceof TermInterface) { @@ -211,6 +218,12 @@ class TaxonomyMenu extends ConfigEntityBase implements TaxonomyMenuInterface { $mlid = $this->buildMenuPluginId($term, $include_base_plugin_id); $links[$mlid] = $this->buildMenuDefinition($term, $base_plugin_definition); + if ($this->hide_empty_terms) { + $child_terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($this->getVocabulary(), $term->id()); + if ((count($child_terms) > 0 && !$this->childTermUsed($term->id())) || !$this->termUsed($term->id())) { + $links[$mlid]['enabled'] = 0; + } + } } return $links; @@ -307,5 +320,74 @@ class TaxonomyMenu extends ConfigEntityBase implements TaxonomyMenuInterface { return $link; } + /** + * Get the number of nodes for given term. + * + * @param int $tid + * A taxonomy term id. + * + * @return int + * The number of nodes the given term is on. + */ + private function termUsed($tid) { + $entity_types = \Drupal::config('taxonomy_entity_index.settings')->get('types'); + + if (empty($entity_types)) { + return FALSE; + } + + foreach ($entity_types as $entity_type) { + $ids = \Drupal::database()->select('taxonomy_entity_index', 'tn') + ->fields('tn', ['entity_id']) + ->condition('tid', $tid) + ->condition('entity_type', $entity_type) + ->execute() + ->fetchCol(); + + if (!$ids) { + continue; + } + + $storage = \Drupal::entityTypeManager()->getStorage($entity_type); + $id_key = $storage->getEntityType()->getKey('id'); + $count = (int) $storage->getQuery() + ->condition('status', 1) + ->condition($id_key, $ids, 'IN') + ->accessCheck(TRUE) + ->count() + ->execute(); + + if ($count > 0) { + return TRUE; + } + } + + return FALSE; + } + + /** + * Check taxonomy term if children terms have data or not. + * + * @param int $tid + * A taxonomy term id. + * + * @return int + * The number of nodes the given term is on. + */ + private function childTermUsed($tid) { + // 1 to get only immediate children, NULL to load entire tree. + $depth = 1; + $usedChildTerms = []; + $child_terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($this->getVocabulary(), $tid, $depth); + foreach ($child_terms as $child_term) { + $usedChildTerms[] = $this->termUsed($child_term->tid); + } + if (in_array(TRUE, $usedChildTerms)) { + return TRUE; + } + else { + return FALSE; + } + } } diff --git a/src/Form/TaxonomyMenuForm.php b/src/Form/TaxonomyMenuForm.php index bfc52d2..89f88f8 100644 --- a/src/Form/TaxonomyMenuForm.php +++ b/src/Form/TaxonomyMenuForm.php @@ -177,6 +177,12 @@ class TaxonomyMenuForm extends EntityForm { '#default_value' => $taxonomy_menu->use_term_weight_order ?? TRUE, ]; + $form['hide_empty_terms'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Hide empty terms'), + '#default_value' => isset($taxonomy_menu->hide_empty_terms) ? $taxonomy_menu->hide_empty_terms : TRUE, + ]; + return $form; } diff --git a/taxonomy_menu.info.yml b/taxonomy_menu.info.yml index 18ff49d..0af6752 100644 --- a/taxonomy_menu.info.yml +++ b/taxonomy_menu.info.yml @@ -4,6 +4,8 @@ description: Embed a taxonomy tree into a menu core_version_requirement: ^9.1 || ^10 package: Menu configure: entity.taxonomy_menu.collection +dependencies: + - taxonomy_entity_index:taxonomy_entity_index # Information added by Drupal.org packaging script on 2023-02-22 version: '8.x-3.6'