Issue #3068733 by blazey, amateescu, pmelab, hchonov: EntityStorageBase::loadMultiple returns unwanted entities when the static cache is warm

merge-requests/55/head
catch 2019-09-02 15:36:48 +01:00
parent fa95bb1d7d
commit c86caa0a89
2 changed files with 27 additions and 7 deletions

View File

@ -256,6 +256,7 @@ abstract class EntityStorageBase extends EntityHandlerBase implements EntityStor
*/ */
public function loadMultiple(array $ids = NULL) { public function loadMultiple(array $ids = NULL) {
$entities = []; $entities = [];
$preloaded_entities = [];
// Create a new variable which is either a prepared version of the $ids // Create a new variable which is either a prepared version of the $ids
// array for later comparison with the entity cache, or FALSE if no $ids // array for later comparison with the entity cache, or FALSE if no $ids
@ -271,16 +272,23 @@ abstract class EntityStorageBase extends EntityHandlerBase implements EntityStor
$ids = array_keys(array_diff_key($flipped_ids, $entities)); $ids = array_keys(array_diff_key($flipped_ids, $entities));
} }
// Gather entities from a 'preload' method. This method can invoke a hook to // Try to gather any remaining entities from a 'preload' method. This method
// be used by modules that need, for example, to swap the default revision // can invoke a hook to be used by modules that need, for example, to swap
// of an entity with a different one. Even though the base entity storage // the default revision of an entity with a different one. Even though the
// class does not actually invoke any preload hooks, we need to call the // base entity storage class does not actually invoke any preload hooks, we
// method here so we can add the pre-loaded entity objects to the static // need to call the method here so we can add the pre-loaded entity objects
// cache below. // to the static cache below. If all the entities were fetched from the
// static cache, skip this step.
if ($ids === NULL || $ids) {
$preloaded_entities = $this->preLoad($ids); $preloaded_entities = $this->preLoad($ids);
}
if (!empty($preloaded_entities)) { if (!empty($preloaded_entities)) {
$entities += $preloaded_entities; $entities += $preloaded_entities;
// If any entities were pre-loaded, remove them from the IDs still to
// load.
$ids = array_keys(array_diff_key($flipped_ids, $entities));
// Add pre-loaded entities to the cache. // Add pre-loaded entities to the cache.
$this->setStaticCache($preloaded_entities); $this->setStaticCache($preloaded_entities);
} }

View File

@ -708,6 +708,18 @@ class WorkspaceIntegrationTest extends KernelTestBase {
$this->assertEquals($expected_default_revision[$published_key], $entities[$entity_id]->isPublished()); $this->assertEquals($expected_default_revision[$published_key], $entities[$entity_id]->isPublished());
} }
// Check loading entities one by one. It is important to do these checks
// after the "multiple load" ones above so we can test with a fully warmed
// static cache.
foreach ($expected_default_revisions as $expected_default_revision) {
$entity_id = $expected_default_revision[$id_key];
$entities = $this->entityTypeManager->getStorage($entity_type_id)->loadMultiple([$entity_id]);
$this->assertCount(1, $entities);
$this->assertEquals($expected_default_revision[$revision_key], $entities[$entity_id]->getRevisionId());
$this->assertEquals($expected_default_revision[$label_key], $entities[$entity_id]->label());
$this->assertEquals($expected_default_revision[$published_key], $entities[$entity_id]->isPublished());
}
// Check \Drupal\Core\Entity\EntityStorageInterface::loadUnchanged(). // Check \Drupal\Core\Entity\EntityStorageInterface::loadUnchanged().
foreach ($expected_default_revisions as $expected_default_revision) { foreach ($expected_default_revisions as $expected_default_revision) {
/** @var \Drupal\Core\Entity\RevisionableInterface|\Drupal\Core\Entity\EntityPublishedInterface $entity */ /** @var \Drupal\Core\Entity\RevisionableInterface|\Drupal\Core\Entity\EntityPublishedInterface $entity */