You are here

class SyncMappingHelper in Lightweight Directory Access Protocol (LDAP) 8.3

Helper class to process user field synchronisation mappings.

Hierarchy

Expanded class hierarchy of SyncMappingHelper

3 files declare their use of SyncMappingHelper
DrupalUserProcessor.php in ldap_user/src/Processor/DrupalUserProcessor.php
LdapUserAdminForm.php in ldap_user/src/Form/LdapUserAdminForm.php
LdapUserProcessor.php in ldap_user/src/Processor/LdapUserProcessor.php

File

ldap_user/src/Helper/SyncMappingHelper.php, line 12

Namespace

Drupal\ldap_user\Helper
View source
class SyncMappingHelper implements LdapUserAttributesInterface {

  /**
   * Sync mappings.
   *
   * @var array
   *  Array of field sync mappings provided by all modules.
   *
   * Via hook_ldap_user_attrs_list_alter(). Array has the form of [
   * LdapConfiguration:: | s => [
   *   <server_id> => array(
   *   'sid' => <server_id> (redundant)
   *   'ldap_attr' => e.g. [sn]
   *   'user_attr'  => e.g. [field.field_user_lname]
   *     (when this value is set to 'user_tokens', 'user_tokens' value is used.)
   *   'user_tokens' => e.g. [field.field_user_lname], [field.field_user_fname]
   *   'convert' => 1|0 boolean indicating need to covert from binary
   *   'direction' => LdapUserAttributesInterface::PROVISION_TO_DRUPAL ||
   *     LdapUserAttributesInterface::PROVISION_TO_LDAP (redundant)
   *   'config_module' => 'ldap_user'
   *   'prov_module' => 'ldap_user'
   *   'enabled' => 1|0 boolean
   *   prov_events' => [( see events above )]
   *  ]
   *
   * Array of field syncing directions for each operation. Should include
   * ldapUserSyncMappings. Keyed on direction => property, ldap, or field token
   * such as '[field.field_lname] with brackets in them.
   */
  private $syncMapping;
  private $config;

  /**
   * Constructor.
   */
  public function __construct() {
    $this->config = \Drupal::config('ldap_user.settings');
    $this
      ->loadSyncMappings();
  }

  /**
   * Given configuration of syncing, determine is a given sync should occur.
   *
   * @param string $attr_token
   *   Attribute token such as [property.mail], or
   *   [field.ldap_user_puid_property].
   * @param array $prov_events
   *   Provisioning events such as
   *   LdapUserAttributesInterface::EVENT_CREATE_DRUPAL_USER.
   *   Typically an array with one element.
   * @param int $direction
   *   Either LdapConfiguration::PROVISION_TO_DRUPAL or
   *   LdapConfiguration::PROVISION_TO_LDAP.
   *
   * @return bool
   *   If sync should occur.
   */
  public function isSynced($attr_token, array $prov_events, $direction) {
    $result = (bool) (isset($this->syncMapping[$direction][$attr_token]['prov_events']) && count(array_intersect($prov_events, $this->syncMapping[$direction][$attr_token]['prov_events'])));
    return $result;
  }

  /**
   * Util to fetch mappings for a given direction.
   *
   * @param string $direction
   *   Direction to sync in.
   * @param array $prov_events
   *   Events to act upon.
   *
   * @return array|bool
   *   Array of mappings (may be empty array)
   */
  public function getSyncMappings($direction = NULL, array $prov_events = NULL) {
    if (!$prov_events) {
      $prov_events = LdapConfiguration::getAllEvents();
    }
    if ($direction == NULL) {
      $direction = self::PROVISION_TO_ALL;
    }
    $mappings = [];
    if ($direction == self::PROVISION_TO_ALL) {
      $directions = [
        self::PROVISION_TO_DRUPAL,
        self::PROVISION_TO_LDAP,
      ];
    }
    else {
      $directions = [
        $direction,
      ];
    }

    // TODO: Note that we again query the DB, getSyncMappings() goes around the
    // general implementation and could be its own class.
    foreach ($directions as $direction) {
      if (!empty($this->config
        ->get('ldapUserSyncMappings')[$direction])) {
        foreach ($this->config
          ->get('ldapUserSyncMappings')[$direction] as $mapping) {
          if (!empty($mapping['prov_events'])) {
            $result = count(array_intersect($prov_events, $mapping['prov_events']));
            if ($result) {
              if ($direction == self::PROVISION_TO_DRUPAL && isset($mapping['user_attr'])) {
                $key = $mapping['user_attr'];
              }
              elseif ($direction == self::PROVISION_TO_LDAP && isset($mapping['ldap_attr'])) {
                $key = $mapping['ldap_attr'];
              }
              else {
                continue;
              }
              $mappings[$key] = $mapping;
            }
          }
        }
      }
    }
    return $mappings;
  }

