Access callback: Checks a user's permission for performing a node operation.
@todo Add langcode support to node_access schema / queries. http://drupal.org/node/1658846
$op: The operation to be performed on the node. Possible values are:
Drupal\node\Node|string|stdClass $node: The node entity on which the operation is to be performed, or the node type object, or node type string (e.g., 'forum') for the 'create' operation.
$account: (optional) A user object representing the user for whom the operation is to be performed. Determines access for a user other than the current user. Defaults to NULL.
$langcode: (optional) Language code for the variant of the node. Different language variants might have different permissions associated. If NULL, the original langcode of the node is used. Defaults to NULL.
TRUE if the operation may be performed, FALSE otherwise.
function node_access($op, $node, $account = NULL, $langcode = NULL) {
$rights =& drupal_static(__FUNCTION__, array());
if (!$node || !in_array($op, array(
'view',
'update',
'delete',
'create',
), TRUE)) {
// If there was no node 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 (empty($account)) {
$account = $GLOBALS['user'];
}
// $node may be a node object, a node type object, or a node type string.
// Use the node ID as the primary cache ID, or the node type name otherwise.
$cid = is_object($node) ? isset($node->nid) ? $node->nid : $node->type : $node;
// If no language code was provided, default to the node's langcode or
// to an empty langcode if a node type was requested. The latter is purely
// for caching purposes.
if (empty($langcode)) {
$langcode = is_object($node) && isset($node->nid) ? $node->langcode : '';
}
// If we've already checked access for this node, user and op, return from
// cache.
if (isset($rights[$account->uid][$cid][$langcode][$op])) {
return $rights[$account->uid][$cid][$langcode][$op];
}
if (user_access('bypass node access', $account)) {
$rights[$account->uid][$cid][$langcode][$op] = TRUE;
return TRUE;
}
if (!user_access('access content', $account)) {
$rights[$account->uid][$cid][$langcode][$op] = FALSE;
return FALSE;
}
// We grant access to the node if both of the following conditions are met:
// - No modules say to deny access.
// - At least one module says to grant access.
// If no module specified either allow or deny, we fall back to the
// node_access table.
$access = module_invoke_all('node_access', $node, $op, $account, $langcode);
if (in_array(NODE_ACCESS_DENY, $access, TRUE)) {
$rights[$account->uid][$cid][$langcode][$op] = FALSE;
return FALSE;
}
elseif (in_array(NODE_ACCESS_ALLOW, $access, TRUE)) {
$rights[$account->uid][$cid][$langcode][$op] = TRUE;
return TRUE;
}
// Check if authors can view their own unpublished nodes.
if ($op == 'view' && !$node
->get('status', $langcode) && user_access('view own unpublished content', $account) && $account->uid == $node
->get('uid', $langcode) && $account->uid != 0) {
$rights[$account->uid][$cid][$langcode][$op] = TRUE;
return TRUE;
}
// If the module did not override the access rights, use those set in the
// node_access table.
if ($op != 'create' && $node->nid) {
if (module_implements('node_grants')) {
$query = db_select('node_access');
$query
->addExpression('1');
$query
->condition('grant_' . $op, 1, '>=');
$nids = db_or()
->condition('nid', $node->nid);
if ($node->status) {
$nids
->condition('nid', 0);
}
$query
->condition($nids);
$query
->range(0, 1);
$grants = db_or();
foreach (node_access_grants($op, $account) as $realm => $gids) {
foreach ($gids as $gid) {
$grants
->condition(db_and()
->condition('gid', $gid)
->condition('realm', $realm));
}
}
if (count($grants) > 0) {
$query
->condition($grants);
}
$result = (bool) $query
->execute()
->fetchField();
$rights[$account->uid][$cid][$langcode][$op] = $result;
return $result;
}
elseif (is_object($node) && $op == 'view' && $node
->get('status', $langcode)) {
// If no modules implement hook_node_grants(), the default behavior is to
// allow all users to view published nodes, so reflect that here.
$rights[$account->uid][$cid][$langcode][$op] = TRUE;
return TRUE;
}
}
return FALSE;
}