You are here

subuser.module in Subuser 8

Same filename and directory in other branches
  1. 5 subuser.module
  2. 6 subuser.module
  3. 7.2 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 subusers'),
      'description' => t('Allows a user to view subusers.'),
    ),
    '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_alter().
 */
function subuser_menu_alter(&$items) {
  $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.
  }
}

/**
 * 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) {
  $account = \Drupal::currentUser();
  subuser_load_all($account);
  switch ($form_id) {
    case 'user_account_form':
    case 'user_profile_form':
      if (!isset($form['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 that doesnt 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 that doesnt have the administer subusers permissions
      $form['field_subuser_limit']['#access'] = user_access('administer subusers', $user);
      break;
  }
}

/**
 * Implements hook_form_FORM_ID_alter(): user_register_form.
 */
function subuser_form_user_register_form_alter(&$form, &$form_state) {
  if (arg(0) == 'user') {
    $account = user_load(arg(1));
    $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' => $account
        ->id(),
      //&& variable_get('subuser_relation', TRUE),
      '#access' => TRUE,
    );
    $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
    ->id()][$index])) {
    if ($children) {

      // Select all user entities where the given account is either the parent or
      // child based on the value of $children.
      $query = \Drupal::entityQuery('user');
      $results = $query
        ->condition('subuser_parent.target_id', $account
        ->id(), '=')
        ->execute();
      $related[$account
        ->id()][$index] = $results;
    }
    else {
      $parent = user_load($account
        ->id())->subuser_parent->value;
      $related[$account
        ->id()][$index] = $parent;
    }
  }
  return $related[$account
    ->id()][$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_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_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.