From d0653e4d3ec2bd93494402bd85d586a98307a63b Mon Sep 17 00:00:00 2001
From: Jimmy Berry <jimmy@boombatower.com>
Date: Fri, 23 Dec 2011 14:25:59 -0600
Subject: Issue #1382252: Implement hook_entity_access().

---
 entity.api.php |   17 +++++++++++++++++
 entity.module  |   43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/entity.api.php b/entity.api.php
index fb239cb..95121b5 100644
--- a/entity.api.php
+++ b/entity.api.php
@@ -434,5 +434,22 @@ function hook_entity_views_field_handlers_alter(array &$field_handlers) {
 }
 
 /**
+ * Implements hook_entity_access().
+ */
+function hook_entity_access($entity_type, $entity, $op, $account) {
+  if ($entity_type == 'foobar') {
+    $node = $entity;
+
+    if ($entity->bar != 'foo') {
+      return ENTITY_ACCESS_DENY;
+    }
+
+    if ($entity->baz == 'foo') {
+      return ENTITY_ACCESS_ALLOW;
+    }
+  }
+}
+
+/**
  * @} End of "addtogroup hooks".
  */
diff --git a/entity.module b/entity.module
index 0f552a3..255b7c7 100644
--- a/entity.module
+++ b/entity.module
@@ -423,9 +423,52 @@ function entity_view($entity_type, $entities, $view_mode = 'full', $langcode = N
  * @see entity_type_supports()
  */
 function entity_access($op, $entity_type, $entity = NULL, $account = NULL) {
+  $rights = &drupal_static(__FUNCTION__, array());
+
+  if (empty($entity) || !in_array($op, array('view', 'update', 'delete', 'create'), TRUE)) {
+    // If there was no entity to check against, or the $op was not one of the
+    // supported ones, we return access denied.
+    return FALSE;
+  }
+  // If no user object is supplied, the access check is for the current user.
+  if (!isset($account)) {
+    $account = $GLOBALS['user'];
+  }
+
+  // $entity may be either an object or a bundle. Since bundles cannot be
+  // an integer, use either entity ID or bundle as the static cache id.
+  $cid = $entity_type . ':';
+  if (is_object($entity)) {
+    list($id) = entity_extract_ids($entity_type, $entity);
+    $cid .= $id;
+  }
+  else {
+    $cid .= $entity;
+  }
+
+  // If we've already checked access for this entity, user and op, return from
+  // cache.
+  if (isset($rights[$account->uid][$cid][$op])) {
+    return $rights[$account->uid][$cid][$op];
+  }
+
+  // If 'access callback' is defined then use it.
   if (($info = entity_get_info()) && isset($info[$entity_type]['access callback'])) {
     return $info[$entity_type]['access callback']($op, $entity, $account, $entity_type);
   }
+
+  // We grant access to the entity if both of the following conditions are met:
+  // - No modules say to deny access.
+  // - At least one module says to grant access.
+  $access = module_invoke_all('entity_access', $entity_type, $entity, $op, $account);
+  if (in_array(ENTITY_ACCESS_DENY, $access, TRUE)) {
+    $rights[$account->uid][$cid][$op] = FALSE;
+    return FALSE;
+  }
+  elseif (in_array(ENTITY_ACCESS_ALLOW, $access, TRUE)) {
+    $rights[$account->uid][$cid][$op] = TRUE;
+    return TRUE;
+  }
 }
 
 /**
-- 
1.7.8

