From 35a1e2defd0710ecf1a9f5e322fae1dbe3f30feb Mon Sep 17 00:00:00 2001
From: Neil Drumm <drumm@delocalizedham.com>
Date: Wed, 11 Jun 2025 13:12:21 -0400
Subject: [PATCH 1/7] =?UTF-8?q?Add=20checking=20for=20view=20unpublished?=
 =?UTF-8?q?=20=E2=80=A6=20content?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 drupalorg.module                              | 17 ++++++++
 .../views/filter/DrupalOrgNodeStatus.php      | 41 +++++++++++++++++++
 2 files changed, 58 insertions(+)
 create mode 100644 src/Plugin/views/filter/DrupalOrgNodeStatus.php

diff --git a/drupalorg.module b/drupalorg.module
index a432022f8..6abef86ec 100644
--- a/drupalorg.module
+++ b/drupalorg.module
@@ -588,6 +588,23 @@ function drupalorg_entity_field_access($operation, FieldDefinitionInterface $fie
   return AccessResult::neutral();
 }
 
+/**
+ * Implements hook_views_data_alter().
+ */
+function drupalorg_views_data_alter(array &$data) {
+  $data['node_field_data']['drupalorg_node_status'] = [
+    'title' => t('Published status or admin user (Drupal.org)'),
+    'help' => t('Filters out unpublished content if the current user cannot view it, including “view unpublished … content” access.'),
+    'filter' => [
+      'field' => 'status',
+      'id' => 'drupalorg_node_status',
+      'label' => t('Published status, admin user, or allowed unpublished content.'),
+    ],
+  ];
+
+  $data['node_field_data']['status_extra']['filter']['id'] = 'drupalorg_node_status';
+}
+
 // Workaround for missing dependency error caused from the project module not
 // being ported.
 // Impacts node.field_issue_sa_version and node.field_issue_version.
diff --git a/src/Plugin/views/filter/DrupalOrgNodeStatus.php b/src/Plugin/views/filter/DrupalOrgNodeStatus.php
new file mode 100644
index 000000000..7898ce94c
--- /dev/null
+++ b/src/Plugin/views/filter/DrupalOrgNodeStatus.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Drupal\drupalorg\Plugin\views\filter;
+
+use Drupal;
+use Drupal\node\Entity\NodeType;
+use Drupal\node\Plugin\views\filter\Status;
+use Drupal\views\Attribute\ViewsFilter;
+
+/**
+ * Filter by published status.
+ *
+ * @ingroup views_filter_handlers
+ */
+#[ViewsFilter("drupalorg_node_status")]
+class DrupalOrgNodeStatus extends Status {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $table = $this->ensureMyTable();
+    $snippet = "$table.status = 1 OR ($table.uid = ***CURRENT_USER*** AND ***CURRENT_USER*** <> 0 AND ***VIEW_OWN_UNPUBLISHED_NODES*** = 1) OR ***BYPASS_NODE_ACCESS*** = 1";
+    if ($this->moduleHandler->moduleExists('content_moderation')) {
+      $snippet .= ' OR ***VIEW_ANY_UNPUBLISHED_NODES*** = 1';
+    }
+
+    $args[':unpublished_type_access[]'] = [];
+    foreach (array_keys(NodeType::loadMultiple()) as $node_type_id) {
+      if (Drupal::currentUser()->hasPermission("view any unpublished $node_type_id content")) {
+        $args[':unpublished_type_access[]'][] = $node_type_id;
+      }
+    }
+    if (!empty($args[':unpublished_type_access[]'])) {
+      $snippet .= ' OR ' . $table . '.type IN (:unpublished_type_access[])';
+    }
+
+    $this->query->addWhereExpression($this->options['group'], $snippet, $args);
+  }
+
+}
-- 
GitLab


From 6479350beed1c370b3d287a0ef583f887e5b2aca Mon Sep 17 00:00:00 2001
From: Neil Drumm <drumm@delocalizedham.com>
Date: Wed, 11 Jun 2025 13:36:29 -0400
Subject: [PATCH 2/7] Remove unused use

---
 drupalorg.module | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drupalorg.module b/drupalorg.module
index 6abef86ec..1b39daa90 100644
--- a/drupalorg.module
+++ b/drupalorg.module
@@ -5,7 +5,6 @@
  * Drupal.org Custom Migrations.
  */
 
-use Drupal\Component\Utility\Xss;
 use Drupal\Core\Entity\EntityForm;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
-- 
GitLab


From 277073c8d15236eecdcfcb9a91fef17438853c65 Mon Sep 17 00:00:00 2001
From: Neil Drumm <drumm@delocalizedham.com>
Date: Wed, 11 Jun 2025 13:39:44 -0400
Subject: [PATCH 3/7] Remove deleted role

---
 drupalorg.permissions.yml | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drupalorg.permissions.yml b/drupalorg.permissions.yml
index 4f03cbdfd..58ebe5dcc 100644
--- a/drupalorg.permissions.yml
+++ b/drupalorg.permissions.yml
@@ -229,12 +229,6 @@ manage security releases:
 #  translate content
 #  use panels in place editing
 #  view any unpublished book_listing content
-#Permissions of user role: "Packaging whitelist maintainer":
-#  bypass honeypot protection
-#  delete terms in 58
-#  edit terms in 58
-#  pift re-test files
-#  setup own tfa
 #Permissions of user role: "security team":
 #  administer multiple emails
 #  administer projects
-- 
GitLab


From 0f8e62d3646898cd3fd34d4e9c7f848bdf0991bb Mon Sep 17 00:00:00 2001
From: Neil Drumm <drumm@delocalizedham.com>
Date: Wed, 11 Jun 2025 14:07:28 -0400
Subject: [PATCH 4/7] Use dependency injection

