From 78a5dc9743d0110e0cde69a08868f7cfee7241e5 Mon Sep 17 00:00:00 2001
From: Kristiaan Van den Eynde <kristiaan@factorial.io>
Date: Thu, 7 May 2020 13:33:39 +0200
Subject: [PATCH] Issue #3086409 by kristiaanvandeneynde: Provide a default
 query_access handler for core (maybe all?) entity types

---
 entity.module                                 | 13 +++
 src/QueryAccess/GenericQueryAccessHandler.php | 84 +++++++++++++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 src/QueryAccess/GenericQueryAccessHandler.php

diff --git a/entity.module b/entity.module
index a515a47..ed55cdd 100644
--- a/entity.module
+++ b/entity.module
@@ -67,6 +67,19 @@ function entity_entity_type_build(array &$entity_types) {
   }
 }
 
+/**
+ * Implements hook_entity_type_alter().
+ */
+function entity_entity_type_alter(array &$entity_types) {
+  /** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
+  // Sets a generic query_access handler for all entity types that have none.
+  foreach ($entity_types as $entity_type_id => $entity_type) {
+    if (!$entity_type->hasHandlerClass('query_access')) {
+      $entity_type->setHandlerClass('query_access', 'Drupal\entity\QueryAccess\GenericQueryAccessHandler');
+    }
+  }
+}
+
 /**
  * Implements hook_entity_bundle_info().
  */
diff --git a/src/QueryAccess/GenericQueryAccessHandler.php b/src/QueryAccess/GenericQueryAccessHandler.php
new file mode 100644
index 0000000..1913909
--- /dev/null
+++ b/src/QueryAccess/GenericQueryAccessHandler.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace Drupal\entity\QueryAccess;
+
+use Drupal\Core\Entity\EntityHandlerInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Session\AccountInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+/**
+ * Generic query access handler for entity types that do not have one.
+ *
+ * This query access handler only fires the alter event so that modules can
+ * subscribe to the query access alter event to alter any entity query or views
+ * query without having to duplicate the related code from Entity API.
+ */
+final class GenericQueryAccessHandler implements EntityHandlerInterface, QueryAccessHandlerInterface {
+
+  /**
+   * The entity type.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface
+   */
+  protected $entityType;
+
+  /**
+   * The event dispatcher.
+   *
+   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
+   */
+  protected $eventDispatcher;
+
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $currentUser;
+
+  /**
+   * Constructs a new QueryAccessHandlerBase object.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+   *   The entity type.
+   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
+   *   The event dispatcher.
+   * @param \Drupal\Core\Session\AccountInterface $current_user
+   *   The current user.
+   */
+  public function __construct(EntityTypeInterface $entity_type, EventDispatcherInterface $event_dispatcher, AccountInterface $current_user) {
+    $this->entityType = $entity_type;
+    $this->eventDispatcher = $event_dispatcher;
+    $this->currentUser = $current_user;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
+    return new static(
+      $entity_type,
+      $container->get('event_dispatcher'),
+      $container->get('current_user')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConditions($operation, AccountInterface $account = NULL) {
+    $account = $account ?: $this->currentUser;
+    $entity_type_id = $this->entityType->id();
+    $conditions = new ConditionGroup('OR');
+
+    // Allow other modules to modify the conditions before they are used.
+    $event = new QueryAccessEvent($conditions, $operation, $account, $entity_type_id);
+    $this->eventDispatcher->dispatch('entity.query_access', $event);
+    $this->eventDispatcher->dispatch("entity.query_access.{$entity_type_id}", $event);
+
+    return $conditions;
+  }
+
+}
-- 
2.17.1

