You are here

flexiaccess.module in Flexi Access 7

Main hooks for per user access control.

File

flexiaccess.module
View source
<?php

/**
 * @file
 * Main hooks for per user access control.
 */

/**
 * Implements hook_help().
 */
function flexiaccess_help($path, $arg) {
  switch ($path) {
    case 'admin/help#flexiaccess':
      $output = '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Flexi access module provides a simple interfrace to the !acl', array(
        '!acl' => l(t('ACL'), 'http://drupal.org/project/acl/'),
      ));
      $output .= ' (Access Control List) ' . t('module') . '. ';
      $output .= t('It lets you set up and mange ACLs naming individual users that are allowed access to a particular node.') . '</p>';
      $output .= '<h3>' . t('Usage') . '</h3><dl>';
      $output .= '<dt>' . t('Administrative interface:') . '</dt>';
      $output .= '<dd>' . t('The !aif has the following tabs:', array(
        '!aif' => l(t('administrative interface'), 'admin/config/people/flexiaccess'),
      )) . '<br/><ul>';
      $output .= '<li>' . t('Main settings: Enable/disable the content types you want Flexi access to manage. Set up automatic ACL creation. Set default priority for ACL entries.') . '</li>';
      $output .= '<li>' . t('Anonymous user: Set a name for the anonymous user (required to attach an ACL to the anonymous user).') . '</li>';
      $output .= '<li>' . t('Bulk operations: Bulk operations to reset ACL priorities and delete all ACLs.') . '</li></dd></ul>';

      // $output .= '<li>' . t('User Lists: Administer (create/edit/delete)
      // predefined user lists. [forthcoming]') . '</li>';
      $output .= '<dt>' . t('Node interface:') . '</dt>';
      $output .= '<dd>' . t('Administrators viewing a node of a Flexi access enabled content type will see a tab called “Flexi access”. Inside this tab, there is three subfields (<em>view, update, delete</em>). Each subfield can be used to manage an ACL granting individual users view, update, and delete rights for the node.') . '</dd>';
      $output .= '<dt>' . t('User profile interface:') . '</dt>';
      $output .= '<dd>' . t('Administrators viewing a user profile will see a tab named “Flexi access” as part of that profile.  This tab is to manage ACLs for that particular user.');
      $output .= '</dl>';
      if (function_exists('advanced_help_hint_docs')) {
        $output .= '<p>' . advanced_help_hint_docs('flexiaccess', 'https://www.drupal.org/docs/7/modules/flexi-access', TRUE) . '</p>';
      }
      else {
        $output .= t('If you install and enable the module <strong>!url</strong>, you will get more help for <strong>Flexi access</strong>.', array(
          '!url' => l('Advanced help hint', 'https://www.drupal.org/project/advanced_help_hint'),
        ));
      }
      return $output;
  }
}

/**
 * Implements hook_permission().
 */
function flexiaccess_permission() {
  return array(
    'administer flexiaccess' => array(
      'title' => t('Administer Flexi access'),
      'description' => t('Access the Flexi access administrative interface.  <em>Give to trusted roles only.</em>'),
    ),
    'access flexiaccess' => array(
      'title' => t('Administer all nodes'),
      'description' => t('Administer access to all nodes mangaged by Flexi access. <em>Give to trusted roles only.</em>'),
    ),
    'access flexiaccess own' => array(
      'title' => t('Administer own nodes'),
      'description' => t('Administer access to own nodes mangaged by Flexi access.'),
    ),
    'flexiaccess create acl' => array(
      'title' => t('Create ACLs'),
      'description' => t('Create an ACL for a node.'),
    ),
    'flexiaccess view' => array(
      'title' => t('Grant view permission'),
      'description' => t('Grant or withdraw view permission for a managed node.'),
    ),
    'flexiaccess update' => array(
      'title' => t('Grant update permission'),
      'description' => t('Grant or withdraw edit/update permission for a managed node.'),
    ),
    'flexiaccess delete' => array(
      'title' => t('Grant delete permission'),
      'description' => t('Grant or withdraw delete permission for a managed node.'),
    ),
  );
}

/**
 * Implements hook_admin_paths().
 */
