diff --git a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php index 5829681767c..24352de93b7 100644 --- a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php +++ b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php @@ -4,6 +4,7 @@ namespace Drupal\taxonomy\Plugin\views\filter; use Drupal\Core\Entity\Element\EntityAutocomplete; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Session\AccountInterface; use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\TermStorageInterface; use Drupal\taxonomy\VocabularyStorageInterface; @@ -38,6 +39,13 @@ class TaxonomyIndexTid extends ManyToOne { */ protected $termStorage; + /** + * The current user. + * + * @var \Drupal\Core\Session\AccountInterface + */ + protected $currentUser; + /** * Constructs a TaxonomyIndexTid object. * @@ -51,11 +59,18 @@ class TaxonomyIndexTid extends ManyToOne { * The vocabulary storage. * @param \Drupal\taxonomy\TermStorageInterface $term_storage * The term storage. + * @param \Drupal\Core\Session\AccountInterface $current_user + * The current user. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, VocabularyStorageInterface $vocabulary_storage, TermStorageInterface $term_storage) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, VocabularyStorageInterface $vocabulary_storage, TermStorageInterface $term_storage, AccountInterface $current_user = NULL) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->vocabularyStorage = $vocabulary_storage; $this->termStorage = $term_storage; + if (!$current_user) { + @trigger_error('The current_user service must be passed to ' . __NAMESPACE__ . '\TaxonomyIndexTid::__construct(). It was added in drupal:8.9.0 and will be required before drupal:10.0.0.', E_USER_DEPRECATED); + $current_user = \Drupal::service('current_user'); + } + $this->currentUser = $current_user; } /** @@ -67,7 +82,8 @@ class TaxonomyIndexTid extends ManyToOne { $plugin_id, $plugin_definition, $container->get('entity_type.manager')->getStorage('taxonomy_vocabulary'), - $container->get('entity_type.manager')->getStorage('taxonomy_term') + $container->get('entity_type.manager')->getStorage('taxonomy_term'), + $container->get('current_user') ); } @@ -181,6 +197,9 @@ class TaxonomyIndexTid extends ManyToOne { if ($tree) { foreach ($tree as $term) { + if (!$term->isPublished() && !$this->currentUser->hasPermission('administer taxonomy')) { + continue; + } $choice = new \stdClass(); $choice->option = [$term->id() => str_repeat('-', $term->depth) . \Drupal::service('entity.repository')->getTranslationFromContext($term)->label()]; $options[] = $choice; @@ -195,6 +214,9 @@ class TaxonomyIndexTid extends ManyToOne { ->sort('weight') ->sort('name') ->addTag('taxonomy_term_access'); + if (!$this->currentUser->hasPermission('administer taxonomy')) { + $query->condition('status', 1); + } if ($this->options['limit']) { $query->condition('vid', $vocabulary->id()); } diff --git a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php index eb0774abb3f..22845acd79d 100644 --- a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php +++ b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php @@ -231,4 +231,41 @@ class TaxonomyIndexTidUiTest extends UITestBase { $this->assertTrue(empty($preview), 'No results.'); } + /** + * Tests that an exposed taxonomy filter doesn't show unpublished terms. + */ + public function testExposedUnpublishedFilterOptions() { + $this->terms[1][0]->setUnpublished()->save(); + // Expose the filter. + $this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_taxonomy_index_tid/default/filter/tid', [], 'Expose filter'); + $edit = ['options[expose_button][checkbox][checkbox]' => TRUE]; + $this->drupalPostForm(NULL, $edit, 'Apply'); + $this->drupalPostForm(NULL, [], 'Save'); + // Make sure the unpublished term is shown to the admin user. + $this->drupalGet('test-filter-taxonomy-index-tid'); + $this->assertNotEmpty($this->cssSelect('option[value="' . $this->terms[0][0]->id() . '"]')); + $this->assertNotEmpty($this->cssSelect('option[value="' . $this->terms[1][0]->id() . '"]')); + $this->drupalLogout(); + $this->drupalGet('test-filter-taxonomy-index-tid'); + // Make sure the unpublished term isn't shown to the anonymous user. + $this->assertNotEmpty($this->cssSelect('option[value="' . $this->terms[0][0]->id() . '"]')); + $this->assertEmpty($this->cssSelect('option[value="' . $this->terms[1][0]->id() . '"]')); + + // Tests that the term also isn't shown when not showing hierarchy. + $this->drupalLogin($this->adminUser); + $edit = [ + 'options[hierarchy]' => FALSE, + ]; + $this->drupalPostForm('admin/structure/views/nojs/handler-extra/test_filter_taxonomy_index_tid/default/filter/tid', $edit, 'Apply'); + $this->drupalPostForm(NULL, [], 'Save'); + $this->drupalGet('test-filter-taxonomy-index-tid'); + $this->assertNotEmpty($this->cssSelect('option[value="' . $this->terms[0][0]->id() . '"]')); + $this->assertNotEmpty($this->cssSelect('option[value="' . $this->terms[1][0]->id() . '"]')); + $this->drupalLogout(); + $this->drupalGet('test-filter-taxonomy-index-tid'); + // Make sure the unpublished term isn't shown to the anonymous user. + $this->assertNotEmpty($this->cssSelect('option[value="' . $this->terms[0][0]->id() . '"]')); + $this->assertEmpty($this->cssSelect('option[value="' . $this->terms[1][0]->id() . '"]')); + } + }