You are here

ldap_user.module in Lightweight Directory Access Protocol (LDAP) 7.2

Module for the LDAP User Entity.

File

ldap_user/ldap_user.module
View source
<?php

/**
 * @file
 * Module for the LDAP User Entity.
 */
define('LDAP_USER_DRUPAL_HELP_URL', 'http://drupal.org/node/997082');

// Configurable drupal acct provision triggers.
define('LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE', 1);
define('LDAP_USER_DRUPAL_USER_PROV_ON_AUTHENTICATE', 2);
define('LDAP_USER_DRUPAL_USER_PROV_ON_ALLOW_MANUAL_CREATE', 3);

// Configurable ldap entry provision triggers.
define('LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE', 6);
define('LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE', 7);
define('LDAP_USER_LDAP_ENTRY_DELETE_ON_USER_DELETE', 8);

// Provisioning events (events are triggered by triggers)
define('LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER', 1);
define('LDAP_USER_EVENT_CREATE_DRUPAL_USER', 2);
define('LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY', 3);
define('LDAP_USER_EVENT_CREATE_LDAP_ENTRY', 4);
define('LDAP_USER_EVENT_LDAP_ASSOCIATE_DRUPAL_ACCT', 5);

// Results of ldap entry provisioning.
define('LDAP_USER_PROVISION_LDAP_ENTRY_EXISTS', 1);
define('LDAP_USER_PROVISION_LDAP_ENTRY_CREATE_FAILED', 2);
define('LDAP_USER_PROVISION_LDAP_ENTRY_SYNCH_FAILED', 3);

// Options for what to do when existing non ldap associated Drupal account conflicts with ldap account.
define('LDAP_USER_CONFLICT_LOG', 1);
define('LDAP_USER_CONFLICT_RESOLVE', 2);
define('LDAP_USER_CONFLICT_RESOLVE_DEFAULT', 2);

// Options for what to do if another Drupal account has the same email address.
define('LDAP_USER_ACCOUNTS_WITH_SAME_EMAIL_DISABLED', 0);
define('LDAP_USER_ACCOUNTS_WITH_SAME_EMAIL_ENABLED', 1);

// Options for dealing with manual account creation that conflict with ldap entries.
define('LDAP_USER_MANUAL_ACCT_CONFLICT_REJECT', 1);
define('LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE', 2);
define('LDAP_USER_MANUAL_ACCT_CONFLICT_SHOW_OPTION_ON_FORM', 3);
define('LDAP_USER_MANUAL_ACCT_CONFLICT_NO_LDAP_ASSOCIATE', 4);

// Options for account creation behavior.
define('LDAP_USER_ACCT_CREATION_LDAP_BEHAVIOR', 4);
define('LDAP_USER_ACCT_CREATION_USER_SETTINGS_FOR_LDAP', 1);
define('LDAP_USER_ACCT_CREATION_LDAP_BEHAVIOR_DEFAULT', 4);

// Provision directions.
define('LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER', 1);
define('LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY', 2);
define('LDAP_USER_PROV_DIRECTION_NONE', 3);
define('LDAP_USER_PROV_DIRECTION_ALL', 4);
define('LDAP_USER_PROV_RESULT_NO_ERROR', 0);
define('LDAP_USER_PROV_RESULT_NO_PWD', 1);
define('LDAP_USER_PROV_RESULT_BAD_PARAMS', 2);

// Need to avoid conflicting with server ids.
define('LDAP_USER_NO_SERVER_SID', 0);
define('LDAP_USER_TEST_FORM_PATH', 'admin/config/people/ldap/user/test');
define('LDAP_USER_WS_USER_PATH', 'ldap/user/ws');

// Machine name for the setting to provision from last authentication server.
define('LDAP_USER_AUTH_SERVER_SID', 'ldap_last_authserv');
define('LDAP_USER_SESSION_PROV_SID', 'ldap_user_session_prov_sid');

/**
 * Implements hook_menu().
 */
function ldap_user_menu() {
  $items = [];
  $items['admin/config/people/ldap/user'] = [
    'title' => '3. User',
    'description' => 'Settings related to user provisioning and data synching between ldap and drupal users.',
    'page callback' => 'drupal_get_form',
    'page arguments' => [
      'ldap_user_admin_form',
    ],
    'access arguments' => [
      'administer site configuration',
    ],
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
    'file' => 'ldap_user.admin.inc',
  ];
  $items[LDAP_USER_TEST_FORM_PATH] = [
    'title' => 'Test LDAP User Functionality for a given user.',
    'description' => '',
    'page callback' => 'drupal_get_form',
    'page arguments' => [
      'ldap_user_test_form',
    ],
    'access arguments' => [
      'administer site configuration',
    ],
    'file' => 'ldap_user.test_form.inc',
    'type' => MENU_LOCAL_ACTION,
  ];
  return $items;
}

/**
 * Implements hook_init().
 */
function ldap_user_init() {

  // Reset for simpletest page load behavior.
  ldap_user_ldap_provision_semaphore(NULL, NULL, NULL, TRUE);
}

/**
 * Implements hook_theme().
 */
function ldap_user_theme() {
  return [
    'ldap_user_conf_form' => [
      'render element' => 'form',
      'file' => 'ldap_user.theme.inc',
    ],
  ];
}

/**
 * Implements hook_cron().
 */
function ldap_user_cron() {
  $ldap_user_conf = ldap_user_conf();
  if ($ldap_user_conf->orphanedDrupalAcctBehavior != 'ldap_user_orphan_do_not_check') {
    module_load_include('inc', 'ldap_user', 'ldap_user.cron');
    $result = _ldap_user_orphans($ldap_user_conf);
    if ($result !== TRUE) {
      watchdog('ldap_user', 'LDAP User check for orphaned ldap provisioned Drupal accounts failed', [], WATCHDOG_ERROR);
    }
  }
}

/**
 * Implements hook_mail().
 */
function ldap_user_mail($key, &$message, $params) {
  switch ($key) {
    case 'orphaned_accounts':
      $message['subject'] = variable_get('site_name') . ' ' . t('Orphaned LDAP Users');
      $message['body'][] = t('The following !count Drupal users no longer have
        corresponding LDAP Entries.  Perhaps they have been removed from the LDAP
        and should be removed:', [
        '!count' => count($params['accounts']),
      ]) . "\n\n" . t('username,mail,edit url') . "\n" . join("\n", $params['accounts']);
      break;
  }
}

/**
 * Implements hook_ldap_derived_user_name_alter().
 */
function ldap_user_ldap_derived_user_name_alter(&$name, $ldap_user) {

  // Alter $name in some way here.
}

/**
 *
 */
function ldap_user_conf_cache_clear() {
  $discard = ldap_user_conf('admin', TRUE);
  $discard = ldap_user_conf(NULL, TRUE);
  ldap_user_ldap_provision_semaphore(NULL, NULL, NULL, TRUE);
}