function flexiaccess_admin_paths() {
  $nodepath = array(
    'node/*/flexiaccess' => TRUE,
  );
  return $nodepath;
}

/**
 * Implements hook_menu().
 */
function flexiaccess_menu() {
  $items = array();
  $items['admin/config/people/flexiaccess'] = array(
    'title' => 'Flexi access',
    'description' => 'Administrator settings for Flexi access.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'flexiaccess_admin_content',
    ),
    'access arguments' => array(
      'administer flexiaccess',
    ),
    'file' => 'flexiaccess.admin.inc',
    'type' => MENU_NORMAL_ITEM,
  );
  $items['admin/config/people/flexiaccess/settings'] = array(
    'title' => 'Main settings',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 0,
  );
  $items['admin/config/people/flexiaccess/anon'] = array(
    'title' => 'Anonymous user',
    'description' => 'Prime anonymous user for use by Flexi access.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'flexiaccess_admin_anon',
    ),
    'access arguments' => array(
      'administer flexiaccess',
    ),
    'file' => 'flexiaccess.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
  );
  $items['admin/config/people/flexiaccess/bulkop'] = array(
    'title' => 'Bulk operations',
    'description' => 'Perform bulk operations on ACLs.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'flexiaccess_admin_bulkop',
    ),
    'access arguments' => array(
      'administer flexiaccess',
    ),
    'file' => 'flexiaccess.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
  );
  $items['node/%node/flexiaccess'] = array(
    'title' => 'Flexi access',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'flexiaccess_page',
      1,
    ),
    'access callback' => '_flexiaccess_node_access',
    'access arguments' => array(
      1,
    ),
    'file' => 'flexiaccess.nodes.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 10,
  );
  $items['user/%user/flexiaccess'] = array(
    'title' => 'Flexi access',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'flexiaccess_user',
      1,
    ),
    'access arguments' => array(
      'administer flexiaccess',
    ),
    'file' => 'flexiaccess.users.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 10,
  );
  $items['flexiaccess/node_autocomplete'] = array(
    'title' => 'Flexiaccess Node autocomplete',
    'page callback' => 'flexiaccess_node_autocomplete',
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer flexiaccess',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'flexiaccess.users.inc',
  );
  return $items;
}

/**
 * Implements hook_menu_alter().
 *
 * This adds a "delete" tab to the node if user has delete permission.
 */
function flexiaccess_menu_alter(&$items) {
  $items['node/%node/delete']['context'] = MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE;
}

/**
 * Implements hook_theme().
 */
function flexiaccess_theme() {
  return array(
    'flexiaccess_admin_content' => array(
      'render element' => 'form',
      'file' => 'flexiaccess.admin.inc',
    ),
  );
}

/**
 * Helper function to count number of ACLs attached to node $nid.
 */
function _flexiaccess_acl_count($nid) {
  $query = db_select('acl_node', 'n');
  $query
    ->join('acl', 'a', 'a.acl_id = n.acl_id AND n.nid = :nnn', array(
    ':nnn' => $nid,
  ));
  $query
    ->fields('a', array(
    'acl_id',
  ))
    ->condition('a.module', 'flexiaccess')
    ->condition('n.nid', $nid);
  $result = $query
    ->execute();
  return $result
    ->rowCount();
}

/**
 * Access callback function to see if user can access Flexi access.
 */
