You are here

acl.module in ACL 5

Same filename and directory in other branches
  1. 8 acl.module
  2. 6 acl.module
  3. 7 acl.module

acl.module

This module handls ACLs on behalf of other modules. The two main reasons to do this are so that modules using ACLs can share them with each other without having to actually know much about them, and so that ACLs can easily co-exist with the existing node_access system.

File

acl.module
View source
<?php

/**
 * @file acl.module
 *
 * This module handls ACLs on behalf of other modules. The two main reasons
 * to do this are so that modules using ACLs can share them with each
 * other without having to actually know much about them, and so that
 * ACLs can easily co-exist with the existing node_access system.
 */

/**
 * Create a new ACL.
 */
function acl_create_new_acl($module, $name) {
  $acl_id = db_next_id('{acl}_acl_id');
  db_query("INSERT INTO {acl} (acl_id, module, name) VALUES (%d, '%s', '%s')", $acl_id, $module, $name);
  return $acl_id;
}

/**
 * Delete an existing ACL.
 */
function acl_delete_acl($acl_id) {
  db_query("DELETE FROM {acl} WHERE acl_id = %d", $acl_id);
  db_query("DELETE FROM {acl_user} WHERE acl_id = %d", $acl_id);
  db_query("DELETE FROM {acl_node} WHERE acl_id = %d", $acl_id);
}

/**
 * Add the specified UID to an ACL.
 */
function acl_add_user($acl_id, $uid) {
  $test_uid = db_result(db_query("SELECT uid FROM {acl_user} WHERE acl_id = %d AND uid = %d ", $acl_id, $uid));
  if (!$test_uid) {
    db_query("INSERT INTO {acl_user} (acl_id, uid) VALUES (%d, %d)", $acl_id, $uid);
  }
}

/**
 * Remove the specified UID from an ACL.
 */
function acl_remove_user($acl_id, $uid) {
  db_query("DELETE FROM {acl_user} WHERE acl_id = %d AND uid = %d ", $acl_id, $uid);
}

/**
 * Provide a special button type that doesn't get its #name blasted.
 */
function acl_elements() {
  $type['acl_button'] = array(
    '#input' => TRUE,
    '#button_type' => 'submit',
    '#executes_submit_callback' => FALSE,
  );
  return $type;
}
function theme_acl_button($element) {
  $element['#value'] = $element['#label'];
  return theme('button', $element);
}

/**
 * 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.
 */
function acl_edit_form($acl_id, $label = NULL, $new_acl = FALSE) {
  $users = array();
  if (!$new_acl) {

    // Ensure the ACL in question even exists.
    if (!($acl_name = db_result(db_query("SELECT name FROM {acl} WHERE acl_id = %d", $acl_id)))) {
      return array();
    }
    $result = db_query("SELECT u.uid, u.name FROM {users} u LEFT JOIN {acl_user} aclu ON aclu.uid = u.uid WHERE acl_id = %d", $acl_id);
    while ($user = db_fetch_object($result)) {
      $users[$user->uid] = $user->name;
    }
  }
  if (!isset($label)) {
    $label = empty($acl_name) ? $acl_id : $acl_name;
  }
  $form = array(
    '#type' => 'fieldset',
    '#collapsible' => true,
    '#title' => $label,
    '#tree' => true,
  );
  $form['acl_id'] = array(
    '#type' => 'value',
    '#value' => $acl_id,
  );
  $form['deletions'] = array(
    '#type' => 'checkboxes',
  );

  // placeholder
  $form['delete_button'] = array(
    '#type' => 'acl_button',
    '#label' => t('Remove Checked'),
  );
  $form['add'] = array(
    '#type' => 'textfield',
    '#title' => t('Add user'),
    '#maxlength' => 60,
    '#size' => 40,
    '#autocomplete_path' => 'user/autocomplete',
  );
  $form['add_button'] = array(
    '#type' => 'acl_button',
    '#label' => t('Add User'),
  );
  $form['user_list'] = array(
    '#type' => 'hidden',
    '#default_value' => serialize($users),
  );
  $form['#after_build'] = array(
    'acl_edit_form_after_build',
  );
  return $form;
}