/**
 * Get ldapUserConf or ldapUserConfAdmin object.
 *
 * @param enum $type
 *   is 'admin' for ldapUserConfAdmin object or NULL for ldapUserConf object.
 * @param bool $resect
 *   clear static cache of object.
 *
 * @return \LdapUserConf|\LdapUserConfAdmin
 */
function ldap_user_conf($type = NULL, $reset = FALSE) {
  static $ldap_user_conf;
  static $ldap_user_conf_admin;
  if ($type == 'admin' && ($reset || !is_object($ldap_user_conf_admin))) {
    ldap_servers_module_load_include('php', 'ldap_user', 'LdapUserConfAdmin.class');
    $ldap_user_conf_admin = new LdapUserConfAdmin();
  }
  elseif ($type != 'admin' && ($reset || !is_object($ldap_user_conf))) {
    ldap_servers_module_load_include('php', 'ldap_user', 'LdapUserConf.class');
    $ldap_user_conf = new LdapUserConf();
  }
  return $type == 'admin' ? $ldap_user_conf_admin : $ldap_user_conf;
}

/**
 * Implements hook_ldap_attributes_needed_alter().
 */
function ldap_user_ldap_attributes_needed_alter(&$attributes, $params) {

  // Puid attributes are server specific.
  if (isset($params['sid']) && $params['sid']) {
    if (is_scalar($params['sid'])) {
      $ldap_server = ldap_servers_get_servers($params['sid'], 'enabled', TRUE);
    }
    else {
      $ldap_server = $params['sid'];
    }

    // Failed to find enabled server.
    if ($ldap_server === FALSE) {
      return;
    }
    $ldap_user_conf = ldap_user_conf();
    if (!isset($attributes['dn'])) {
      $attributes['dn'] = [];
    }

    // Force dn "attribute" to exist.
    $attributes['dn'] = ldap_servers_set_attribute_map($attributes['dn']);

    // Add the attributes required by the user configuration when provisioning drupal users.
    switch ($params['ldap_context']) {
      case 'ldap_user_insert_drupal_user':
      case 'ldap_user_update_drupal_user':
      case 'ldap_user_ldap_associate':
      case 'all':
        $attributes[$ldap_server->user_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->user_attr]);
        $attributes[$ldap_server->mail_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->mail_attr]);
        if ($ldap_server->picture_attr) {
          $attributes[$ldap_server->picture_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->picture_attr]);
        }
        if ($ldap_server->unique_persistent_attr) {
          $attributes[$ldap_server->unique_persistent_attr] = ldap_servers_set_attribute_map(@$attributes[$ldap_server->unique_persistent_attr]);
        }
        if ($ldap_server->mail_template) {
          ldap_servers_token_extract_attributes($attributes, $ldap_server->mail_template);
        }
        break;
    }
    $ldap_context = empty($params['ldap_context']) ? NULL : $params['ldap_context'];
    $direction = empty($params['direction']) ? $ldap_user_conf
      ->ldapContextToProvDirection($ldap_context) : $params['direction'];
    $attributes_required_by_user_module_mappings = $ldap_user_conf
      ->getLdapUserRequiredAttributes($direction, $ldap_context);
    $attributes = array_merge($attributes_required_by_user_module_mappings, $attributes);
  }
}

/**
 * Implements hook_ldap_user_attrs_list_alter().
 */
function ldap_user_ldap_user_attrs_list_alter(&$available_user_attrs, &$params) {
  $sid = isset($params['ldap_server']) && is_object($params['ldap_server']) ? $params['ldap_server']->sid : LDAP_USER_NO_SERVER_SID;
  $ldap_user_conf = $params['ldap_user_conf'];
  $direction = isset($params['direction']) ? $params['direction'] : LDAP_USER_PROV_DIRECTION_NONE;
  if ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
    $available_user_attrs['[property.name]'] = [
      'name' => 'Property: Username',
      'source' => '',
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
      'enabled' => TRUE,
      'prov_events' => [
        LDAP_USER_EVENT_CREATE_LDAP_ENTRY,
        LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY,
      ],
      'config_module' => 'ldap_user',
      'prov_module' => 'ldap_user',
      'configurable_to_ldap' => TRUE,
    ];
    $available_user_attrs['[property.mail]'] = [
      'name' => 'Property: Email',
      'source' => '',
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
      'enabled' => TRUE,
      'prov_events' => [
        LDAP_USER_EVENT_CREATE_LDAP_ENTRY,
        LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY,
      ],
      'config_module' => 'ldap_user',
      'prov_module' => 'ldap_user',
      'configurable_to_ldap' => TRUE,
    ];
    $available_user_attrs['[property.picture]'] = [
      'name' => 'Property: picture',
      'source' => '',
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
      'enabled' => TRUE,
      'prov_events' => [
        LDAP_USER_EVENT_CREATE_LDAP_ENTRY,
        LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY,
      ],
      'config_module' => 'ldap_user',
      'prov_module' => 'ldap_user',
      'configurable_to_ldap' => TRUE,
    ];
    $available_user_attrs['[property.uid]'] = [
      'name' => 'Property: Drupal User Id (uid)',
      'source' => '',
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
      'enabled' => TRUE,
      'prov_events' => [
        LDAP_USER_EVENT_CREATE_LDAP_ENTRY,
        LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY,
      ],
      'config_module' => 'ldap_user',
      'prov_module' => 'ldap_user',
      'configurable_to_ldap' => TRUE,
    ];
  }

  // 1. Drupal user properties
  // 1.a make sure empty array are present so array + function works.
  foreach ([
    'property.status',
    'property.timezone',
    'property.signature',
  ] as $i => $property_id) {
    $property_token = '[' . $property_id . ']';
    if (!isset($available_user_attrs[$property_token]) || !is_array($available_user_attrs[$property_token])) {
      $available_user_attrs[$property_token] = [];
    }
  }

  // @todo make these merges so they don't override saved values such as 'enabled'
  $available_user_attrs['[property.status]'] = $available_user_attrs['[property.status]'] + [
    'name' => 'Property: Acount Status',
    'configurable_to_drupal' => 1,
    'configurable_to_ldap' => 1,
    'user_tokens' => '1=enabled, 0=blocked.',
    'enabled' => FALSE,
    'config_module' => 'ldap_user',
    'prov_module' => 'ldap_user',
  ];
  $available_user_attrs['[property.timezone]'] = $available_user_attrs['[property.timezone]'] + [
    'name' => 'Property: User Timezone',
    'configurable_to_drupal' => 1,
    'configurable_to_ldap' => 1,
    'enabled' => FALSE,
    'config_module' => 'ldap_user',
    'prov_module' => 'ldap_user',
  ];
  $available_user_attrs['[property.signature]'] = $available_user_attrs['[property.signature]'] + [
    'name' => 'Property: User Signature',
    'configurable_to_drupal' => 1,
    'configurable_to_ldap' => 1,
    'enabled' => FALSE,
    'config_module' => 'ldap_user',
    'prov_module' => 'ldap_user',
  ];

  // 2. Drupal user fields.
  $user_fields = field_info_instances('user', 'user');
  foreach ($user_fields as $field_name => $field_instance) {
    $field_id = "[field.{$field_name}]";
    if (!isset($available_user_attrs[$field_id]) || !is_array($available_user_attrs[$field_id])) {
      $available_user_attrs[$field_id] = [];
    }
    $available_user_attrs[$field_id] = $available_user_attrs[$field_id] + [
      'name' => t('Field') . ': ' . $field_instance['label'],
      'configurable_to_drupal' => 1,
      'configurable_to_ldap' => 1,
      'enabled' => FALSE,
      'config_module' => 'ldap_user',
      'prov_module' => 'ldap_user',
    ];
  }
  if (!$ldap_user_conf->provisionsDrupalAccountsFromLdap) {
    $available_user_attrs['[property.mail]']['config_module'] = 'ldap_user';
    $available_user_attrs['[property.name]']['config_module'] = 'ldap_user';
    $available_user_attrs['[property.picture]']['config_module'] = 'ldap_user';
  }
  if ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
    $available_user_attrs['[password.random]'] = [
      'name' => 'Pwd: Random',
      'source' => '',
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
      'enabled' => TRUE,
      'prov_events' => [
        LDAP_USER_EVENT_CREATE_LDAP_ENTRY,
        LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY,
      ],
      'config_module' => 'ldap_user',
      'prov_module' => 'ldap_user',
      'configurable_to_ldap' => TRUE,
    ];

    // Use user password when available fall back to random pwd.
    $available_user_attrs['[password.user-random]'] = [
      'name' => 'Pwd: User or Random',
      'source' => '',
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
      'enabled' => TRUE,
      'prov_events' => [
        LDAP_USER_EVENT_CREATE_LDAP_ENTRY,
        LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY,
      ],
      'config_module' => 'ldap_user',
      'prov_module' => 'ldap_user',
      'configurable_to_ldap' => TRUE,
    ];

    // Use user password, do not modify if unavailable.
    $available_user_attrs['[password.user-only]'] = [
      'name' => 'Pwd: User Only',
      'source' => '',
      'direction' => LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY,
      'enabled' => TRUE,
      'prov_events' => [
        LDAP_USER_EVENT_CREATE_LDAP_ENTRY,
        LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY,
      ],
      'config_module' => 'ldap_user',
      'prov_module' => 'ldap_user',
      'configurable_to_ldap' => TRUE,
    ];
  }

  // This is where need to be added to arrays.
  if (!empty($ldap_user_conf->ldapUserSynchMappings[$direction])) {
    foreach ($ldap_user_conf->ldapUserSynchMappings[$direction] as $target_token => $mapping) {
      if ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER && isset($mapping['user_attr'])) {
        $key = $mapping['user_attr'];
      }
      elseif ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY && isset($mapping['ldap_attr'])) {
        $key = $mapping['ldap_attr'];
      }
      else {
        continue;
      }
      foreach ([
        'ldap_attr',
        'user_attr',
        'convert',
        'direction',
        'enabled',
        'prov_events',
      ] as $k) {
        if (isset($mapping[$k])) {
          $available_user_attrs[$key][$k] = $mapping[$k];
        }
        else {
          $available_user_attrs[$key][$k] = NULL;
        }
        $available_user_attrs[$key]['config_module'] = 'ldap_user';
        $available_user_attrs[$key]['prov_module'] = 'ldap_user';
      }
      if ($mapping['user_attr'] == 'user_tokens') {
        $available_user_attrs['user_attr'] = $mapping['user_tokens'];
      }
    }
  }

  // 3. profile2 fields
  // 4. $user->data array.   will need to be added manually.  perhaps better not to implement this at all?
}

