@@ -88,6 +88,11 @@ abstract class EdgeEntityStorageBase extends DrupalEntityStorageBase implements
8888 */
8989 protected $ systemTime ;
9090
91+ /**
92+ * Indicates that all entities should be/have been loaded in this request.
93+ */
94+ private bool $ allEntitiesHaveBeenLoaded = FALSE ;
95+
9196 /**
9297 * Constructs an EdgeEntityStorageBase instance.
9398 *
@@ -491,10 +496,48 @@ public function resetCache(?array $ids = NULL) {
491496 Cache::invalidateTags ([$ this ->entityTypeId . ':values ' ]);
492497 }
493498 }
499+ // When resetting cache for ANY of the entities, cache entry for ALL
500+ // entities MUST also be cleared to prevent cache poisoning eg. after a
501+ // loadMultiple(); save(); loadMultiple(); cycle.
502+ $ this ->memoryCache ->delete ($ this ->entityTypeId . '-all-entity-ids ' );
494503 // We do not clear the entity controller's cache here because our main goal
495504 // with the entity controller cache to reduce the API calls that we
496505 // send to Apigee Edge. Although we do delete the entity controller's cache
497506 // when it is necessary, like in loadUnchanged().
498507 }
499508
509+ /**
510+ * {@inheritdoc}
511+ */
512+ public function loadMultiple (?array $ ids = NULL ) {
513+ // Without $ids the caller wants to load ALL entities. To speed things up,
514+ // let's assume the storage does not change during a page load; IOW, load
515+ // all the entities for the first time and store them in a memory cache.
516+ // For all subsequent calls for the same page load, return entities from
517+ // that memory cache instead (without making API calls to Apigee).
518+ if ($ ids === NULL ) {
519+ $ all_known_entity_ids = $ this ->memoryCache ->get ($ this ->entityTypeId . '-all-entity-ids ' );
520+ if ($ all_known_entity_ids !== FALSE ) {
521+ return parent ::loadMultiple ($ all_known_entity_ids ->data );
522+ }
523+ $ this ->allEntitiesHaveBeenLoaded = TRUE ;
524+ $ return = parent ::loadMultiple ($ ids );
525+ $ this ->allEntitiesHaveBeenLoaded = FALSE ;
526+ return $ return ;
527+ }
528+
529+ return parent ::loadMultiple ($ ids );
530+ }
531+
532+ /**
533+ * {@inheritdoc}
534+ */
535+ protected function setStaticCache (array $ entities ) {
536+ if ($ this ->allEntitiesHaveBeenLoaded ) {
537+ $ ids = array_map (static fn (DrupalEdgeEntityInterface $ entity ) => $ entity ->id (), $ entities );
538+ $ this ->memoryCache ->set ($ this ->entityTypeId . '-all-entity-ids ' , $ ids );
539+ }
540+ parent ::setStaticCache ($ entities );
541+ }
542+
500543}
0 commit comments