@@ -86,26 +86,51 @@ public function execute() {
86
86
// result because this function gets called.
87
87
$ all_records = $ this ->getFromStorage ();
88
88
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.
92
93
// 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.
93
96
// (Having a fix for a similar Group module issue is a nice to have,
94
97
// https://www.drupal.org/project/group/issues/3332963.)
98
+ $ this ->addTag ('entity_query ' );
99
+ $ this ->addTag ('entity_query_ ' . $ this ->entityTypeId );
100
+
95
101
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
+
96
107
// Read meta-data from query, if provided.
97
108
if (!$ account = $ this ->getMetaData ('account ' )) {
98
- // @todo DI dependency.
99
109
$ account = \Drupal::currentUser ();
100
110
}
111
+
101
112
$ 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 ) {
103
114
// Bubble up cacheability information even from a revoked access result.
104
115
$ result = $ entity ->access ('view ' , $ account , TRUE );
105
116
$ 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
+ }
109
134
/** @var \Symfony\Component\HttpFoundation\Request $request */
110
135
$ request = \Drupal::requestStack ()->getCurrentRequest ();
111
136
$ renderer = \Drupal::service ('renderer ' );
@@ -116,6 +141,12 @@ public function execute() {
116
141
}
117
142
}
118
143
144
+ $ hooks = ['query ' ];
145
+ foreach ($ this ->alterTags as $ tag => $ value ) {
146
+ $ hooks [] = 'query_ ' . $ tag ;
147
+ }
148
+ \Drupal::moduleHandler ()->alter ($ hooks , $ this );
149
+
119
150
$ filter = $ this ->condition ->compile ($ this );
120
151
$ result = array_filter ($ all_records , $ filter );
121
152
0 commit comments