final class BookAccess in Book access 7.2
Same name and namespace in other branches
- 6.2 book_access.module \BookAccess
@file
Allows to set the access control for book nodes on a per book basis. Based on forum_access.module and tac_lite.module.
Hierarchy
- class \BookAccess
Expanded class hierarchy of BookAccess
File
- ./
book_access.module, line 10 - Allows to set the access control for book nodes on a per book basis. Based on forum_access.module and tac_lite.module.
View source
final class BookAccess {
/**
* The minimum API version with which the module is compatible.
*/
const API_COMPATIBLE_VERSION = '2.5';
/**
* The API version implemented by the module.
*/
const API_VERSION = '2.5';
/**
* Adds author grants to book pages.
*
* @param $bid
* The book ID.
* @param $uid
* The user ID of the book author.
* @param $grants
* An array of grants, in the format @code $grants[$grant] @endcode,
* where @code $grant @endcode is a string between 'grant_view',
* 'grant_update', 'grant_delete', 'grant_admin_access', 'grant_add_child',
* 'grant_edit_outline'.
*/
public static function addAuthorGrants($bid, $uid, array $grants) {
$row = new stdClass();
$row->nid = $bid;
$row->uid = $uid;
$bool = db_query_range("SELECT 1 FROM {book_access_author} WHERE nid = :nid AND uid = :uid", 0, 1, array(
':nid' => $bid,
':uid' => $uid,
))
->fetchField();
foreach (self::grantIDs() as $id) {
$row->{$id} = !empty($grants[$id]);
}
drupal_write_record('book_access_author', $row, $bool ? array(
'nid',
'uid',
) : array());
}
/**
* Adds role grants to book pages.
*
* @param $bid
* The book ID.
* @param $rids
* An array of role IDs for which to add the book grants.
* @param $grants
* An array of grants, in the format @code $grants[$grant][$rid] @endcode,
* where @code $grant @endcode is a string between 'grant_view',
* 'grant_update', 'grant_delete', 'grant_admin_access', 'grant_add_child',
* 'grant_edit_outline', and @code $rid @endcode is the role ID.
*/
public static function addRoleGrants($bid, array $rids, array $grants) {
$row = new stdClass();
$row->nid = $bid;
foreach ($rids as $rid) {
$row->rid = $rid;
$bool = db_query_range("SELECT 1 FROM {book_access_role} WHERE nid = :nid AND rid = :rid", 0, 1, array(
':nid' => $bid,
':rid' => $rid,
))
->fetchField();
$granted = 0;
foreach (self::grantIDs() as $id) {
$row->{$id} = !empty($grants[$id][$rid]);
if ($row->{$id} != 0) {
$granted++;
}
}
if ($granted > 0) {
drupal_write_record('book_access_role', $row, $bool ? array(
'nid',
'rid',
) : array());
}
}
}
/**
* Adds user grants to book pages.
*
* @param $bid
* The book ID.
* @param $uids
* An array of user IDs for which to add the book grants.
* @param $grants
* An array of grants, in the format @code $grants[$grant][$uid] @endcode,
* where @code $grant @endcode is a string between 'grant_view',
* 'grant_update', 'grant_delete', 'grant_admin_access', 'grant_add_child',
* 'grant_edit_outline', and @code $uid @endcode is the user ID.
*/
public static function addUserGrants($bid, array $uids, array $grants) {
foreach ($uids as $uid) {
$bool = db_query_range("SELECT 1 FROM {book_access_user} WHERE nid = :nid AND uid = :uid", 0, 1, array(
':nid' => $bid,
':uid' => $uid,
))
->fetchField();
$row = new stdClass();
$row->nid = $bid;
$row->uid = $uid;
foreach (self::grantIDs() as $id) {
$row->{$id} = !empty($grants[$id][$uid]);
}
drupal_write_record('book_access_user', $row, $bool ? array(
'nid',
'uid',
) : array());
}
}
/**
* Verifies the current API version is included between two values passed as
* arguments.
*
* @param $minimum
* The minimum API version required. If the parameter is not passed, the
* method will use the constant API_COMPATIBLE_VERSION.
* @param $maximum
* The maximum version required. This argument is optional; the current API
* will be checked against this value only if it is passed to the function.
*
* @return
* TRUE, if the current API version is included between the passed values.
*/
public static function api($minimum = NULL, $maximum = NULL) {
if (!isset($minimum)) {
$minimum = self::API_COMPATIBLE_VERSION;
}
if (version_compare(self::API_VERSION, $minimum, '<')) {
return FALSE;
}
if (isset($maximum) && version_compare(self::API_VERSION, $maximum, '>')) {
return FALSE;
}
return TRUE;
}
/**
* Checks if a user has access to the book passed as argument.
*
* @param $bid
* The ID of the book to check.
* @param $grant
* The permission to check for. Can either be in the form "grant_update" or
* "update" though the former is now preferred for consistency.
* @param $account
* The user account for which the permission is checked; if it is not passed,
* the permission is checked against the current logged in user.
*
* @return
* TRUE if the user has the permission, FALSE otherwise.
*/
public static function checkGrant($bid, $grant, $account = NULL) {
static $queries = NULL;
if ($queries == NULL) {
$queries = array(
"book_access_author",
"book_access_role",
"book_access_user",
);
}
if (!isset($account)) {
$account = $GLOBALS['user'];
}
if (!preg_match('/^grant_/', $grant)) {
$grant = "grant_{$grant}";
}
$roles = array_keys($account->roles);
$resultSets = array();
foreach ($queries as $table) {
$queryObj = db_select($table, $table);
$queryObj
->condition("nid", $bid, "=");
if ($table == 'book_access_role') {
$queryObj
->condition("rid", $roles, "IN");
}
else {
$queryObj
->condition("uid", $account->uid, "=");
}
$queryObj
->fields($table, array(
$grant,
))
->orderBy($grant, 'DESC')
->range(0, 1);
$resultSets[$table] = $queryObj
->execute();
}
$rowCount = 0;
$grantCount = 0;
$explicitTables = array();
foreach ($resultSets as $table => $resultSet) {
if ($resultSet
->rowCount() > 0) {
$row = $resultSet
->fetchAssoc();
$explicitTables[$table] = TRUE;
++$rowCount;
$grantCount += (int) $row[$grant];
}
}
$hasPermission = $grantCount > 0;
// if our row count is less than 3, that means taht we are missing an explicit
// permissions entry in one of the tables. iterate and find the missing ones
// and check the defaults instead.
if (!$hasPermission && $rowCount < 3) {
$node = node_load($bid);
// check default author permissions first
if (!isset($explicitTables['book_access_author'])) {
$authorDefaults = variable_get("book_access_default_author_access");
$hasPermission = $account->uid == $node->uid && in_array($grant, $authorDefaults);
}
// then, failing that, check default role permissions
if (!$hasPermission && !isset($explicitTables['book_access_role'])) {
foreach ($roles as $role) {
$roleDefaults = variable_get("book_access_default_role_{$role}_access");
$hasPermission = in_array($grant, $roleDefaults);
if ($hasPermission) {
break;
}
}
}
}
return $hasPermission;
}
/**
* Resets the book access grants from the database.
*
* NOTE: once a grant has been created, it is merely set to 0 to avoid using
* defaults.
*
* @param $value
* The value to look for.
* param $field
* The database field where to look the value. The currently accepted
* values are 'bid', 'nid', 'uid', 'rid'.
* @param $types
* An array of grants types for which the function deletes records; the
* currently used values are 'author', 'role', 'user'. When this parameter
* is not passed, the method cues off the $field setting.
*/
public static function deleteGrants($value, $field = 'nid', array $types = NULL) {
if (isset($types)) {
$tables = array();
foreach ($types as $type) {
switch ($type) {
case 'author':
case 'role':
case 'user':
$tables[] = "book_access_{$type}";
break;
}
}
}
else {
switch ($field) {
case 'bid':
case 'nid':
$tables = array(
'book_access_author',
'book_access_role',
'book_access_user',
);
break;
case 'uid':
$tables = array(
'book_access_author',
'book_access_user',
);
break;
case 'rid':
$tables = array(
'book_access_role',
);
break;
default:
$tables = array();
}
}
foreach ($tables as $table) {
db_update($table)
->fields(array(
"grant_admin_access" => 0,
"grant_update" => 0,
"grant_delete" => 0,
"grant_add_child" => 0,
"grant_edit_outline" => 0,
"grant_view" => 0,
))
->condition($field == "bid" ? "nid" : $field, $value, '=')
->execute();
}
}
/**
* Returns the book author grants.
*
* @param $bid
* The book ID.
* @param $uid
* The user ID for the book author.
* @param $defaults
* An array containing the default values for the grants.
*
* @return
* An array of grants, in the format @code $grants[$grant] @endcode,
* where @code $grant @endcode is a string between 'grant_view',
* 'grant_update', 'grant_delete', 'grant_admin_access', 'grant_add_child',
* 'grant_edit_outline'.
*/
public static function getAuthorGrants($bid, $uid, array $defaults = array()) {
$grants = db_query_range('SELECT * FROM {book_access_author} WHERE nid = :nid AND uid = :uid', 0, 1, array(
':nid' => $bid,
':uid' => $uid,
))
->fetchAssoc();
if (!$grants) {
$defaults = array_filter($defaults);
foreach (self::grantIDs() as $id) {
$grants[$id] = !empty($defaults[$id]);
}
}
return $grants;
}
/**
* Lists all the books to which the current user has access.
*
* @param $account
* The user account to use; if NULL, the currently logged in user account
* will be used.
* @param $grants
* An array containing one or more values between 'view', 'update',
* 'delete', 'admin_access', 'add_child', and 'edit_outline'.
*
* @return
* An array containing the node ID of the books to which the user has access.
*/
public static function getBookList(array $grants = array(
'update',
), $account = NULL) {
$permitted_bids = array();
if (!isset($account)) {
$account = $GLOBALS['user'];
}
foreach ($grants as $grant) {
$result = db_query("SELECT nid FROM {book_access_author} WHERE uid = :uid AND grant_{$grant} > 0", array(
':uid' => $account->uid,
));
foreach ($result as $book) {
$permitted_bids[$book->nid] = $book->nid;
}
$roles = array_keys($account->roles);
$result = db_query("SELECT nid FROM {book_access_role} WHERE rid IN (:rid) AND grant_{$grant} > 0", array(
':rid' => $roles,
));
foreach ($result as $book) {
$permitted_bids[$book->nid] = $book->nid;
}
$result = db_query("SELECT nid FROM {book_access_user} WHERE uid = :uid AND grant_{$grant} > 0", array(
':uid' => $account->uid,
));
foreach ($result as $book) {
$permitted_bids[$book->nid] = $book->nid;
}
}
return $permitted_bids;
}
/**
* Gets the list of grant records assigned to a book.
*
* @param $bid
* The ID of the book for which the function returns the grant records.
* @param $types
* An array of grants types for which the function returns the records; the
* currently used values are 'author', 'role', 'user'.
*
* @return
* The array of grant records for the specified book.
*/
public static function getGrantRecords($bid, array $types = array(
'author',
'role',
'user',
)) {
$grants = array();
$info = array();
foreach ($types as $type) {
switch ($type) {
case 'author':
$info[] = array(
'table' => 'book_access_author',
'gid' => 'uid',
);
break;
case 'role':
$info[] = array(
'table' => 'book_access_role',
'gid' => 'rid',
);
break;
case 'user':
$info[] = array(
'table' => 'book_access_user',
'gid' => 'uid',
);
break;
}
}
foreach ($info as $data) {
$result = db_query("SELECT * FROM {" . db_escape_table($data['table']) . "} WHERE nid = :nid", array(
':nid' => $bid,
));
foreach ($result as $grant) {
$grants[] = array(
'realm' => $data['table'],
'gid' => $grant->{$data['gid']},
'grant_view' => $grant->grant_view,
'grant_update' => $grant->grant_update,
'grant_delete' => $grant->grant_delete,
'priority' => variable_get('book_access_priority', 0),
);
}
}
return $grants;
}
/**
* Returns the role book grants.
*
* @param $bid
* The book ID.
* @param $roles
* The variables where to store the value returned by user_roles().
* @param $defaults
* An array containing the default values for the grants.
*
* @return
* An array of grants, in the format @code $grants[$grant][$rid] @endcode,
* where @code $grant @endcode is a string between 'grant_view',
* 'grant_update', 'grant_delete', 'grant_admin_access', 'grant_add_child',
* 'grant_edit_outline', and @code $rid @endcode is the role ID.
*/
public static function getRoleGrants($bid, &$roles, array $defaults = array()) {
$grants = array(
'grant_view' => array(),
'grant_update' => array(),
'grant_delete' => array(),
'grant_admin_access' => array(),
'grant_add_child' => array(),
'grant_edit_outline' => array(),
);
$roles = user_roles();
$rcopy = $roles;
$rids = array_keys($roles);
$result = db_query("SELECT * FROM {book_access_role} WHERE nid = :nid AND rid IN (:rid)", array(
':nid' => $bid,
':rid' => $rids,
));
// Build the role access permissions for the book.
if ($result
->rowCount() > 0) {
foreach ($result as $access) {
unset($rcopy[$access->rid]);
foreach (self::grantIDs() as $id) {
$grants[$id][$access->rid] = !empty($access->{$id});
}
}
}
else {
foreach ($rids as $rid) {
$roleDefaults = variable_get("book_access_default_role_{$rid}_access");
if ($roleDefaults) {
unset($rcopy[$rid]);
foreach (self::grantIDs() as $id) {
$grants[$id][$rid] = in_array($id, $roleDefaults);
}
}
}
}
$defaults = array_filter($defaults);
// Set the default role access permissions for the roles that don't have
// access permissions already set.
foreach (self::grantIDs() as $id) {
foreach ($rcopy as $rid => $name) {
$grants[$id][$rid] = !empty($defaults[$id]);
}
}
return $grants;
}
/**
* Returns the user book grants.
*
* @param $bid
* The book ID.
* @param $uids
* The variables where to store the user IDs.
* @param $defaults
* An array containing the default values for the grants.
*
* @return
* An array of grants, in the format @code $grants[$grant][$uid] @endcode,
* where @code $grant @endcode is a string between 'grant_view',
* 'grant_update', 'grant_delete', 'grant_admin_access', 'grant_add_child',
* 'grant_edit_outline', and @code $uid @endcode is the user ID.
*/
public static function getUserGrants($bid, &$uids) {
$grants = array(
'grant_view' => array(),
'grant_update' => array(),
'grant_delete' => array(),
'grant_admin_access' => array(),
'grant_add_child' => array(),
'grant_edit_outline' => array(),
);
$uids = array();
$result = db_query("SELECT * FROM {book_access_user} bau INNER JOIN {users} u ON u.uid = bau.uid WHERE bau.nid = :nid", array(
':nid' => $bid,
));
foreach ($result as $access) {
$uid = $access->uid;
$uids[$uid] = $uid;
foreach (self::grantIDs() as $id) {
$grants[$id][$uid] = !empty($access->{$id});
}
}
return $grants;
}
/**
* Returns the grant IDs implemented by the module.
*/
public static function grantIDs() {
return array(
'grant_view',
'grant_update',
'grant_delete',
'grant_admin_access',
'grant_add_child',
'grant_edit_outline',
);
}
/**
* Returns the default access permissions.
*/
public static function defaultGrants() {
return array(
'grant_view',
);
}
/**
* Returns the default author access permissions.
*/
public static function defaultAuthorGrants() {
static $defaults = NULL;
if (!$defaults) {
$defaults = self::grantIDs();
unset($defaults[array_search('grant_admin_access', $defaults)]);
$defaults = array_values($defaults);
}
return $defaults;
}
/**
* Restricts the options available to who moves book pages between books.
*
* @param $options
* The options array used from book_outline_form() and the book edit form
* for the list of books to which the page can be moved to.
* @param $account
* The user account to use; if NULL, the currently logged in user account
* will be used.
*/
public static function restrictOptions(&$options, $account = NULL) {
if (!isset($account)) {
$account = $GLOBALS['user'];
}
if (user_access('administer nodes', $account)) {
return;
}
$permitted_bids = self::getBookList(array(
'update',
), $account);
foreach ($options as $bid => $value) {
if ($bid > 0 && !isset($permitted_bids[$bid])) {
unset($options[$bid]);
}
}
}
/**
* Sets the author grants for book pages.
*
* The method delete the author grants before to set the new ones.
*
* @param $bid
* The book ID.
* @param $uid
* The user ID of the book author.
* @param $grants
* An array of grants, in the format @code $grants[$grant] @endcode,
* where @code $grant @endcode is a string between 'grant_view',
* 'grant_update', 'grant_delete', 'grant_admin_access', 'grant_add_child',
* 'grant_edit_outline'.
*/
public static function setAuthorGrants($bid, $uid, array $grants) {
db_delete('book_access_author')
->condition('nid', $bid)
->execute();
self::addAuthorGrants($bid, $uid, $grants);
}
/**
* Sets the role grants for book pages.
*
* The method delete the role grants before to set the new ones.
*
* @param $bid
* The book ID.
* @param $rids
* An array of role IDs for which to add the book grants.
* @param $grants
* An array of grants, in the format @code $grants[$grant][$rid] @endcode,
* where @code $grant @endcode is a string between 'grant_view',
* 'grant_update', 'grant_delete', 'grant_admin_access', 'grant_add_child',
* 'grant_edit_outline', and @code $rid @endcode is the role ID.
*/
public static function setRoleGrants($bid, array $rids, array $grants) {
db_delete('book_access_role')
->condition('nid', $bid)
->execute();
self::addRoleGrants($bid, $rids, $grants);
}
/**
* Sets the user grants for book pages.
*
* The method delete the user grants before to set the new ones.
*
* @param $bid
* The book ID.
* @param $uids
* An array of user IDs for which to add the book grants.
* @param $grants
* An array of grants, in the format @code $grants[$grant][$uid] @endcode,
* where @code $grant @endcode is a string between 'grant_view',
* 'grant_update', 'grant_delete', 'grant_admin_access', 'grant_add_child',
* 'grant_edit_outline', and @code $uid @endcode is the user ID.
*/
public static function setUserGrants($bid, array $uids, array $grants) {
db_delete('book_access_user')
->condition('nid', $bid)
->execute();
self::addUserGrants($bid, $uids, $grants);
}
/**
* @param $rid
* The role id to set the default for.
* @param $rname
* The optional name of the role. If specified, this saves a database
* trip, as otherwise this method uses $rid to look up the name.
*
* Based on the role name, this initializes the default grants for the role
* id. This is only intended to be used during hook_init() or when creating a
* brand new role.
*/
public static function setDefaultForRole($rid, $rname = NULL) {
if (!$rname) {
$role = user_role_load($rid);
if ($role === FALSE) {
drupal_set_message(t("Could not set default book_access grants for role: @rid, role not found", array(
'@rid' => $rid,
)), "error");
return;
}
$rname = $role->rid;
}
if ($rname == 'administrator') {
$defaultToUse = self::grantIDs();
}
else {
$defaultToUse = self::defaultGrants();
}
if (variable_get("book_access_default_role_{$rid}_access") === NULL) {
variable_set("book_access_default_role_{$rid}_access", $defaultToUse);
}
}
/**
* Resets book permissions to its defaults, ignoring user-specific ones.
*/
public static function resetToDefault($nid) {
$node = node_load($nid);
$roles = user_roles();
$authorDefaults = variable_get('book_access_default_author_access');
BookAccess::setAuthorGrants($nid, $node->uid, drupal_map_assoc($authorDefaults));
// clear out the existing role grants and add on to it
BookAccess::setRoleGrants($nid, array_keys($roles), array());
$roleGrantsToAdd = array();
foreach ($roles as $rid => $rname) {
$roleDefaults = variable_get("book_access_default_role_{$rid}_access");
foreach ($roleDefaults as $grant) {
$roleGrantsToAdd[$grant][$rid] = TRUE;
}
}
BookAccess::addRoleGrants($nid, array_keys($roles), $roleGrantsToAdd);
}
/**
* Updates the grants for a book.
*
* @param $bid
* The book ID.
* @param $fields
* The fields to update.
* @param $types
* An array containing the grant types; the currently used values are
* 'author', 'role', 'user'. It is responsibility of the caller to use
* values for $types for which $field is valid.
*/
public static function updateGrants($bid, array $fields, array $types = array(
'author',
'role',
'user',
)) {
foreach ($types as $type) {
switch ($type) {
case 'author':
case 'role':
case 'user':
$table = "book_access_{$type}";
break;
default:
$table = '';
}
if ($table) {
db_update($table)
->fields($fields)
->condition('nid', $bid)
->execute();
}
}
}
/*
* Writes the grant records to the Drupal node access table.
*
* @param $node
* The node object for the book page.
* @param $types
* An array of grants types that are written; the currently used values are
* 'author', 'role', 'user'.
*/
public static function writeGrantRecords($node, array $types = array(
'author',
'role',
'user',
)) {
if (!empty($node->nid) && !empty($node->book['bid'])) {
foreach ($types as $type) {
switch ($type) {
case 'author':
case 'role':
case 'user':
$table = "book_access_{$type}";
break;
default:
$table = '';
}
if ($table && ($grants = self::getGrantRecords($node->book['bid'], array(
$type,
)))) {
node_access_write_grants($node, $grants, $table, TRUE);
}
}
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
BookAccess:: |
public static | function | Adds author grants to book pages. | |
BookAccess:: |
public static | function | Adds role grants to book pages. | |
BookAccess:: |
public static | function | Adds user grants to book pages. | |
BookAccess:: |
public static | function | Verifies the current API version is included between two values passed as arguments. | |
BookAccess:: |
constant | The minimum API version with which the module is compatible. | ||
BookAccess:: |
constant | The API version implemented by the module. | ||
BookAccess:: |
public static | function | Checks if a user has access to the book passed as argument. | |
BookAccess:: |
public static | function | Returns the default author access permissions. | |
BookAccess:: |
public static | function | Returns the default access permissions. | |
BookAccess:: |
public static | function | Resets the book access grants from the database. | |
BookAccess:: |
public static | function | Returns the book author grants. | |
BookAccess:: |
public static | function | Lists all the books to which the current user has access. | |
BookAccess:: |
public static | function | Gets the list of grant records assigned to a book. | |
BookAccess:: |
public static | function | Returns the role book grants. | |
BookAccess:: |
public static | function | Returns the user book grants. | |
BookAccess:: |
public static | function | Returns the grant IDs implemented by the module. | |
BookAccess:: |
public static | function | Resets book permissions to its defaults, ignoring user-specific ones. | |
BookAccess:: |
public static | function | Restricts the options available to who moves book pages between books. | |
BookAccess:: |
public static | function | Sets the author grants for book pages. | |
BookAccess:: |
public static | function | ||
BookAccess:: |
public static | function | Sets the role grants for book pages. | |
BookAccess:: |
public static | function | Sets the user grants for book pages. | |
BookAccess:: |
public static | function | Updates the grants for a book. | |
BookAccess:: |
public static | function |