---
 .../views/filter/DrupalOrgNodeStatus.php      | 31 +++++++++++++++++--
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/src/Plugin/views/filter/DrupalOrgNodeStatus.php b/src/Plugin/views/filter/DrupalOrgNodeStatus.php
index 7898ce94c..ebace9958 100644
--- a/src/Plugin/views/filter/DrupalOrgNodeStatus.php
+++ b/src/Plugin/views/filter/DrupalOrgNodeStatus.php
@@ -1,11 +1,14 @@
 <?php
+declare(strict_types=1);
 
 namespace Drupal\drupalorg\Plugin\views\filter;
 
-use Drupal;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Session\AccountInterface;
 use Drupal\node\Entity\NodeType;
 use Drupal\node\Plugin\views\filter\Status;
 use Drupal\views\Attribute\ViewsFilter;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Filter by published status.
@@ -13,7 +16,29 @@ use Drupal\views\Attribute\ViewsFilter;
  * @ingroup views_filter_handlers
  */
 #[ViewsFilter("drupalorg_node_status")]
-class DrupalOrgNodeStatus extends Status {
+class DrupalOrgNodeStatus extends Status implements ContainerFactoryPluginInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('current_user'),
+    );
+  }
+
+  /**
+   * AllowedContentTypes constructor.
+   *
+   * @param \Drupal\Core\Session\AccountInterface $currentUser
+   *   The current user.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, private readonly AccountInterface $currentUser) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+  }
 
   /**
    * {@inheritdoc}
@@ -27,7 +52,7 @@ class DrupalOrgNodeStatus extends Status {
 
     $args[':unpublished_type_access[]'] = [];
     foreach (array_keys(NodeType::loadMultiple()) as $node_type_id) {
-      if (Drupal::currentUser()->hasPermission("view any unpublished $node_type_id content")) {
+      if ($this->currentUser->hasPermission("view any unpublished $node_type_id content")) {
         $args[':unpublished_type_access[]'][] = $node_type_id;
       }
     }
-- 
GitLab


From 676ecd1c88b21e307397b659fa6289a9f568b6ce Mon Sep 17 00:00:00 2001
From: Neil Drumm <drumm@delocalizedham.com>
Date: Wed, 11 Jun 2025 14:14:20 -0400
Subject: [PATCH 5/7] Coding standards

---
 src/Plugin/views/filter/DrupalOrgNodeStatus.php | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/Plugin/views/filter/DrupalOrgNodeStatus.php b/src/Plugin/views/filter/DrupalOrgNodeStatus.php
index ebace9958..62611b834 100644
--- a/src/Plugin/views/filter/DrupalOrgNodeStatus.php
+++ b/src/Plugin/views/filter/DrupalOrgNodeStatus.php
@@ -1,4 +1,5 @@
 <?php
+
 declare(strict_types=1);
 
 namespace Drupal\drupalorg\Plugin\views\filter;
@@ -31,10 +32,7 @@ class DrupalOrgNodeStatus extends Status implements ContainerFactoryPluginInterf
   }
 
   /**
-   * AllowedContentTypes constructor.
-   *
-   * @param \Drupal\Core\Session\AccountInterface $currentUser
-   *   The current user.
+   * {@inheritdoc}
    */
   public function __construct(array $configuration, $plugin_id, $plugin_definition, private readonly AccountInterface $currentUser) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
-- 
GitLab


From 437a2818fc177a549a4f6306f2e7891fea12bc89 Mon Sep 17 00:00:00 2001
From: Neil Drumm <drumm@delocalizedham.com>
Date: Wed, 11 Jun 2025 14:32:49 -0400
Subject: [PATCH 6/7] Formatting

---
 src/Plugin/views/filter/DrupalOrgNodeStatus.php | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/Plugin/views/filter/DrupalOrgNodeStatus.php b/src/Plugin/views/filter/DrupalOrgNodeStatus.php
index 62611b834..9ea13d975 100644
--- a/src/Plugin/views/filter/DrupalOrgNodeStatus.php
+++ b/src/Plugin/views/filter/DrupalOrgNodeStatus.php
@@ -48,7 +48,9 @@ class DrupalOrgNodeStatus extends Status implements ContainerFactoryPluginInterf
       $snippet .= ' OR ***VIEW_ANY_UNPUBLISHED_NODES*** = 1';
     }
 
-    $args[':unpublished_type_access[]'] = [];
+    $args = [
+      ':unpublished_type_access[]' => [],
+    ];
     foreach (array_keys(NodeType::loadMultiple()) as $node_type_id) {
       if ($this->currentUser->hasPermission("view any unpublished $node_type_id content")) {
         $args[':unpublished_type_access[]'][] = $node_type_id;
-- 
GitLab


From ca87cc521d35db6d93c4d1a0bdaa0320917d89d4 Mon Sep 17 00:00:00 2001
From: Neil Drumm <drumm@delocalizedham.com>
Date: Wed, 11 Jun 2025 16:17:30 -0400
Subject: [PATCH 7/7] Do not silently override core-provided filter

---
 drupalorg.module | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drupalorg.module b/drupalorg.module
index 1b39daa90..c8b0e8c8e 100644
--- a/drupalorg.module
+++ b/drupalorg.module
@@ -600,8 +600,6 @@ function drupalorg_views_data_alter(array &$data) {
       'label' => t('Published status, admin user, or allowed unpublished content.'),
     ],
   ];
-
-  $data['node_field_data']['status_extra']['filter']['id'] = 'drupalorg_node_status';
 }
 
 // Workaround for missing dependency error caused from the project module not
-- 
GitLab