/**
 * Implements hook_help().
 */
function ldap_user_help($path, $arg) {
  $ldap_user_help = t('LDAP user configuration determines how and when
    Drupal accounts are created based on LDAP data and which user fields
    are derived and synched to and from LDAP. See !helplink.', [
    '!helplink' => l(LDAP_USER_DRUPAL_HELP_URL, LDAP_USER_DRUPAL_HELP_URL),
  ]);
  switch ($path) {
    case 'admin/config/people/ldap/user':
      $output = '<p>' . $ldap_user_help . '</p>';
      return $output;
    case 'admin/help#ldap_user':
      $output = '<p>' . $ldap_user_help . '</p>';
      return $output;
  }
}

/**
 * Implements hook_form_FORM_ID_alter(). for user_login_block.
 */
function ldap_user_form_user_login_block_alter(&$form, &$form_state) {
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
}

/**
 * Implements hook_form_FORM_ID_alter(). for user_login_form.
 */
function ldap_user_form_user_login_alter(&$form, $form_state) {
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
}

/**
 * Implements hook_form_FORM_ID_alter(). for user_register_form.
 */
function ldap_user_form_user_profile_form_alter(&$form, $form_state) {
  array_unshift($form['#submit'], 'ldap_user_grab_password_validate');
}

/**
 * Implements hook_form_FORM_ID_alter(). for password_policy_password_tab.
 */
function ldap_user_form_password_policy_password_tab_alter(&$form, &$form_state) {
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
}

/**
 * Implements hook_form_FORM_ID_alter(). for user-pass-reset form. Useful for
 * sites where this is the form ID for a user to intially set their password
 * (user clicks an emailed registration link, is prompted to set their password).
 */
function ldap_user_form_user_pass_reset_alter(&$form, &$form_state) {
  array_unshift($form['#validate'], 'ldap_user_grab_password_validate');
}

/**
 * Store password from logon forms in ldap_user_ldap_provision_pwd static variable
 * for use in provisioning to ldap.
 */
function ldap_user_grab_password_validate($form, &$form_state) {

  // This is not a login form but profile form and user is inserting password to update email.
  if (!empty($form_state['values']['current_pass_required_values'])) {
    if (!empty($form_state['values']['current_pass']) && empty($form_state['values']['pass'])) {
      ldap_user_ldap_provision_pwd('set', $form_state['values']['current_pass']);
    }
    elseif (!empty($form_state['values']['pass'])) {
      ldap_user_ldap_provision_pwd('set', $form_state['values']['pass']);
    }
  }
  elseif (!empty($form_state['values']['pass'])) {
    ldap_user_ldap_provision_pwd('set', $form_state['values']['pass']);
  }
}

/**
 * Implements hook_form_FORM_ID_alter(). for user_register_form.
 */