/**
 * Write the results of a form.
 */
function acl_save_form($form) {
  $users = unserialize($form['user_list']);
  db_query('DELETE FROM {acl_user} WHERE acl_id = %d', $form['acl_id']);
  foreach ($users as $uid => $name) {
    db_query('INSERT INTO {acl_user} (acl_id, uid) VALUES (%d, %d)', $form['acl_id'], $uid);
  }
}

/**
 * Process a form that had our buttons on it.
 */
function acl_edit_form_after_build($form, $form_values) {

  // We can't use form_values because it's the entire structure
  // and we have no clue where our values actually are. That's
  // ok tho cause #value still works for us.
  $user_list = unserialize($form['user_list']['#value']);
  if ($form['delete_button']['#value'] && is_array($form['deletions']['#value'])) {
    foreach ($form['deletions']['#value'] as $uid) {
      unset($user_list[$uid]);
    }
  }
  else {
    if ($form['add_button']['#value']) {
      $name = $form['add']['#value'];
      $u = db_fetch_object(db_query("SELECT uid, name FROM {users} WHERE name = '%s'", $name));
      if (!$u->uid) {
        form_error($form['add'], "Invalid user.");
      }
      else {
        $user_list[$u->uid] = $u->name;
        $form['add']['#value'] = NULL;
      }
    }
  }
  if (count($user_list) != 0) {
    $form['deletions']['#type'] = 'checkboxes';
    $form['deletions']['#title'] = t("Current users");
    $form['deletions']['#options'] = $user_list;
    $form['deletions']['#value'] = array();

    // don't carry value through.
    // need $form_id and have no way to get it but from $_POST that
    // I can find; and if we got here that variable's already been
    // checked.
    $form['deletions'] = form_builder($_POST['form_id'], $form['deletions']);
  }
  else {
    $form['delete_button']['#type'] = 'value';
  }
  $form['user_list']['#value'] = serialize($user_list);
  return $form;
}

/**
 * Provide access control to a node based upon an ACL id.
 */
function acl_node_add_acl($nid, $acl_id, $view, $update, $delete, $priority = 0) {
  db_query("DELETE FROM {acl_node} WHERE acl_id = %d AND nid = %d", $acl_id, $nid);
  db_query("INSERT INTO {acl_node} (acl_id, nid, grant_view, grant_update, grant_delete, priority) VALUES (%d, %d, %d, %d, %d, %d)", $acl_id, $nid, $view, $update, $delete, $priority);
}

/**
 * Remove an ACL completely from a node.
 */
function acl_node_remove_acl($nid, $acl_id) {
  db_query("DELETE FROM {acl_node} WHERE acl_id = %d AND nid = %d", $acl_id, $nid);
}

/**
 * Clear all of a module's ACL's from a node.
 */
function acl_node_clear_acls($nid, $module) {
  $result = db_query("SELECT acl_id FROM {acl} WHERE module = '%s'", $module);
  while ($o = db_fetch_object($result)) {
    $acls[] = $o->acl_id;
  }
  if ($acls) {
    db_query("DELETE FROM {acl_node} WHERE nid = %d AND acl_id in (%s)", $nid, implode(',', $acls));
  }
}

/**
 * Gets the id of an acl
 */
function acl_get_id_by_name($module, $name) {
  return db_result(db_query("SELECT acl_id FROM {acl} WHERE module = '%s' AND name = '%s'", $module, $name));
}

/**
 * Determines if an acl has some assigned users
 */
function acl_has_users($acl_id) {
  return db_result(db_query("SELECT COUNT(aclu.uid) FROM {acl_user} aclu WHERE acl_id = %d", $acl_id));
}

/**
 * Gets the uids of an acl
 */
function acl_get_uids($acl_id) {
  $result = db_query("SELECT uid FROM {acl_user} WHERE acl_id = '%d'", $acl_id);
  $return = array();
  while ($row = db_fetch_object($result)) {
    $return[$row->uid] = $row->uid;
  }
  return empty($return) ? NULL : $return;
}

/**
 * Implementation of hook_node_access_grants (from node_access)
 */
