diff --git a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php index eacbf53..ac2ab2e 100644 --- a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php @@ -197,7 +197,7 @@ public function loadMultiple(array $ids = NULL) { // Load remaining entities either from the persistent cache or storage. $entities = $this->doLoadMultiple($ids); - + $this->invokeLoadUncachedHook($entities); $this->setStaticCache($entities); $entities += $entities_from_static_cache; @@ -366,6 +366,27 @@ protected function setPersistentCache($entities) { } /** + * Invokes hook_entity_load_uncached(). + * + * @param \Drupal\Core\Entity\EntityInterface[] $entities + * List of entities, keyed on the entity ID. + */ + protected function invokeLoadUncachedHook(array &$entities) { + if (!empty($entities)) { + // Call hook_entity_load_uncached(). + foreach ($this->moduleHandler()->getImplementations('entity_load_uncached') as $module) { + $function = $module . '_entity_load_uncached'; + $function($entities, $this->entityTypeId); + } + // Call hook_TYPE_load_uncached(). + foreach ($this->moduleHandler()->getImplementations($this->entityTypeId . '_load_uncached') as $module) { + $function = $module . '_' . $this->entityTypeId . '_load_uncached'; + $function($entities); + } + } + } + + /** * {@inheritdoc} */ public function resetCache(array $ids = NULL) { diff --git a/core/modules/book/book.module b/core/modules/book/book.module index 8fe9e41..cb753bd 100644 --- a/core/modules/book/book.module +++ b/core/modules/book/book.module @@ -455,9 +455,11 @@ function book_children($book_link) { } /** - * Implements hook_node_load(). + * Implements hook_node_load_uncached(). + * + * @todo: Use hook_node_load() and clear caches when changes happen. */ -function book_node_load($nodes) { +function book_node_load_uncached($nodes) { $result = db_query("SELECT * FROM {book} b INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE b.nid IN (:nids)", array(':nids' => array_keys($nodes)), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $record) { $nodes[$record['nid']]->book = $record; diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 6d7e051..ab8a5e0 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -880,11 +880,11 @@ function comment_translation_configuration_element_submit($form, &$form_state) { } /** - * Implements hook_entity_load(). + * Implements hook_entity_load_uncached(). * * @see \Drupal\comment\Plugin\Field\FieldType\CommentItem::getPropertyDefinitions() */ -function comment_entity_load($entities, $entity_type) { +function comment_entity_load_uncached($entities, $entity_type) { if (!\Drupal::service('comment.manager')->getFields($entity_type)) { // Do not query database when entity has no comment fields. return; diff --git a/core/modules/node/tests/modules/node_access_test/node_access_test.module b/core/modules/node/tests/modules/node_access_test/node_access_test.module index 128b31a..81259f3 100644 --- a/core/modules/node/tests/modules/node_access_test/node_access_test.module +++ b/core/modules/node/tests/modules/node_access_test/node_access_test.module @@ -107,9 +107,9 @@ function node_access_test_form_node_form_alter(&$form, $form_state) { } /** - * Implements hook_node_load(). + * Implements hook_ENTITY_TYPE_load_uncached(). */ -function node_access_test_node_load($nodes) { +function node_access_test_node_load_uncached($nodes) { $result = db_query('SELECT nid, private FROM {node_access_test} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes))); foreach ($result as $record) { $nodes[$record->nid]->private = $record->private; diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php index 1e37fff..91493a8 100644 --- a/core/modules/system/entity.api.php +++ b/core/modules/system/entity.api.php @@ -266,18 +266,55 @@ function hook_entity_create(\Drupal\Core\Entity\EntityInterface $entity) { * This is a generic load hook called for all entity types loaded via the * entity API. * - * @param array $entities + * The hook will not be invoked for entities loaded from the cache. Use + * hook_entity_load_uncached() if necessary. + * + * @param \Drupal\Core\Entity\EntityInterface[] $entities * The entities keyed by entity ID. * @param string $entity_type * The type of entities being loaded (i.e. node, user, comment). */ -function hook_entity_load($entities, $entity_type) { +function hook_entity_load(array $entities, $entity_type) { foreach ($entities as $entity) { $entity->foo = mymodule_add_something($entity); } } /** + * Act on entities when loaded from the storage or cache. + * + * Only use this hook if the result must not be cached. + * + * @param \Drupal\Core\Entity\EntityInterface[] $entities + * The entities keyed by entity ID. + * @param string $entity_type + * The type of entities being loaded (i.e. node, user, comment). + * + * @see hook_entity_load_uncached() + */ +function hook_entity_load_uncached(array $entities, $entity_type) { + foreach ($entities as $entity) { + $entity->foo = mymodule_add_something_uncached($entity); + } +} + +/** + * Act on entities of the given type when loaded from the storage or cache. + * + * Only use this hook if the result must not be cached. + * + * @param \Drupal\Core\Entity\EntityInterface[] $entities + * The entities keyed by entity ID. + * + * @see hook_entity_load_uncached() + */ +function hook_ENTITY_TYPE_load_uncached(array $entities) { + foreach ($entities as $entity) { + $entity->foo = mymodule_add_something_uncached($entity); + } +} + +/** * Act on an entity before it is about to be created or updated. * * @param \Drupal\Core\Entity\EntityInterface $entity