function ldap_user_form_user_register_form_alter(&$form, $form_state) {
  array_unshift($form['#submit'], 'ldap_user_grab_password_validate');
  if (!user_access('administer users')) {
    return;
  }
  $ldap_user_conf = ldap_user_conf();
  if ($ldap_user_conf->disableAdminPasswordField == TRUE) {
    $form['account']['pass']['#type'] = 'value';
    $form['account']['pass']['#value'] = user_password(20);
    $form['account']['pass_disabled']['#type'] = 'fieldset';
    $form['account']['pass_disabled']['#title'] = t('Password');
    $form['account']['pass_disabled'][]['#markup'] = t('An LDAP setting at /admin/config/people/ldap/user has disabled the password fields. Drupal will store a 20 character random password in the Drupal "users" table, and the user will login with their LDAP password.');
  }
  $ldap_fieldset = [];
  $options = [
    LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE => t('Make this an LDAP Associated account.  If a related LDAP account can not be found, a validation error will appear and the account will not be created.'),
    LDAP_USER_MANUAL_ACCT_CONFLICT_NO_LDAP_ASSOCIATE => t('Do not make this an LDAP Associated account.'),
  ];
  $ldap_fieldset['ldap_user_association'] = [
    '#type' => 'radios',
    '#options' => $options,
    '#required' => FALSE,
    '#title' => t('LDAP Entry Association.'),
  ];
  if ($ldap_user_conf
    ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE)) {
    $ldap_fieldset['ldap_user_association']['#disabled'] = TRUE;
    $ldap_fieldset['ldap_user_association']['#description'] = t('Since "Create
      or Synch to Drupal user anytime a Drupal user account is created or updated"
      is selected at admin/config/people/ldap/user, this option will have no
      effect so its disabled.');
  }
  elseif ($ldap_user_conf->manualAccountConflict != LDAP_USER_MANUAL_ACCT_CONFLICT_SHOW_OPTION_ON_FORM) {
    $ldap_fieldset['ldap_user_association']['#disabled'] = TRUE;
    $ldap_fieldset['ldap_user_association']['#description'] = t('To enable
      this an LDAP server must be selected for provisioning to Drupal in
      admin/config/people/ldap/user and "Show option on user create form..." must be selected.');
  }
  $ldap_fieldset['ldap_user_create_ldap_acct'] = [
    '#type' => 'checkbox',
    '#title' => t('Create corresponding LDAP entry.'),
  ];
  if (!$ldap_user_conf
    ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_DRUPAL_USER_PROV_ON_ALLOW_MANUAL_CREATE)) {
    $ldap_fieldset['ldap_user_create_ldap_acct']['#disabled'] = TRUE;
    $ldap_fieldset['ldap_user_create_ldap_acct']['#description'] = t('To enable
      this an LDAP server must be selected for provisioning to Drupal in
      admin/config/people/ldap/user and manual creation of LDAP accounts
      must be enabled also.');
  }
  if (count($ldap_fieldset) > 0) {
    $form['ldap_user_fields'] = $ldap_fieldset;
    $form['ldap_user_fields']['#type'] = 'fieldset';
    $form['ldap_user_fields']['#title'] = t('LDAP Options');
    $form['ldap_user_fields']['#collapsible'] = TRUE;
    $form['ldap_user_fields']['#collapsed'] = FALSE;
  }
  $form['#validate'][] = 'ldap_user_form_register_form_validate';
  $form['#submit'][] = 'ldap_user_form_register_form_submit2';
}

/**
 *
 */
function ldap_user_form_register_form_validate($form, &$form_state) {
  $values = $form_state['values'];
  $user_ldap_entry = NULL;
  $drupal_username = $form_state['values']['name'];
  if ($values['ldap_user_association'] == LDAP_USER_MANUAL_ACCT_CONFLICT_NO_LDAP_ASSOCIATE) {
    $form_state['values']['ldap_user_ldap_exclude'][LANGUAGE_NONE][0]['value'] = 1;
  }

  // If corresponding ldap account doesn't exist and provision not selected and make ldap associated is selected, throw error.
  if (!@$values['ldap_user_create_ldap_acct'] && @$values['ldap_user_association'] == LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE) {
    $ldap_user_conf = ldap_user_conf();
    $ldap_user = ldap_servers_get_user_ldap_data($drupal_username, $ldap_user_conf->ldapEntryProvisionServer, 'ldap_user_prov_to_drupal');
    if (!$ldap_user) {
      form_set_error('ldap_user_association', t('User %name does not have a corresponding LDAP Entry (dn).
        Under LDAP options, you may NOT select "Make this an LDAP Associated Account"', [
        '%name' => $drupal_username,
      ]));
    }
  }

  // If trying to provision and ldap account and one already exists, throw error.
  if (@$values['ldap_user_create_ldap_acct']) {
    $ldap_user_conf = ldap_user_conf();
    $ldap_user = ldap_servers_get_user_ldap_data($drupal_username, $ldap_user_conf->ldapEntryProvisionServer, 'ldap_user_prov_to_ldap');
    if ($ldap_user) {
      $tokens = [
        '%dn' => $ldap_user['dn'],
        '%name' => $drupal_username,
      ];
      form_set_error('ldap_user_create_ldap_acct', t('User %name already has a corresponding LDAP Entry (%dn).
        Uncheck "Create corresponding LDAP entry" to allow this Drupal user to be created.  Select
        "Make this an LDAP associated account" to associate this account with the ldap entry.', $tokens));
    }
  }
}

/**
 * Called after user_register_form_submit .**/
function ldap_user_form_register_form_submit2($form, &$form_state) {
  $values = $form_state['values'];
  $ldap_user_association_set = FALSE;
  if (@$values['ldap_user_create_ldap_acct']) {
    if ($account = user_load_by_name($values['name'])) {
      $ldap_user_conf = ldap_user_conf();
      $ldap_provision_entry = $ldap_user_conf
        ->getProvisionRelatedLdapEntry($account);
      if (!$ldap_provision_entry) {
        $provision_result = $ldap_user_conf
          ->provisionLdapEntry($account);
      }
      else {
        $ldap_user_association_set = TRUE;
      }
    }
    else {

      // don't do anything here.  If account is not created, other user module warnings will exist.
    }
  }
  if ($ldap_user_association_set || @$values['ldap_user_association'] == LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE) {
    $ldap_user_conf = ldap_user_conf();
    $ldap_user_conf
      ->ldapAssociateDrupalAccount($form_state['values']['name']);
  }
}

/**
 * @param object $account
 *   as drupal user object.
 * @param array $edit
 *   is a drupal user edit array.
 * @param enum int $direction
 *   indicating which directions to test for association.
 *
 *
 * @return boolean TRUE if user should be excluded from ldap provision/synching
 */
function ldap_user_ldap_exclude($account = NULL, $edit = NULL, $direction = LDAP_USER_PROV_DIRECTION_ALL) {

  // Always exclude user 1.
  if (is_object($account) && isset($account->uid) && $account->uid == 1) {
    return TRUE;
  }

  // Exclude users who have the field ldap_user_ldap_exclude set to 1.
  if (is_object($account) && isset($account->ldap_user_ldap_exclude[LANGUAGE_NONE][0]['value']) && $account->ldap_user_ldap_exclude[LANGUAGE_NONE][0]['value'] == 1) {
    return TRUE;
  }

  // Exclude new users who have the value set to 1 in their $edit array.
  if (is_array($edit) && isset($edit['ldap_user_ldap_exclude'][LANGUAGE_NONE][0]['value']) && $edit['ldap_user_ldap_exclude'][LANGUAGE_NONE][0]['value'] == 1) {
    return TRUE;
  }

  // Everyone else is fine.
  return FALSE;
}

/**
 * @param object $account
 *   as drupal user object.
 * @param enum int $direction
 *   indicating which directions to test for association
 *   LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER signifies test if drupal account has been provisioned or synched from ldap
 *   LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY signifies test if ldap account has been provisioned or synched from drupal
 *   NULL signifies check for either direction.
 *
 * @return boolean if user is ldap associated
 */
function ldap_user_is_ldap_associated($account, $direction = NULL) {
  $to_drupal_user = FALSE;
  $to_ldap_entry = FALSE;
  if ($direction === NULL || $direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
    if (property_exists($account, 'ldap_user_current_dn') && !empty($account->ldap_user_current_dn[LANGUAGE_NONE][0]['value'])) {
      $to_drupal_user = TRUE;
    }
    elseif (isset($account->uid)) {
      $authname = ldap_user_get_authname($account);
      $to_drupal_user = (bool) $authname;
    }
  }
  if ($direction === NULL || $direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
    if (property_exists($account, 'ldap_user_prov_entries') && !empty($account->ldap_user_prov_entries[LANGUAGE_NONE][0]['value'])) {
      $to_ldap_entry = TRUE;
    }
  }
  if ($direction == LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER) {
    return $to_drupal_user;
  }
  elseif ($direction == LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY) {
    return $to_ldap_entry;
  }
  else {
    return $to_ldap_entry || $to_drupal_user;
  }
}

/**
 * Api function for synching
 * note: does no checking if synching is enabled or configured for a given context.
 */
function ldap_user_synch_to_drupal($username, $prov_event = LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER, $ldap_user = NULL) {
  $ldap_user_conf = ldap_user_conf();
  $account = user_load_by_name($username);
  $user_edit = [];
  $ldap_user_conf
    ->synchToDrupalAccount($account, $user_edit, $prov_event, $ldap_user, TRUE);
}

/**
 * Api function for ldap associated user provisioning
 * note: does no checking if synching is enabled or configured for a given context.
 */
function ldap_user_provision_to_drupal($ldap_user, $user_edit = []) {
  $sid = $ldap_user['sid'];
  $ldap_user_conf = ldap_user_conf();
  $account = NULL;
  $ldap_user_conf
    ->provisionDrupalAccount($account, $user_edit, $ldap_user, TRUE);
}

/**
 * Function to:
 *   -- store user entered password during pageload
 *   and protect unencrypted user password from other modules.
 *
 * @param enum string $action
 *   'get' | 'set'.
 * @param string | FALSE $value
 *   as user entered password.
 */
function ldap_user_ldap_provision_pwd($action, $value = NULL, $reset = FALSE) {
  static $current_user_pass;
  if ($reset) {
    $current_user_pass = NULL;
  }
  if ($action == 'set') {
    $current_user_pass = $value;
  }
  elseif ($action == 'get' && $current_user_pass) {
    return $current_user_pass;
  }
  else {
    return FALSE;
  }
}

/**
 * Function to avoid multiple synch or provision in same page load (if desired)
 *
 * @param enum string $action
 *   'synch' | 'provision' | 'set_page_load_key' | NULL.
 * @param enum string $op
 *   = 'set' or 'get'.
 *
 * @value mixed value associate with $op.
 *
 * @return bool|void
 */
function ldap_user_ldap_provision_semaphore($action, $op, $value = NULL, $reset = FALSE) {
  $calling_function = FALSE;

  // {.
  if (function_exists('debug_backtrace') && ($backtrace = debug_backtrace())) {
    $calling_function = $backtrace[1]['function'];
  }
  static $ldap_accts;
  static $intialized;
  if ($reset || !$intialized) {
    $ldap_accts = [];
    $intialized = TRUE;
  }

  // Mark that the given drupal user has had ldap entry synched or provisioned on this page load.
  if ($op == 'set') {
    if ($action && $value) {
      $ldap_accts[$action][$value] = TRUE;
    }
    return;
  }

  // Has the given drupal user x action (synch or provision) been executed.
  if ($op == 'get') {
    if ($action && $value && isset($ldap_accts[$action][$value])) {
      return $ldap_accts[$action][$value];
    }
    else {
      return FALSE;
    }
  }
}

/**
 * Implements hook_user_login().
 */
function ldap_user_user_login(&$edit, $account) {
  if (ldap_user_ldap_exclude($account, $edit)) {
    return;
  }
  $ldap_user_conf = ldap_user_conf();
  $user_edit = [];
  ldap_user_reset_provision_server($ldap_user_conf, $account);

  // Provision or synch to ldap, not both.
  $provision_result = [
    'status' => 'none',
  ];

  // Provision to ldap
  // Check for first time user.
  if ($ldap_user_conf->provisionsLdapEntriesFromDrupalUsers && ldap_user_ldap_provision_semaphore('provision', 'get', $account->name) === FALSE && !$ldap_user_conf
    ->getProvisionRelatedLdapEntry($account) && $ldap_user_conf->ldapEntryProvisionServer && $ldap_user_conf
    ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE)) {
    $provision_result = $ldap_user_conf
      ->provisionLdapEntry($account);
    if ($provision_result['status'] == 'success') {
      ldap_user_ldap_provision_semaphore('provision', 'set', $account->name);
    }
  }

  // don't synch if just provisioned.
  if ($ldap_user_conf->provisionsLdapEntriesFromDrupalUsers && ldap_user_ldap_provision_semaphore('synch', 'get', $account->name) === FALSE && $provision_result['status'] != 'success' && $ldap_user_conf
    ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE)) {
    $bool_result = $ldap_user_conf
      ->synchToLdapEntry($account, $user_edit);
    if ($bool_result) {
      ldap_user_ldap_provision_semaphore('synch', 'set', $account->name);
    }
  }
  $prov_enabled = $ldap_user_conf
    ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE);

  // Provision from LDAP if a new account was not just provisioned from LDAP.
  if (ldap_user_ldap_provision_semaphore('drupal_created', 'get', $account->name) === FALSE) {
    if ($ldap_user_conf->provisionsDrupalAccountsFromLdap && in_array(LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER, array_keys($ldap_user_conf->provisionsDrupalEvents))) {
      $ldap_user = ldap_servers_get_user_ldap_data($account->name, $ldap_user_conf->drupalAcctProvisionServer, 'ldap_user_prov_to_drupal');
      if ($ldap_user) {
        $ldap_server = ldap_servers_get_servers($ldap_user_conf->drupalAcctProvisionServer, NULL, TRUE);
        $ldap_user_conf
          ->entryToUserEdit($ldap_user, $user_edit, $ldap_server, LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, [
          LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER,
        ]);

        // See #1973352 and #935592.
        if (empty($account->picture->fid)) {
          $account2 = user_load($account->uid);
          $account->picture = $account2->picture;
        }
        $account = user_save($account, $user_edit, 'ldap_user');
      }
    }
  }
}

