Skip to content

Commit cb4b363

Browse files
committed
Finalize entity query support
1 parent f828090 commit cb4b363

File tree

1 file changed

+39
-8
lines changed

1 file changed

+39
-8
lines changed

src/Entity/Query/Query.php

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,26 +86,51 @@ public function execute() {
8686
// result because this function gets called.
8787
$all_records = $this->getFromStorage();
8888

89-
// @todo Proper entity query support that is aligned with the implementation
90-
// in \Drupal\Core\Entity\Query\Sql\Query::prepare() can be only added
91-
// if the following Entity API module issue is solved.
89+
// Be consistent with \Drupal\Core\Entity\Query\Sql\Query::prepare().
90+
// Add and fire special entity query tags.
91+
// @todo This fix can be only merged after the fix in the following issue
92+
// is available in a tagged release of entity.module.
9293
// https://www.drupal.org/project/entity/issues/3332956
94+
// The minimum required entity.module version also MUST be bumped as part
95+
// of this fix.
9396
// (Having a fix for a similar Group module issue is a nice to have,
9497
// https://www.drupal.org/project/group/issues/3332963.)
98+
$this->addTag('entity_query');
99+
$this->addTag('entity_query_' . $this->entityTypeId);
100+
95101
if ($this->accessCheck) {
102+
// We do not just add a tag but ensure that only those Apigee entities
103+
// are returned that the entity access API grants view access.
104+
// (Storage level filtering is not available or way too limited.)
105+
$this->addTag($this->entityTypeId . '_access');
106+
96107
// Read meta-data from query, if provided.
97108
if (!$account = $this->getMetaData('account')) {
98-
// @todo DI dependency.
99109
$account = \Drupal::currentUser();
100110
}
111+
101112
$cacheability = CacheableMetadata::createFromRenderArray([]);
102-
$all_records = array_filter($all_records, static function (EntityInterface $entity) use ($cacheability, $account) {
113+
$viewable_entity_ids = array_reduce($all_records, static function (array $carry, EntityInterface $entity) use ($cacheability, $account) {
103114
// Bubble up cacheability information even from a revoked access result.
104115
$result = $entity->access('view', $account, TRUE);
105116
$cacheability->addCacheableDependency($result);
106-
return $result->isAllowed();
107-
});
108-
// @todo DI dependencies.
117+
if ($result->isAllowed()) {
118+
$carry[] = $entity->id();
119+
}
120+
return $carry;
121+
}, []);
122+
123+
// We deliberately add conditions to the original entity query instead
124+
// of pre-filtering all records because query conditions are visible
125+
// in hook_query_TAG_alter() implementations for downstream developers.
126+
if (empty($viewable_entity_ids)) {
127+
// Add an always false condition. A persisted entity's primary id
128+
// cannot be null.
129+
$this->condition->notExists($this->entityType->getKey('id'));
130+
}
131+
else {
132+
$this->condition->condition($this->entityType->getKey('id'), $viewable_entity_ids, 'IN');
133+
}
109134
/** @var \Symfony\Component\HttpFoundation\Request $request */
110135
$request = \Drupal::requestStack()->getCurrentRequest();
111136
$renderer = \Drupal::service('renderer');
@@ -116,6 +141,12 @@ public function execute() {
116141
}
117142
}
118143

144+
$hooks = ['query'];
145+
foreach ($this->alterTags as $tag => $value) {
146+
$hooks[] = 'query_' . $tag;
147+
}
148+
\Drupal::moduleHandler()->alter($hooks, $this);
149+
119150
$filter = $this->condition->compile($this);
120151
$result = array_filter($all_records, $filter);
121152

0 commit comments

Comments
 (0)