From cd6a9cd55b2ca15feedda323f5f6c84194569d5e Mon Sep 17 00:00:00 2001 From: catch <catch@35733.no-reply.drupal.org> Date: Tue, 1 Sep 2020 09:30:32 +0100 Subject: [PATCH] Issue #3101738 by Lendude, jannakha, alexpott, daffie, catch, bkosborne, Berdir: Exposed term filters should not show term options that the user does not have access to (cherry picked from commit 6c878ed56ae89ecf375830b60a77309e9e3ed8b3) --- .../Plugin/views/filter/TaxonomyIndexTid.php | 26 ++++++++++++- .../Views/TaxonomyIndexTidUiTest.php | 37 +++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php index 5829681767c7..24352de93b74 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 @@ 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 @@ public static function create(ContainerInterface $container, array $configuratio $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 @@ protected function valueForm(&$form, FormStateInterface $form_state) { 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 @@ protected function valueForm(&$form, FormStateInterface $form_state) { ->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 1e1866753c4f..b7e26425bcab 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 @@ public function testExposedFilter() { $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() . '"]')); + } + } -- GitLab