/**
 * Implements hook_user_insert().
 */
function ldap_user_user_insert(&$user_edit, $account, $category) {
  global $user;
  $not_associated = ldap_user_ldap_exclude($account, $user_edit);

  // Check for first time user.
  $new_account_request = (bool) ($user->uid == 0 && $account->access == 0 && $account->login == 0);
  $already_provisioned_to_ldap = ldap_user_ldap_provision_semaphore('provision', 'get', $account->name);
  $already_synched_to_ldap = ldap_user_ldap_provision_semaphore('synch', 'user_action_query', $account->name);
  if ($not_associated || $already_synched_to_ldap || $already_synched_to_ldap || $new_account_request) {
    return;
  }
  $ldap_user_conf = ldap_user_conf();

  /**
   * in hook_user_insert, account is already created, so never call provisionDrupalAccount(), just
   * synchToDrupalAccount(), even if action is 'provision'
   */
  $empty_user_edit = [];
  if ($account->status && $ldap_user_conf
    ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE)) {
    $ldap_user_conf
      ->synchToDrupalAccount($account, $empty_user_edit, LDAP_USER_EVENT_CREATE_DRUPAL_USER, NULL, TRUE);
  }
  if ($ldap_user_conf->provisionsLdapEntriesFromDrupalUsers) {
    $prov_enabled = $ldap_user_conf
      ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE);
    if ($prov_enabled) {
      $ldap_provision_entry = $ldap_user_conf
        ->getProvisionRelatedLdapEntry($account);
      if (!$ldap_provision_entry) {
        $provision_result = $ldap_user_conf
          ->provisionLdapEntry($account);
        if ($provision_result['status'] == 'success') {
          ldap_user_ldap_provision_semaphore('provision', 'set', $account->name);
        }
      }
      elseif ($ldap_provision_entry) {
        $bool_result = $ldap_user_conf
          ->synchToLdapEntry($account, $user_edit);
        if ($bool_result) {
          ldap_user_ldap_provision_semaphore('synch', 'set', $account->name);
        }
      }
    }
  }
}