  /**
   * Returns all available mappings.
   *
   * @TODO: Try to remove this, parsing of arrays as in LdapUserAdminForm is
   * not ideal.
   *
   * @return array
   *   All sync mappings.
   */
  public function getAllSyncMappings() {
    return $this->syncMapping;
  }

  /**
   * Setter function to ease testing.
   *
   * @param array $mappings
   *   Set all mappings.
   */
  private function setAllSyncMappings(array $mappings) {
    $this->syncMapping = $mappings;
  }

  /**
   * Fetches the sync mappings from cache or loads them from configuration.
   */
  public function loadSyncMappings() {
    $syncMappingsCache = \Drupal::cache()
      ->get('ldap_user_sync_mapping');
    if ($syncMappingsCache) {
      $this->syncMapping = $syncMappingsCache->data;
    }
    else {
      $this
        ->processSyncMappings();
      \Drupal::cache()
        ->set('ldap_user_sync_mapping', $this->syncMapping);
    }
  }

  /**
   * Derive synchronization mappings from configuration.
   *
   * This function would be private if not for easier access for tests.
   *
   * return array
   */
  private function processSyncMappings() {
    $available_user_attributes = [];
    foreach ([
      self::PROVISION_TO_DRUPAL,
      self::PROVISION_TO_LDAP,
    ] as $direction) {
      if ($direction == self::PROVISION_TO_DRUPAL) {
        $sid = $this->config
          ->get('drupalAcctProvisionServer');
      }
      else {
        $sid = $this->config
          ->get('ldapEntryProvisionServer');
      }
      $available_user_attributes[$direction] = [];
      $ldap_server = FALSE;
      if ($sid) {
        try {
          $ldap_server = Server::load($sid);
        } catch (\Exception $e) {
          \Drupal::logger('ldap_user')
            ->error('Missing server');
        }
      }
      $params = [
        'ldap_server' => $ldap_server,
        'direction' => $direction,
      ];

      // This function does not add any attributes by itself but allows modules
      // such as ldap_user to inject them through this hook.
      \Drupal::moduleHandler()
        ->alter('ldap_user_attrs_list', $available_user_attributes[$direction], $params);
    }
    $this
      ->setAllSyncMappings($available_user_attributes);
  }

  /**
   * Util to fetch attributes required for this user conf, not other modules.
   *
   * @param int $direction
   *   LDAP_USER_PROV_DIRECTION_* constants.
   * @param string $ldap_context
   *   LDAP context.
   *
   * @return array
   *   Required attributes.
   */
  public function getLdapUserRequiredAttributes($direction = NULL, $ldap_context = NULL) {
    if ($direction == NULL) {
      $direction = self::PROVISION_TO_ALL;
    }
    $required_attributes = [];
    if ($this->config
      ->get('drupalAcctProvisionServer')) {
      $prov_events = $this
        ->ldapContextToProvEvents($ldap_context);
      $attributes_map = $this
        ->getSyncMappings($direction, $prov_events);
      $required_attributes = [];
      foreach ($attributes_map as $detail) {
        if (count(array_intersect($prov_events, $detail['prov_events']))) {

          // Add the attribute to our array.
          if ($detail['ldap_attr']) {
            ConversionHelper::extractTokenAttributes($required_attributes, $detail['ldap_attr']);
          }
        }
      }
    }
    return $required_attributes;
  }

