function hook_node_access_records

7 node.api.php hook_node_access_records($node)
5 core.php hook_node_access_records($node)
6 core.php hook_node_access_records($node)
8 node.api.php hook_node_access_records(\Drupal\Core\Entity\EntityInterface $node)

Set permissions for a node to be written to the database.

When a node is saved, a module implementing hook_node_access_records() will be asked if it is interested in the access permissions for a node. If it is interested, it must respond with an array of permissions arrays for that node.

Node access grants apply regardless of the published or unpublished status of the node. Implementations must make sure not to grant access to unpublished nodes if they don't want to change the standard access control behavior. Your module may need to create a separate access realm to handle access to unpublished nodes.

Note that the grant values in the return value from your hook must be integers and not boolean TRUE and FALSE.

Each permissions item in the array is an array with the following elements:

  • 'realm': The name of a realm that the module has defined in hook_node_grants().
  • 'gid': A 'grant ID' from hook_node_grants().
  • 'grant_view': If set to 1 a user that has been identified as a member of this gid within this realm can view this node. This should usually be set to $node->status. Failure to do so may expose unpublished content to some users.
  • 'grant_update': If set to 1 a user that has been identified as a member of this gid within this realm can edit this node.
  • 'grant_delete': If set to 1 a user that has been identified as a member of this gid within this realm can delete this node.
  • 'priority': If multiple modules seek to set permissions on a node, the realms that have the highest priority will win out, and realms with a lower priority will not be written. If there is any doubt, it is best to leave this 0.

When an implementation is interested in a node but want to deny access to everyone, it may return a "deny all" grant:

$grants[] = array(
  'realm' => 'all',
  'gid' => 0,
  'grant_view' => 0,
  'grant_update' => 0,
  'grant_delete' => 0,
  'priority' => 1,
);

Setting the priority should cancel out other grants. In the case of a conflict between modules, it is safer to use hook_node_access_records_alter() to return only the deny grant.

Note: a deny all grant is not written to the database; denies are implicit.

Parameters

$node: The node that has just been saved.

Return value

An array of grants as defined above.

See also

node_access_write_grants()

hook_node_access_records_alter()

Related topics

2 functions implement hook_node_access_records()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

node_access_test_node_access_records in modules/node/tests/node_access_test.module
Implements hook_node_access_records().
node_test_node_access_records in modules/node/tests/node_test.module
Implements hook_node_access_records().
1 invocation of hook_node_access_records()
node_access_acquire_grants in modules/node/node.module
Gets the list of node access grants and writes them to the database.

File

modules/node/node.api.php, line 268
Hooks provided by the Node module.

Code

function hook_node_access_records($node) {
  // We only care about the node if it has been marked private. If not, it is
  // treated just like any other node and we completely ignore it.
  if ($node->private) {
    $grants = array();
    // Only published nodes should be viewable to all users. If we allow access
    // blindly here, then all users could view an unpublished node.
    if ($node->status) {
      $grants[] = array(
        'realm' => 'example',
        'gid' => 1,
        'grant_view' => 1,
        'grant_update' => 0,
        'grant_delete' => 0,
        'priority' => 0,
      );
    }
    // For the example_author array, the GID is equivalent to a UID, which
    // means there are many groups of just 1 user.
    // Note that an author can always view his or her nodes, even if they
    // have status unpublished.
    $grants[] = array(
      'realm' => 'example_author',
      'gid' => $node->uid,
      'grant_view' => 1,
      'grant_update' => 1,
      'grant_delete' => 1,
      'priority' => 0,
    );

    return $grants;
  }
}

Comments

If you need to alter values from a form element (possibly a field widget dedicated to establishing node access settings) that will be passed to an implementation of hook_node_access_records, be aware that hook_node_access_records runs before the form submit function.

My quick-fix was to use a validation function, which runs before hook_node_access_records. Although it isn't the correct use of a validation function (I gather you aren't supposed to alter values, only validate them, in such functions), it works in a jiffy.

I may be misunderstanding its use, but I think a hook_node_access_records_alter() implementation would be a cleaner solution? I'll leave that story to someone else.

For ones who are questioning what is $node->private and where you can set it, I'm suppose it's a custom property defined by node_access_example.module in hook_node_load().

If 2 modules produce grants with the same priority, shouldn't they all be written in the {node_access} table upon a node save?