function acl_node_access_records($node) {
  if (!$node->nid) {
    return;
  }
  $result = db_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 = %d", $node->nid);
  $grants = array();
  while ($grant = db_fetch_array($result)) {
    if (module_exists($grant['module']) && module_invoke($grant['module'], 'enabled')) {
      if (acl_has_users($grant['gid'])) {
        $grants[] = $grant;
      }
      else {

        //just deny access
        $grants[] = array(
          'grant_view' => 0,
          'realm' => 'acl',
          'gid' => $grant['gid'],
        );
      }
    }
  }
  return $grants;
}

/**
 * Implementation of hook_node_grants
 */
function acl_node_grants($account, $op) {
  $array = array(
    'acl' => array(),
  );
  $result = db_query("SELECT acl_id FROM {acl_user} WHERE uid = %d", $account->uid);
  while ($row = db_fetch_object($result)) {
    $array['acl'][] = $row->acl_id;
  }
  return !empty($array['acl']) ? $array : NULL;
}

/**
 * Implementation of hook_nodeapi
 */
function acl_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  switch ($op) {
    case 'delete':
      db_query("DELETE FROM {acl_node} WHERE nid = %d", $node->nid);
      break;
  }
}

/**
 * Implementation of hook_user
 */
function acl_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {
    case 'delete':
      db_query("DELETE FROM {acl_user} WHERE uid = %d", $account->uid);
      break;
  }
}

/**
 * Implementation of hook_disable
 */
function acl_disable() {
  drupal_set_message(t('You have disabled the ACL module&mdash;to avoid permission problems you should now go to !link and click on the [!button] button!', array(
    '!link' => l('admin/content/node-settings', 'admin/content/node-settings'),
    '!button' => t('Rebuild permissions'),
  )));
}

/**
 * Implementation of hook_node_access_explain
 */
function acl_node_access_explain($row) {
  static $interpretations = array();
  if ($row->realm == 'acl') {
    if (!isset($interpretations[$row->gid])) {
      $acl = db_fetch_object(db_query("SELECT * FROM {acl} WHERE acl_id = %d", $row->gid));
      $result = db_query("SELECT u.name FROM {acl_user} au, {users} u WHERE au.acl_id = %d AND au.uid = u.uid", $row->gid);
      while ($user = db_fetch_object($result)) {
        $users[] = $user->name;
      }
      if (isset($users)) {
        $interpretations[$row->gid] = "{$acl->module}/{$acl->name}: " . implode(', ', $users);
      }
      elseif ($row->gid == 0) {
        $result = db_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 = %d AND au.uid IS NULL", $row->nid);
        while ($acl = db_fetch_object($result)) {
          $rows[] = "{$acl->acl_id}:&nbsp;{$acl->module}/{$acl->name}";
        }
        if (!empty($rows)) {
          return implode('<br />', $rows);
        }
        return 'No access via ACL.';
      }
      else {
        $interpretations[$row->gid] = "{$acl->module}/{$acl->name}: no users!";
      }
    }
    return $interpretations[$row->gid];
  }
}

Functions

Namesort descending Description
acl_add_user Add the specified UID to an ACL.
acl_create_new_acl Create a new ACL.
acl_delete_acl Delete an existing ACL.
acl_disable Implementation of hook_disable
acl_edit_form 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.
acl_edit_form_after_build Process a form that had our buttons on it.
acl_elements Provide a special button type that doesn't get its #name blasted.
acl_get_id_by_name Gets the id of an acl
acl_get_uids Gets the uids of an acl
acl_has_users Determines if an acl has some assigned users
acl_nodeapi Implementation of hook_nodeapi
acl_node_access_explain Implementation of hook_node_access_explain
acl_node_access_records Implementation of hook_node_access_grants (from node_access)
acl_node_add_acl Provide access control to a node based upon an ACL id.
acl_node_clear_acls Clear all of a module's ACL's from a node.
acl_node_grants Implementation of hook_node_grants
acl_node_remove_acl Remove an ACL completely from a node.
acl_remove_user Remove the specified UID from an ACL.
acl_save_form Write the results of a form.
acl_user Implementation of hook_user
theme_acl_button