insert('acl');
$query->fields([
'module' => $module,
'name' => $name,
'figure' => $figure,
]);
return $query->execute();
}
/**
* Delete an existing ACL.
*/
function acl_delete_acl($acl_id) {
$database = \Drupal::database();
$database->delete('acl')
->condition('acl_id', $acl_id)
->execute();
$database->delete('acl_user')
->condition('acl_id', $acl_id)
->execute();
$database->delete('acl_node')
->condition('acl_id', $acl_id)
->execute();
}
/**
* Add the specified UID to an ACL.
*/
function acl_add_user($acl_id, $uid) {
$database = \Drupal::database();
$test_uid = $database->query("SELECT uid FROM {acl_user} WHERE acl_id = :acl_id AND uid = :uid", [
'acl_id' => $acl_id,
'uid' => $uid,
])->fetchField();
if (!$test_uid) {
$database
->insert('acl_user')
->fields([
'acl_id' => $acl_id,
'uid' => $uid,
])
->execute();
}
}
/**
* Remove the specified UID from an ACL.
*/
function acl_remove_user($acl_id, $uid) {
\Drupal::database()->delete('acl_user')
->condition('acl_id', $acl_id)
->condition('uid', $uid)
->execute();
}
/**
* Remove all users from an ACL.
*/
function acl_remove_all_users($acl_id) {
\Drupal::database()->delete('acl_user')
->condition('acl_id', $acl_id)
->execute();
}
/**
* Provide a form to edit the ACL that can be embedded in other forms.
*
* Pass $new_acl=TRUE if you have no ACL yet, but do supply a string
* like 'my_module_new_acl' as $acl_id anyway; create the ACL and set
* $form['acl_id'] before calling acl_save_form().
*/
function acl_edit_form(FormStateInterface $form_state, $acl_id, $label = NULL, $new_acl = FALSE) {
\Drupal::moduleHandler()->loadInclude('acl', 'inc', 'acl.admin');
$build_info = $form_state->getBuildInfo();
$build_info['files'][] = [
'module' => 'acl',
'type' => 'inc',
'name' => 'acl.admin',
];
$form_state->setBuildInfo($build_info);
return _acl_edit_form($acl_id, $label, $new_acl);
}
/**
* Provide access control to all nodes selected by subquery, based on an ACL id.
*/
function acl_add_nodes(SelectInterface $subselect, $acl_id, $view, $update, $delete, $priority = 0) {
$database = \Drupal::database();
$database->delete('acl_node')
->condition('acl_id', $acl_id)
->condition('nid', $subselect, 'IN')
->execute();
$subselect->addExpression($acl_id, 'acl_id');
$subselect->addExpression((int) $view, 'grant_view');
$subselect->addExpression((int) $update, 'grant_update');
$subselect->addExpression((int) $delete, 'grant_delete');
$subselect->addExpression($priority, 'priority');
if (\Drupal::database()->driver() == 'mysql') {
$database->insert('acl_node')
->from($subselect)
->execute();
}
else {
// The PostgreSQL and SQLite drivers currently fail to
// generate the required parentheses around the subselect and
// cause an error in their respective database systems.
$results = $subselect->execute()->fetchAll(PDO::FETCH_ASSOC);
if (!empty($results)) {
$query = $database->insert('acl_node');
$query->fields([
'acl_id',
'nid',
'grant_view',
'grant_update',
'grant_delete',
'priority',
]);
foreach ($results as $result) {
$query->values($result);
}
$query->execute();
}
}
}
/**
* Provide access control to a node based upon an ACL id.
*/
function acl_node_add_acl($nid, $acl_id, $view, $update, $delete, $priority = 0) {
acl_node_add_acl_record([
'acl_id' => $acl_id,
'nid' => $nid,
'grant_view' => (int) $view,
'grant_update' => (int) $update,
'grant_delete' => (int) $delete,
'priority' => $priority,
]);
}
/**
* Provide access control to a node based upon an ACL id.
*/
function acl_node_add_acl_record(array $record) {
$database = \Drupal::database();
$database->delete('acl_node')
->condition('acl_id', $record['acl_id'])
->condition('nid', $record['nid'])
->execute();
$database->insert('acl_node')
->fields($record)
->execute();
}
/**
* Remove an ACL completely from a node.
*/
function acl_node_remove_acl($nid, $acl_id) {
\Drupal::database()->delete('acl_node')
->condition('acl_id', $acl_id)
->condition('nid', $nid)
->execute();
}
/**
* Clear all of a module's ACLs from a node.
*/
function acl_node_clear_acls($nid, $module) {
$database = \Drupal::database();
$select = $database->select('acl', 'a')
->fields('a', ['acl_id'])
->condition('a.module', $module);
$database->delete('acl_node')
->condition('nid', $nid)
->condition('acl_id', $select, 'IN')
->execute();
}
/**
* Get the id of an ACL by name (+ optionally figure).
*/
function acl_get_id_by_name($module, $name, $figure = NULL) {
$query = \Drupal::database()->select('acl', 'a')
->fields('a', ['acl_id'])
->condition('a.module', $module)
->condition('a.name', $name);
if (isset($figure)) {
$query->condition('a.figure', $figure);
}
return $query->execute()->fetchField();
}
/**
* Get the id of an ACL by figure.
*/
function acl_get_id_by_figure($module, $figure) {
$query = \Drupal::database()->select('acl', 'a')
->fields('a', ['acl_id'])
->condition('a.module', $module)
->condition('a.figure', $figure);
return $query->execute()->fetchField();
}
/**
* Determine whether an ACL has some assigned users.
*/
function acl_has_users($acl_id) {
return \Drupal::database()
->query("SELECT COUNT(uid) FROM {acl_user} WHERE acl_id = :acl_id", [
'acl_id' => $acl_id,
])
->fetchField();
}
/**
* Determine whether an ACL has a specific assigned user.
*/
function acl_has_user($acl_id, $uid) {
return \Drupal::database()
->query("SELECT COUNT(uid) FROM {acl_user} WHERE acl_id = :acl_id AND uid = :uid", [
'acl_id' => $acl_id,
'uid' => $uid,
])
->fetchField();
}
/**
* Get an array of acl_ids held by a user.
*/
function acl_get_ids_by_user($module, $uid, $name = NULL, $figure = NULL) {
$query = \Drupal::database()->select('acl', 'a');
$query->join('acl_user', 'au', 'a.acl_id = au.acl_id');
$query
->fields('a', ['acl_id'])
->condition('a.module', $module)
->condition('au.uid', $uid);
if (isset($name)) {
$query->condition('a.name', $name);
}
if (isset($figure)) {
$query->condition('a.figure', $figure);
}
$acl_ids = $query->execute()->fetchCol();
return $acl_ids;
}
/**
* Get the uids of an ACL.
*/
function acl_get_uids($acl_id) {
$uids = \Drupal::database()
->query("SELECT uid FROM {acl_user} WHERE acl_id = :acl_id", [
'acl_id' => $acl_id,
])
->fetchCol();
return $uids;
}
/**
* Get the usernames of an ACL.
*/
function acl_get_usernames($acl_id) {
$database = \Drupal::database();
$usernames = [];
foreach (User::loadMultiple(acl_get_uids($acl_id)) as $account) {
$usernames[$account->id()] = $account->getDisplayName();
}
return $usernames;
}
/**
* Implements hook_node_access_records().
*/
function acl_node_access_records(NodeInterface $node) {
if (!$node->id()) {
return;
}
$result = \Drupal::database()
->query("SELECT n.*, 'acl' AS realm, n.acl_id AS gid, a.module FROM {acl_node} n INNER JOIN {acl} a ON n.acl_id = a.acl_id WHERE nid = :nid", [
'nid' => $node->id(),
], ['fetch' => PDO::FETCH_ASSOC]);
$grants = [];
foreach ($result as $grant) {
if (\Drupal::moduleHandler()->invoke($grant['module'], 'enabled')) {
if (acl_has_users($grant['gid'])) {
$grants[] = $grant;
}
else {
// Just deny access.
$grants[] = [
'realm' => 'acl',
'gid' => $grant['gid'],
'grant_view' => 0,
'grant_update' => 0,
'grant_delete' => 0,
'priority' => $grant['priority'],
];
}
}
}
return $grants;
}
/**
* Implements hook_node_grants().
*/
function acl_node_grants($account, $op) {
$acl_ids = \Drupal::database()
->query("SELECT acl_id FROM {acl_user} WHERE uid = :uid", [
'uid' => $account->id(),
])
->fetchCol();
return (!empty($acl_ids) ? ['acl' => $acl_ids] : NULL);
}
/**
* Implements hook_node_delete().
*/
function acl_node_delete(NodeInterface $node) {
\Drupal::database()->delete('acl_node')
->condition('nid', $node->id())
->execute();
}
/**
* Implements hook_user_cancel().
*/
function acl_user_cancel($edit, AccountInterface $account, $method) {
\Drupal::database()->delete('acl_user')
->condition('uid', $account->id())
->execute();
}
/**
* Implements hook_node_access_explain().
*/
function acl_node_access_explain($row) {
static $interpretations = [];
$database = \Drupal::database();
if ($row->realm == 'acl') {
if (!isset($interpretations[$row->gid])) {
$acl = $database->query("SELECT * FROM {acl} WHERE acl_id = :acl_id", [
'acl_id' => $row->gid,
])->fetchObject();
$acl->tag = '?';
if (!isset($acl->name)) {
$acl->tag = $acl->figure;
}
elseif (!isset($acl->figure)) {
$acl->tag = $acl->name;
}
else {
$acl->tag = $acl->name . '-' . $acl->figure;
}
$account_names = acl_get_usernames($row->gid);
if (!empty($account_names)) {
$account_names = implode(', ', $account_names);
$interpretations[$row->gid] = _acl_get_explanation("$acl->module/$acl->tag: $account_names", $acl->acl_id, $acl->module, $acl->name, $acl->figure, $account_names);
}
elseif ($row->gid == 0) {
$result = $database->query("SELECT an.acl_id, a.module, a.name FROM {acl_node} an JOIN {acl} a ON an.acl_id = a.acl_id LEFT JOIN {acl_user} au ON a.acl_id = au.acl_id WHERE an.nid = :nid AND au.uid IS NULL", [
'nid' => $row->nid,
]);
foreach ($result as $acl) {
$rows[] = _acl_get_explanation("$acl->acl_id: $acl->module/$acl->tag", $acl->acl_id, $acl->module, $acl->name, $acl->figure);
}
if (!empty($rows)) {
return implode('
', $rows);
}
return 'No access via ACL.';
}
else {
$interpretations[$row->gid] = _acl_get_explanation("$acl->module/$acl->tag: no users!", $acl->acl_id, $acl->module, $acl->name, $acl->figure);
}
}
return $interpretations[$row->gid];
}
}
/**
* Ask the client for its interpretation of the given grant record.
*/
function _acl_get_explanation($text, $acl_id, $module, $name, $figure, $usernames = NULL) {
$hook = $module . '_acl_explain';
if (function_exists($hook)) {
return '' . $text . '';
}
return $text;
}