You are here

subuser.module in Subuser 7.2

Same filename and directory in other branches
  1. 8 subuser.module
  2. 5 subuser.module
  3. 6 subuser.module

Provides primary Drupal hook implementations.

@author Jimmy Berry ("boombatower", http://drupal.org/user/214218)

File

subuser.module
View source
<?php

/**
 * @file
 * Provides primary Drupal hook implementations.
 *
 * @author Jimmy Berry ("boombatower", http://drupal.org/user/214218)
 */

/**
 * Implements hook_permission().
 */
function subuser_permission() {
  $permissions = array(
    'administer subusers' => array(
      'title' => t('Administer subusers'),
      'description' => t('Allows a user to administer subusers.'),
    ),
    'view subusers' => array(
      'title' => t('View all subusers'),
      'description' => t('Allows viewing all subusers. Own subuser can be seen by default.'),
    ),
    'edit subusers' => array(
      'title' => t('Edit subusers'),
      'description' => t('Allows a user to edit subusers.'),
    ),
    'delete subusers' => array(
      'title' => t('Delete subusers'),
      'description' => t('Allows a user to delete subusers.'),
    ),
    'override subuser relation' => array(
      'title' => t('Override relation'),
      'description' => t('Override the default for subuser_relation field which determines if a relation should be stored.'),
    ),
  );

  // Provide a create subuser permission for each role.
  foreach (user_roles(TRUE) as $rid => $role) {
    $permissions['create subuser ' . $rid] = array(
      'title' => t('Create an %role', array(
        '%role' => $role,
      )),
    );
  }
  return $permissions;
}

/**
 * Implements hook_menu().
 */
function subuser_menu() {
  $items = array();
  $items['user/%user/subuser/create'] = array(
    'title' => 'Add user',
    'page callback' => 'drupal_goto',
    'page arguments' => array(
      'admin/people/create',
    ),
    'access callback' => 'subuser_access_create',
    'type' => MENU_LOCAL_ACTION,
  );
  return $items;
}

/**
 * Implements hook_menu_alter().
 */
function subuser_menu_alter(&$items) {
  $items['admin/people/create']['access callback'] = 'subuser_access_create_callback';
  $items['user/%user']['access callback'] = 'subuser_access_view_callback';
  $items['user/%user/cancel']['access callback'] = 'subuser_access_delete_callback';
  $items['user/%user/cancel/confirm/%/%']['access callback'] = 'subuser_access_delete_callback';
  $items['user/%user/edit']['access callback'] = 'subuser_access_edit_callback';
}

/**
 * Implements hook_profile2_access().
 */
function subuser_profile2_access($op, $profile = NULL, $account = NULL) {
  global $user;

  // Fall through if we're not checking access for the current user account
  if ((!isset($account) || $account->uid == $user->uid) && isset($profile->uid)) {
    switch ($op) {
      case 'view':
        if (subuser_access_view_callback($profile->uid)) {
          return TRUE;
        }
        break;
      case 'edit':
        if (subuser_access_edit_callback($profile->uid)) {
          return TRUE;
        }
        break;
      case 'delete':
        if (subuser_access_delete_callback($profile->uid)) {
          return TRUE;
        }
    }

    // Do not explicitly deny access so others may still grant access.
  }
}

/**
 * Check if an account has access to at least one create subuser permission.
 *
 * @param $account
 *   (optional) The account to check, if not given use currently logged in user.
 * @return
 *   Boolean TRUE if the account has access to create a subuser.
 */
function subuser_access_create($account = NULL) {
  global $user;
  if (!isset($account)) {
    $account = $user;
  }
  foreach (user_roles(TRUE) as $rid => $role) {
    if (user_access('create subuser ' . $rid, $account)) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Our access callback for user editing - only permits users with
 * 'edit subusers' to edit user or parent-user to edit subusers
 *
 * @param $account
 *   the account being edited (user object or uid)
 */
function subuser_access_edit_callback($account) {
  global $user;
  $children = subuser_load_all($user);
  $acct_uid = is_object($account) ? $account->uid : $account;
  return ($user->uid == $acct_uid || user_access('administer users') || user_access('edit subusers') && in_array($acct_uid, $children)) && $acct_uid > 0;
}

/**
 * Our access callback for user deleting - only permits users with
 * 'delete subusers' to delete user or parent-user to delete subusers
 *
 * @param $account
 *   the account being deleted (user object or uid)
 */
function subuser_access_delete_callback($account) {
  global $user;
  $children = subuser_load_all($user);
  $acct_uid = is_object($account) ? $account->uid : $account;
  return ($user->uid == $acct_uid && user_access('cancel account') || user_access('delete subusers') && in_array($acct_uid, $children) || user_access('administer users')) && $acct_uid > 0;
}

/**
 * Our access callback for user viewing - only permits users with
 * 'view subusers' to view user or parent-user to view subusers
 *
 * @param $account
 *   the account being viewed (user object or uid)
 */
function subuser_access_view_callback($account) {
  global $user;
  $children = subuser_load_all($user);
  $acct_uid = is_object($account) ? $account->uid : $account;

  // Never allow access to view the anonymous user account.
  if ($acct_uid) {

    // Admins can view all, users can view own profiles at all times.
    if ($user->uid == $acct_uid || user_access('administer users') || user_access('view subusers', $user) && in_array($acct_uid, $children)) {
      return TRUE;
    }
    elseif (user_access('access user profiles')) {

      // At this point, load the complete account object.
      if (!is_object($account)) {
        $account = user_load((int) $acct_uid);
      }
      return is_object($account) && $account->access && $account->status;
    }
  }
  return FALSE;
}

/**
 * Determine whether the user has a given privilege.
 *
 * If not subuser_access_create() is checked to determin if the permission
 * should be grantted for the current request. The 'access callback' for
 * admin/people/create is changed to this function which should be given the
 * string 'administer users'.
 *
 * @param $string
 *   The permission, such as "administer nodes", being checked for.
 * @param $account
 *   (optional) The account to check, if not given use currently logged in user.
 * @return
 *   Boolean TRUE if the current user has the requested permission.
 */
function subuser_access_create_callback($string, $account = NULL) {
  global $user;
  if (!isset($account)) {
    $account = $user;
  }
  $user_loaded = user_load($account->uid);
  $total_subusers = count(subuser_load_all($account));
  $subuser_limit = field_get_items('user', $user_loaded, 'field_subuser_limit');
  $max_subusers = '';
  if (isset($subuser_limit[0]['value'])) {
    $max_subusers = $subuser_limit[0]['value'];
  }
  drupal_alter('subuser_limit', $max_subusers, $user);
  if (subuser_access_create($account) && ($max_subusers > $total_subusers || $max_subusers == '')) {
    $static =& drupal_static('user_access');
    $static[$account->uid][$string] = TRUE;
  }
  return user_access($string, $account);
}

/**
 * Implements hook_form_alter().
 */
function subuser_form_alter(&$form, &$form_state, $form_id) {
  global $user;
  switch ($form_id) {
    case 'user_account_form':
    case 'user_profile_form':
      if (!isset($form['account']) || $form['#user_category'] != 'account') {
        return;
      }
      $account = $form['#user'];

      // If the user does not have access to the roles field then filter the roles
      // field based on subuser permissions and display if more then one left. If
      // the user has 'administer permissions' then the #access will be set to TRUE
      // and they will have access to all roles, otherwise if the user has access
      // to this page through subuser then only provide them with the roles they
      // are allowed based on subuser. All users will have at least one role, but
      // that role may be 'authenticated user' which is not included in #options.
      if (!$form['account']['roles']['#access']) {
        $parents = subuser_load_all($account, FALSE);
        if (user_access('edit subusers', $user) && in_array($user->uid, $parents)) {
          foreach ($form['account']['roles']['#options'] as $rid => $role) {
            if (!user_access('create subuser ' . $rid)) {
              unset($form['account']['roles']['#options'][$rid]);
            }
          }
          $form['account']['roles']['#access'] = count($form['account']['roles']['#options']) > 0;
        }
      }

      // Remove the limit user setting from users which do not have the
      // administer subusers permissions.
      $form['field_subuser_limit']['#access'] = user_access('administer subusers', $user);
      break;
    case 'user_register_form':

      // Remove the limit user setting from users which do not have the
      // administer subusers permissions.
      $form['field_subuser_limit']['#access'] = user_access('administer subusers', $user);

      // Expose any roles to which the user has access to grant, as above.
      if (!$form['account']['roles']['#access']) {
        foreach ($form['account']['roles']['#options'] as $rid => $role) {
          if (!user_access('create subuser ' . $rid)) {
            unset($form['account']['roles']['#options'][$rid]);
          }
        }
        $form['account']['roles']['#access'] = count($form['account']['roles']['#options']) > 0;
      }
      break;
  }
}

/**
 * Implements hook_form_FORM_ID_alter(): user_register_form.
 */
function subuser_form_user_register_form_alter(&$form, &$form_state) {
  global $user;
  $form['subuser_relation'] = array(
    '#type' => 'checkbox',
    '#title' => t('User relation'),
    '#description' => t('Store a relationship that will allow for further management of the user.'),
    '#default_value' => $user->uid && variable_get('subuser_relation', TRUE),
    '#access' => $user->uid && user_access('override subuser relation'),
  );
  $form['#submit'][] = 'subuser_user_register_form_submit';
}

/**
 * Additional submit handler for user_register_form.
 */
function subuser_user_register_form_submit($form, &$form_state) {
  global $user;

  // If the subuser relation is to be stored then create the relation.
  if ($form_state['values']['subuser_relation']) {
    $endpoints = array(
      array(
        'entity_type' => 'user',
        'entity_id' => $form_state['user']->uid,
      ),
      array(
        'entity_type' => 'user',
        'entity_id' => $user->uid,
      ),
    );
    $relation = relation_create('subuser', $endpoints);
    relation_save($relation);
  }
}

/**
 * Load all related accounts.
 *
 * @param $account
 *   The user account to which all other accounts will be related.
 * @param $children
 *   (Optional) Boolean TRUE to load children of account, otherwise FALSE to
 *   load parent(s) of account.
 * @return
 *   An associative array of related accounts were key and value is user ID.
 */
function subuser_load_all($account, $children = TRUE) {
  $related =& drupal_static(__FUNCTION__);

  // Determine the index we need to look at based on the $children argument.
  // The subuser relation has the child entity at index 0 and parent at 1. If
  // $children is TRUE then we want to collect the uids from index 0, otherwise
  // the uids from index 1.
  $index = (int) (!$children);

  // Check to see if the related accounts are cached, otherwise load them.
  if (!isset($related[$account->uid][$index])) {

    // Select all user entities where the given account is either the parent or
    // child based on the value of $children.
    $results = relation_query('user', $account->uid, (int) $children)
      ->entityCondition('bundle', 'subuser')
      ->execute();

    // Loop over results and collect uids.
    $uids = array();
    foreach ($results as $result) {
      if ($relation = relation_load($result->rid, $result->vid)) {
        $uids[$uid = (int) $relation->endpoints[LANGUAGE_NONE][$index]['entity_id']] = $uid;
      }
    }

    // Store collected uids in static cache.
    $related[$account->uid][$index] = $uids;
  }
  return $related[$account->uid][$index];
}

/**
 * Implements hook_ctools_plugin_api().
 */
function subuser_ctools_plugin_api($module, $api) {
  if ($module == 'relation' && $api == 'relation_type_default') {
    return array(
      'version' => 1,
    );
  }
}

Functions

Namesort descending Description
subuser_access_create Check if an account has access to at least one create subuser permission.
subuser_access_create_callback Determine whether the user has a given privilege.
subuser_access_delete_callback Our access callback for user deleting - only permits users with 'delete subusers' to delete user or parent-user to delete subusers
subuser_access_edit_callback Our access callback for user editing - only permits users with 'edit subusers' to edit user or parent-user to edit subusers
subuser_access_view_callback Our access callback for user viewing - only permits users with 'view subusers' to view user or parent-user to view subusers
subuser_ctools_plugin_api Implements hook_ctools_plugin_api().
subuser_form_alter Implements hook_form_alter().
subuser_form_user_register_form_alter Implements hook_form_FORM_ID_alter(): user_register_form.
subuser_load_all Load all related accounts.
subuser_menu Implements hook_menu().
subuser_menu_alter Implements hook_menu_alter().
subuser_permission Implements hook_permission().
subuser_profile2_access Implements hook_profile2_access().
subuser_user_register_form_submit Additional submit handler for user_register_form.