/**
 * Implements hook_user_update()
 */
function ldap_user_user_update(&$user_edit, $account, $category) {
  if (ldap_user_ldap_exclude($account, $user_edit)) {
    return;
  }
  $ldap_user_conf = ldap_user_conf();

  // Check for provisioning to LDAP; this will normally occur on hook_user_insert or other event when drupal user is created.
  if ($ldap_user_conf->provisionsLdapEntriesFromDrupalUsers && $ldap_user_conf
    ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE)) {
    $already_provisioned_to_ldap = ldap_user_ldap_provision_semaphore('provision', 'get', $account->name);
    $already_synched_to_ldap = ldap_user_ldap_provision_semaphore('synch', 'get', $account->name);
    if ($already_provisioned_to_ldap || $already_synched_to_ldap) {
      return;
    }
    $provision_result = [
      'status' => 'none',
    ];

    // Always check if provisioning to ldap has already occurred this page load.
    $ldap_entry = $ldap_user_conf
      ->getProvisionRelatedLdapEntry($account);

    // {.
    if (!$ldap_entry) {
      $provision_result = $ldap_user_conf
        ->provisionLdapEntry($account);
      if ($provision_result['status'] == 'success') {
        ldap_user_ldap_provision_semaphore('provision', 'set', $account->name);
      }
    }

    // Synch if not just provisioned and enabled.
    if ($provision_result['status'] != 'success') {

      // Always check if provisioing to ldap has already occurred this page load.
      $provision_enabled = $ldap_user_conf
        ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE);
      $ldap_entry = $ldap_user_conf
        ->getProvisionRelatedLdapEntry($account);
      if ($provision_enabled && $ldap_entry) {
        $bool_result = $ldap_user_conf
          ->synchToLdapEntry($account, $user_edit);
        if ($bool_result) {
          ldap_user_ldap_provision_semaphore('synch', 'set', $account->name);
        }
      }
    }
  }
}

/**
 * Implements hook_user_presave()
 */
function ldap_user_user_presave(&$user_edit, $account, $category) {
  if (ldap_user_ldap_exclude($account, $user_edit)) {
    return;
  }
  if (isset($account->name)) {
    $drupal_username = $account->name;
  }
  elseif (!empty($user_edit['name'])) {
    $drupal_username = $user_edit['name'];
  }
  else {
    return;
  }
  $ldap_user_conf = ldap_user_conf();
  ldap_user_reset_provision_server($ldap_user_conf, $account);

  // Check for provisioning to drupal and override synched user fields/props
  // Provision from LDAP if a new account was not just provisioned from LDAP.
  if (ldap_user_ldap_provision_semaphore('drupal_created', 'get', $drupal_username) === FALSE) {
    if ($ldap_user_conf->provisionsDrupalAccountsFromLdap && in_array(LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER, array_keys($ldap_user_conf->provisionsDrupalEvents))) {
      if ($ldap_user_conf
        ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE)) {
        if (ldap_user_is_ldap_associated($account, LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER)) {
          $ldap_user = ldap_servers_get_user_ldap_data($drupal_username, $ldap_user_conf->drupalAcctProvisionServer, 'ldap_user_prov_to_drupal');
          if ($ldap_user) {
            $ldap_server = ldap_servers_get_servers($ldap_user_conf->drupalAcctProvisionServer, NULL, TRUE);
            $ldap_user_conf
              ->entryToUserEdit($ldap_user, $user_edit, $ldap_server, LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER, [
              LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER,
            ]);
          }
        }
      }
    }
  }
}

/**
 * Implements hook_user_delete().
 */
function ldap_user_user_delete($account) {

  // Drupal user account is about to be deleted.
  $ldap_user_conf = ldap_user_conf();
  if ($ldap_user_conf->provisionsLdapEntriesFromDrupalUsers && $ldap_user_conf
    ->provisionEnabled(LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY, LDAP_USER_LDAP_ENTRY_DELETE_ON_USER_DELETE)) {
    $boolean_result = $ldap_user_conf
      ->deleteProvisionedLdapEntries($account);

    // No need to watchdog here, because fail in deleteProvisionedLdapEntries provides watchdog entry.
  }
}

/**
 * Implements hook_field_widget_info().
 * to provide field type for LDAP fields.
 */
function ldap_user_field_widget_info() {
  return [
    'ldap_user_hidden' => [
      'label' => t('Hidden Text Field'),
      'field types' => [
        'text',
      ],
      'settings' => [],
    ],
  ];
}

/**
 * Implements hook_field_widget_settings_form().
 */
function ldap_user_field_widget_settings_form($field, $instance) {
  return [];
}

/**
 * Implements hook_field_widget_form().
 */
