diff --git a/drupalorg.module b/drupalorg.module index a432022f88f6f550d3ad8625d2c2320260cd7a47..c8b0e8c8e8453edbe6befb43c37810ce4ae7645b 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; @@ -588,6 +587,21 @@ 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.'), + ], + ]; +} + // 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/drupalorg.permissions.yml b/drupalorg.permissions.yml index 4f03cbdfd1b4ab19bb9635c238c07ee6c7fe0cbe..58ebe5dcc2828d91d61caaa9dd26e7c2d7068aa0 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 diff --git a/src/Plugin/views/filter/DrupalOrgNodeStatus.php b/src/Plugin/views/filter/DrupalOrgNodeStatus.php new file mode 100644 index 0000000000000000000000000000000000000000..9ea13d9752d5f0f2b62f7a4940f2fc7ac3218eee --- /dev/null +++ b/src/Plugin/views/filter/DrupalOrgNodeStatus.php @@ -0,0 +1,66 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\drupalorg\Plugin\views\filter; + +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. + * + * @ingroup views_filter_handlers + */ +#[ViewsFilter("drupalorg_node_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'), + ); + } + + /** + * {@inheritdoc} + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, private readonly AccountInterface $currentUser) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + } + + /** + * {@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 ($this->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); + } + +}