function _flexiaccess_node_access($node) {
  global $user;
  $access = FALSE;
  $types = variable_get('flexiaccess_types', array());
  if (isset($types[$node->type]) && $types[$node->type]) {
    if (user_access('access flexiaccess')) {
      $access = TRUE;
    }
    elseif (user_access('access flexiaccess own')) {
      if ($node->uid == $user->uid) {
        $access = TRUE;
      }
    }
  }
  if (!$access) {
    return FALSE;
  }
  $cnt = _flexiaccess_acl_count($node->nid);
  if ($cnt) {
    $ops = 0;
    if (user_access('flexiaccess view')) {
      $ops++;
    }
    if (user_access('flexiaccess update')) {
      $ops++;
    }
    if (user_access('flexiaccess delete')) {
      $ops++;
    }
    return $ops;
  }
  else {
    if (user_access('flexiaccess create acl')) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Just make sure that the ACLs exist in the DB.
 *
 * This is just for code re-use.
 *
 * @param int $nid
 *    Node id.
 */
function _flexiaccess_create_acl_rows($nid) {
  global $user;
  if (module_exists('acl')) {
    foreach (array(
      'view',
      'update',
      'delete',
    ) as $op) {
      $acl_id = acl_get_id_by_name('flexiaccess', $op . '_' . $nid);
      if (!$acl_id) {
        $acl_id = acl_create_acl('flexiaccess', $op . '_' . $nid);
      }
      if ('view' == $op || user_access('flexiaccess ' . $op)) {
        acl_add_user($acl_id, $user->uid);
      }
      acl_node_add_acl($nid, $acl_id, (int) ($op == 'view'), (int) ($op == 'update'), (int) ($op == 'delete'), variable_get('flexiaccess_priority', 0));
    }
  }
}

/**
 * Used by the ACL module.
 */
function flexiaccess_enabled() {
  return !flexiaccess_disabling();
}

/**
 * Remembers if we have disabled access.
 */
function flexiaccess_disabling($set = NULL) {
  static $disabling = FALSE;
  if (isset($set)) {
    $disabling = $set;
  }
  return $disabling;
}

/**
 * Implements hook_node_insert().
 *
 * Creates empty acl for the new node if necessary.
 */
function flexiaccess_node_insert($node) {
  $types = array_filter(variable_get('flexiaccess_types', array()));
  if (in_array($node->type, $types)) {
    $auto_acl = variable_get('flexiaccess_typesettings_' . $node->type . '_autoACL', 0);
    if ($auto_acl) {
      _flexiaccess_create_acl_rows($node->nid);
    }
  }
}

/**
 * Set the priority of every ACL created by Flexi access to a configured value.
 */
function flexiaccess_reset_priorities() {
  $priority = variable_get('flexiaccess_priority', 0);

  /*
   * The docs say about db_query:
   * Do not use this function for INSERT, UPDATE, or DELETE queries.
   * But inner join is not possible on db_update, and a direct sql is
   * better than db_update with a subquery.
   */
  $result = db_query("UPDATE acl_node INNER JOIN acl ON acl.acl_id = acl_node.acl_id SET acl_node.priority = :prio WHERE acl.module = 'flexiaccess'", array(
    ':prio' => $priority,
  ));
  $num = $result
    ->rowCount();
  if ($num > 0) {
    node_access_needs_rebuild(TRUE);
  }
  drupal_set_message("Updated {$num} ACLs with priority {$priority} .");
}

/**
 * Remove all ACLs created by Flexi access.
 */
function flexiaccess_delete_all() {
  $result = db_select('acl', 'a')
    ->fields('a', array(
    'acl_id',
  ))
    ->condition('module', 'flexiaccess', '=')
    ->execute();
  $num = $result
    ->rowCount();
  foreach ($result as $record) {
    acl_delete_acl($record->acl_id);
  }
  if ($num > 0) {
    node_access_needs_rebuild(TRUE);
  }
  drupal_set_message("Deleted {$num} ACLs");
}

Functions

Namesort descending Description
flexiaccess_admin_paths Implements hook_admin_paths().
flexiaccess_delete_all Remove all ACLs created by Flexi access.
flexiaccess_disabling Remembers if we have disabled access.
flexiaccess_enabled Used by the ACL module.
flexiaccess_help Implements hook_help().
flexiaccess_menu Implements hook_menu().
flexiaccess_menu_alter Implements hook_menu_alter().
flexiaccess_node_insert Implements hook_node_insert().
flexiaccess_permission Implements hook_permission().
flexiaccess_reset_priorities Set the priority of every ACL created by Flexi access to a configured value.
flexiaccess_theme Implements hook_theme().
_flexiaccess_acl_count Helper function to count number of ACLs attached to node $nid.
_flexiaccess_create_acl_rows Just make sure that the ACLs exist in the DB.
_flexiaccess_node_access Access callback function to see if user can access Flexi access.