function ldap_user_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $main_widget = [];
  switch ($instance['widget']['type']) {
    case 'ldap_user_hidden':
      $element['value'] = $element + [
        '#type' => 'value',
        '#value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
        '#attached' => [
          'css' => [
            drupal_get_path('module', 'ldap_user') . '/ldap_user.css',
          ],
        ],
      ];
      break;
  }
  return $element;
}

/**
 *
 */
function ldap_user_synch_triggers_key_values() {
  return [
    LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE => t('On synch to Drupal user create or update. Requires a server with binding method of "Service Account Bind" or "Anonymous Bind".'),
    LDAP_USER_DRUPAL_USER_PROV_ON_AUTHENTICATE => t('On create or synch to Drupal user when successfully authenticated with LDAP credentials. (Requires LDAP Authentication module).'),
    LDAP_USER_DRUPAL_USER_PROV_ON_ALLOW_MANUAL_CREATE => t('On manual creation of Drupal user from admin/people/create and "Create corresponding LDAP entry" is checked'),
    LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE => t('On creation or synch of an LDAP entry when a Drupal account is created or updated. Only applied to accounts with a status of approved.'),
    LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE => t('On creation or synch of an LDAP entry when a user authenticates.'),
    LDAP_USER_LDAP_ENTRY_DELETE_ON_USER_DELETE => t('On deletion of an LDAP entry when the corresponding Drupal Account is deleted.  This only applies when the LDAP entry was provisioned by Drupal by the LDAP User module.'),
  ];
}

/**
 *
 */
function ldap_user_all_events() {
  return [
    LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER,
    LDAP_USER_EVENT_CREATE_DRUPAL_USER,
    LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY,
    LDAP_USER_EVENT_CREATE_LDAP_ENTRY,
    LDAP_USER_EVENT_LDAP_ASSOCIATE_DRUPAL_ACCT,
  ];
}

/**
 * @param array $account
 * @param string $text
 * @return string text with tokens replaced
 */
function ldap_user_token_replace($token, $account, $entity = NULL) {
  $desired_tokens = ldap_servers_token_tokens_needed_for_template($token);
  $tokens = ldap_user_token_tokenize_entry($account, $desired_tokens, LDAP_SERVERS_TOKEN_PRE, LDAP_SERVERS_TOKEN_POST, $entity);
  $result = str_replace(array_keys($tokens), array_values($tokens), $token);
  return $result;
}

/**
 * Turn an ldap entry into a token array suitable for the t() function.
 *
 * @param drupal user object $account
 * @param array $token_keys
 *   as list of token/value pairs to generate.
 * @param string prefix token prefix such as !,%,[
 * @param string suffix token suffix such as ]
 *
 * @return token array suitable for t() functions of with lowercase keys as exemplified below
 */
function ldap_user_token_tokenize_entry($account, $token_keys, $pre = LDAP_SERVERS_TOKEN_PRE, $post = LDAP_SERVERS_TOKEN_POST, $user_entity = NULL) {
  $detailed_watchdog_log = variable_get('ldap_help_watchdog_detail', 0);
  $tokens = [];
  if (!$user_entity) {
    list($discard, $user_entity) = ldap_user_load_user_acct_and_entity($account->uid, 'uid');
  }
  foreach ($token_keys as $token_key) {

    // Target id is of form field.lname, property.mail, field.dept:0, etc.
    list($type, $attr_ordinal) = explode('.', $token_key);
    $parts = explode(':', $attr_ordinal);
    $attr = $parts[0];
    $ordinal = count($parts) > 1 ? $parts[1] : 0;
    $token = $pre . $token_key . $post;
    switch ($type) {
      case 'field':
        if (isset($user_entity->{$attr}[LANGUAGE_NONE][$ordinal]['value'])) {
          $tokens[$token] = $user_entity->{$attr}[LANGUAGE_NONE][$ordinal]['value'];
        }
        break;
      case 'property':
        if (property_exists($account, $attr)) {
          $tokens[$token] = $account->{$attr};
        }
        break;
    }
  }
  return $tokens;
}

/**
 * Load user $account and $entity, given uid or $username.
 *
 * @param string $user_id
 *   is username or uid.
 * @param enum $user_id_type
 *   is 'username' or 'uid'
 *
 *   return array $account and $user_entity.
 */
function ldap_user_load_user_acct_and_entity($user_id, $user_id_type = 'username') {
  if ($user_id_type == 'username') {
    $account = user_load_by_name($user_id);
  }
  else {
    $account = user_load($user_id);
  }
  if ($account) {
    $user_entities = entity_load('user', [
      $account->uid,
    ]);
    $user_entity = $user_entities[$account->uid];
  }
  else {
    $user_entity = NULL;
  }
  return [
    $account,
    $user_entity,
  ];
}

/**
 * Implements hook_ldap_servers_username_to_ldapname_alter
 * - Set ldap name to auth name.
 */
function ldap_user_ldap_servers_username_to_ldapname_alter(&$ldap_username, $drupal_username, $context) {

  // Alter the name only if it has not been altered already, ie php eval code.
  if ($ldap_username == $drupal_username) {
    $authname = ldap_user_get_authname($ldap_username);
    if (!empty($authname)) {
      $ldap_username = $authname;
    }
  }
}

/**
 * Returns LDAP authname from the authmap table for a variant input.
 *
 * @param $data
 *   A variant input. Allowed variable types:
 *   - object: user account object
 *   - string: username
 *
 * @return string|null
 *   Returns the LDAP authname of the passed Drupal user.
 */
function ldap_user_get_authname($data) {
  $cache =& drupal_static(__FUNCTION__, []);
  $authname = NULL;
  $uid = NULL;
  if (is_object($data)) {

    // Object - set uid if object has uid and uid > 0.
    if (!empty($data->uid)) {
      $uid = $data->uid;
    }
  }
  else {

    // String - load account and set uid if uid > 0.
    $account = user_load_by_name($data);
    if (!empty($account->uid)) {
      $uid = $account->uid;
    }
  }

  // Exit if no uid found.
  if (empty($uid)) {
    return NULL;
  }

  // Run query if uid is not statically cached.
  if (!array_key_exists($uid, $cache)) {
    $authname = db_query('SELECT authname FROM {authmap} WHERE uid = :uid AND module = :module', [
      ':uid' => $uid,
      ':module' => 'ldap_user',
    ])
      ->fetchField();
    $cache[$uid] = !empty($authname) ? $authname : NULL;
  }
  return $cache[$uid];
}

/**
 * Resets the drupalAcctProvisionServer if needed.
 *
 * Used when handling multi-domain authentication to set the provisioning
 * server to be the server that last successfully authenticated the user.
 *
 * @param LdapUserConf $ldap_user_conf
 *   The LDAP User Configuration object.
 *
 * @param object $account
 *   The Drupal user account.
 */