  /**
   * Convert context for ldap_user event.
   *
   * Converts the more general ldap_context string to its associated LDAP user
   * event.
   *
   * @param string|null $ldapContext
   *   Context.
   *
   * @return array
   *   List of events.
   */
  public static function ldapContextToProvEvents($ldapContext = NULL) {
    switch ($ldapContext) {
      case 'ldap_user_prov_to_drupal':
        $result = [
          self::EVENT_SYNC_TO_DRUPAL_USER,
          self::EVENT_CREATE_DRUPAL_USER,
          self::EVENT_LDAP_ASSOCIATE_DRUPAL_USER,
        ];
        break;
      case 'ldap_user_prov_to_ldap':
        $result = [
          self::EVENT_SYNC_TO_LDAP_ENTRY,
          self::EVENT_CREATE_LDAP_ENTRY,
        ];
        break;
      default:
        $result = LdapConfiguration::getAllEvents();
        break;
    }
    return $result;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
LdapUserAttributesInterface::ACCOUNT_CREATION_LDAP_BEHAVIOUR constant
LdapUserAttributesInterface::ACCOUNT_CREATION_USER_SETTINGS_FOR_LDAP constant
LdapUserAttributesInterface::EVENT_CREATE_DRUPAL_USER constant
LdapUserAttributesInterface::EVENT_CREATE_LDAP_ENTRY constant
LdapUserAttributesInterface::EVENT_LDAP_ASSOCIATE_DRUPAL_USER constant
LdapUserAttributesInterface::EVENT_SYNC_TO_DRUPAL_USER constant
LdapUserAttributesInterface::EVENT_SYNC_TO_LDAP_ENTRY constant
LdapUserAttributesInterface::MANUAL_ACCOUNT_CONFLICT_LDAP_ASSOCIATE constant
LdapUserAttributesInterface::MANUAL_ACCOUNT_CONFLICT_NO_LDAP_ASSOCIATE constant
LdapUserAttributesInterface::MANUAL_ACCOUNT_CONFLICT_REJECT constant
LdapUserAttributesInterface::MANUAL_ACCOUNT_CONFLICT_SHOW_OPTION_ON_FORM constant
LdapUserAttributesInterface::PROVISION_DRUPAL_USER_ON_USER_AUTHENTICATION constant
LdapUserAttributesInterface::PROVISION_DRUPAL_USER_ON_USER_ON_MANUAL_CREATION constant
LdapUserAttributesInterface::PROVISION_DRUPAL_USER_ON_USER_UPDATE_CREATE constant
LdapUserAttributesInterface::PROVISION_LDAP_ENTRY_ON_USER_ON_USER_AUTHENTICATION constant
LdapUserAttributesInterface::PROVISION_LDAP_ENTRY_ON_USER_ON_USER_DELETE constant
LdapUserAttributesInterface::PROVISION_LDAP_ENTRY_ON_USER_ON_USER_UPDATE_CREATE constant
LdapUserAttributesInterface::PROVISION_TO_ALL constant
LdapUserAttributesInterface::PROVISION_TO_DRUPAL constant
LdapUserAttributesInterface::PROVISION_TO_LDAP constant
LdapUserAttributesInterface::PROVISION_TO_NONE constant
LdapUserAttributesInterface::USER_CONFLICT_ATTEMPT_RESOLVE constant
LdapUserAttributesInterface::USER_CONFLICT_LOG constant
SyncMappingHelper::$config private property
SyncMappingHelper::$syncMapping private property Sync mappings.
SyncMappingHelper::getAllSyncMappings public function Returns all available mappings.
SyncMappingHelper::getLdapUserRequiredAttributes public function Util to fetch attributes required for this user conf, not other modules.
SyncMappingHelper::getSyncMappings public function Util to fetch mappings for a given direction.
SyncMappingHelper::isSynced public function Given configuration of syncing, determine is a given sync should occur.
SyncMappingHelper::ldapContextToProvEvents public static function Convert context for ldap_user event.
SyncMappingHelper::loadSyncMappings public function Fetches the sync mappings from cache or loads them from configuration.
SyncMappingHelper::processSyncMappings private function Derive synchronization mappings from configuration.
SyncMappingHelper::setAllSyncMappings private function Setter function to ease testing.
SyncMappingHelper::__construct public function Constructor.