function ldap_user_reset_provision_server($ldap_user_conf, $account) {

  // Reset the Provision Server sid to the server that last authenticated the user.
  if ($ldap_user_conf->drupalAcctProvisionServer == LDAP_USER_AUTH_SERVER_SID) {
    $sid = FALSE;
    if (isset($account->data['ldap_user']['init']['sid'])) {
      $sid = $account->data['ldap_user']['init']['sid'];
    }
    else {

      // Provisioning Server sid is not in the account object,
      // see if we have a session variable with it.
      $sid = isset($_SESSION[LDAP_USER_SESSION_PROV_SID]) ? $_SESSION[LDAP_USER_SESSION_PROV_SID] : FALSE;
    }
    if ($sid) {
      $ldap_user_conf->drupalAcctProvisionServer = $sid;
    }
  }
}

Functions

Namesort descending Description
ldap_user_all_events
ldap_user_conf Get ldapUserConf or ldapUserConfAdmin object.
ldap_user_conf_cache_clear
ldap_user_cron Implements hook_cron().
ldap_user_field_widget_form Implements hook_field_widget_form().
ldap_user_field_widget_info Implements hook_field_widget_info(). to provide field type for LDAP fields.
ldap_user_field_widget_settings_form Implements hook_field_widget_settings_form().
ldap_user_form_password_policy_password_tab_alter Implements hook_form_FORM_ID_alter(). for password_policy_password_tab.
ldap_user_form_register_form_submit2 Called after user_register_form_submit .*
ldap_user_form_register_form_validate
ldap_user_form_user_login_alter Implements hook_form_FORM_ID_alter(). for user_login_form.
ldap_user_form_user_login_block_alter Implements hook_form_FORM_ID_alter(). for user_login_block.
ldap_user_form_user_pass_reset_alter Implements hook_form_FORM_ID_alter(). for user-pass-reset form. Useful for sites where this is the form ID for a user to intially set their password (user clicks an emailed registration link, is prompted to set their password).
ldap_user_form_user_profile_form_alter Implements hook_form_FORM_ID_alter(). for user_register_form.
ldap_user_form_user_register_form_alter Implements hook_form_FORM_ID_alter(). for user_register_form.
ldap_user_get_authname Returns LDAP authname from the authmap table for a variant input.
ldap_user_grab_password_validate Store password from logon forms in ldap_user_ldap_provision_pwd static variable for use in provisioning to ldap.
ldap_user_help Implements hook_help().
ldap_user_init Implements hook_init().
ldap_user_is_ldap_associated
ldap_user_ldap_attributes_needed_alter Implements hook_ldap_attributes_needed_alter().
ldap_user_ldap_derived_user_name_alter Implements hook_ldap_derived_user_name_alter().
ldap_user_ldap_exclude
ldap_user_ldap_provision_pwd Function to: -- store user entered password during pageload and protect unencrypted user password from other modules.
ldap_user_ldap_provision_semaphore Function to avoid multiple synch or provision in same page load (if desired)
ldap_user_ldap_servers_username_to_ldapname_alter Implements hook_ldap_servers_username_to_ldapname_alter
ldap_user_ldap_user_attrs_list_alter Implements hook_ldap_user_attrs_list_alter().
ldap_user_load_user_acct_and_entity Load user $account and $entity, given uid or $username.
ldap_user_mail Implements hook_mail().
ldap_user_menu Implements hook_menu().
ldap_user_provision_to_drupal Api function for ldap associated user provisioning note: does no checking if synching is enabled or configured for a given context.
ldap_user_reset_provision_server Resets the drupalAcctProvisionServer if needed.
ldap_user_synch_to_drupal Api function for synching note: does no checking if synching is enabled or configured for a given context.
ldap_user_synch_triggers_key_values
ldap_user_theme Implements hook_theme().
ldap_user_token_replace
ldap_user_token_tokenize_entry Turn an ldap entry into a token array suitable for the t() function.
ldap_user_user_delete Implements hook_user_delete().
ldap_user_user_insert Implements hook_user_insert().
ldap_user_user_login Implements hook_user_login().
ldap_user_user_presave Implements hook_user_presave()
ldap_user_user_update Implements hook_user_update()

Constants

Namesort descending Description
LDAP_USER_ACCOUNTS_WITH_SAME_EMAIL_DISABLED
LDAP_USER_ACCOUNTS_WITH_SAME_EMAIL_ENABLED
LDAP_USER_ACCT_CREATION_LDAP_BEHAVIOR
LDAP_USER_ACCT_CREATION_LDAP_BEHAVIOR_DEFAULT
LDAP_USER_ACCT_CREATION_USER_SETTINGS_FOR_LDAP
LDAP_USER_AUTH_SERVER_SID
LDAP_USER_CONFLICT_LOG
LDAP_USER_CONFLICT_RESOLVE
LDAP_USER_CONFLICT_RESOLVE_DEFAULT
LDAP_USER_DRUPAL_HELP_URL @file Module for the LDAP User Entity.
LDAP_USER_DRUPAL_USER_PROV_ON_ALLOW_MANUAL_CREATE
LDAP_USER_DRUPAL_USER_PROV_ON_AUTHENTICATE
LDAP_USER_DRUPAL_USER_PROV_ON_USER_UPDATE_CREATE
LDAP_USER_EVENT_CREATE_DRUPAL_USER
LDAP_USER_EVENT_CREATE_LDAP_ENTRY
LDAP_USER_EVENT_LDAP_ASSOCIATE_DRUPAL_ACCT
LDAP_USER_EVENT_SYNCH_TO_DRUPAL_USER
LDAP_USER_EVENT_SYNCH_TO_LDAP_ENTRY
LDAP_USER_LDAP_ENTRY_DELETE_ON_USER_DELETE
LDAP_USER_LDAP_ENTRY_PROV_ON_AUTHENTICATE
LDAP_USER_LDAP_ENTRY_PROV_ON_USER_UPDATE_CREATE
LDAP_USER_MANUAL_ACCT_CONFLICT_LDAP_ASSOCIATE
LDAP_USER_MANUAL_ACCT_CONFLICT_NO_LDAP_ASSOCIATE
LDAP_USER_MANUAL_ACCT_CONFLICT_REJECT
LDAP_USER_MANUAL_ACCT_CONFLICT_SHOW_OPTION_ON_FORM
LDAP_USER_NO_SERVER_SID
LDAP_USER_PROVISION_LDAP_ENTRY_CREATE_FAILED
LDAP_USER_PROVISION_LDAP_ENTRY_EXISTS
LDAP_USER_PROVISION_LDAP_ENTRY_SYNCH_FAILED
LDAP_USER_PROV_DIRECTION_ALL
LDAP_USER_PROV_DIRECTION_NONE
LDAP_USER_PROV_DIRECTION_TO_DRUPAL_USER
LDAP_USER_PROV_DIRECTION_TO_LDAP_ENTRY
LDAP_USER_PROV_RESULT_BAD_PARAMS
LDAP_USER_PROV_RESULT_NO_ERROR
LDAP_USER_PROV_RESULT_NO_PWD
LDAP_USER_SESSION_PROV_SID
LDAP_USER_TEST_FORM_PATH
LDAP_USER_WS_USER_PATH