You are here

cas_attributes.module in CAS Attributes 6.3

Same filename and directory in other branches
  1. 7 cas_attributes.module

Allows user account and profile attributes to be automatically populated using tokens. Provides basic tokens for attributes returned by the CAS server.

File

cas_attributes.module
View source
<?php

/**
 * @file
 * Allows user account and profile attributes to be automatically populated
 * using tokens. Provides basic tokens for attributes returned by the CAS
 * server.
 */

/**
 * Implements hook_menu().
 */
function cas_attributes_menu() {
  $items = array();
  $items['admin/user/cas/attributes'] = array(
    'title' => 'Attributes',
    'description' => 'Manage the relationships between CAS attributes and user fields.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'cas_attributes_admin_settings',
    ),
    'access arguments' => array(
      'administer cas',
    ),
    'file' => 'cas_attributes.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => -8,
  );
  $items['admin/user/cas/attributes/cas'] = array(
    'title' => 'CAS Attribute Tokens',
    'description' => 'Get a list of all available CAS Attributes',
    'page callback' => 'cas_attributes_list',
    'access arguments' => array(
      'administer cas',
    ),
    'file' => 'cas_attributes.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => -8,
  );
  return $items;
}

/**
 * Implements hook_token_list().
 */
function cas_attributes_token_list($type = 'all') {
  module_load_include('tokens.inc', 'cas_attributes');
  return _cas_attributes_token_list($type);
}

/**
 * Implements hook_token_values().
 */
function cas_attributes_token_values($type, $object = NULL) {
  module_load_include('tokens.inc', 'cas_attributes');
  return _cas_attributes_token_values($type, $object);
}

/**
 * Implements hook_cas_user_presave().
 */
function cas_attributes_cas_user_presave(&$edit, $account) {
  $cas_attributes = variable_get('cas_attributes', array());
  $cas_attributes += array(
    'sync_every_login' => NULL,
    'relations' => array(
      'mail' => NULL,
      'name' => NULL,
    ),
    'roles' => array(
      'manage' => array(),
      'mapping' => '',
    ),
  );

  // We synchronize on the first login (always) and on future logins (if chosen).
  if ($account->login && !$cas_attributes['sync_every_login']) {

    // The user has logged in before and we are not set to always synchronize.
    return;
  }
  $data = array(
    'cas' => $edit['cas_user']['name'],
  );
  $profile_fields = _cas_attributes_get_profile_fields();

  // Set each drupal field to its mapped attribute.
  foreach ($cas_attributes['relations'] as $drupal_field => $text) {
    $result = trim(token_replace_multiple($text, $data, TOKEN_PREFIX, TOKEN_SUFFIX, array(
      'clear' => TRUE,
    )));
    $result = html_entity_decode($result);

    // Only update the fields if there is data to set.
    if (!empty($result)) {

      // Is it a profile field? We unfortunately cannot just set this in edit, as
      // profile is braindead.
      if (is_numeric($drupal_field)) {
        if (isset($profile_fields[$drupal_field]) && ($instance = $profile_fields[$drupal_field])) {
          $value = $result;
          if (_profile_field_serialize($instance->type)) {
            $value = serialize($value);
          }
          if ($row = db_fetch_array(db_query("SELECT value FROM {profile_values} WHERE fid = '%d' AND uid = '%d'", $drupal_field, $account->uid))) {
            if ($row['value'] != $value) {
              db_query("UPDATE {profile_values} SET value = '%s' WHERE fid = '%d' AND uid = '%d'", $value, $drupal_field, $account->uid);
            }
          }
          else {
            db_query("INSERT INTO {profile_values} (value, fid, uid) VALUES ('%s', '%d', '%d')", $value, $drupal_field, $account->uid);
          }
        }
      }
      else {

        // It is a Drupal field like 'mail' or 'name'.
        $edit[$drupal_field] = $result;
      }
    }
  }

  // Content Profile compatibility.
  if (module_exists('content_profile')) {
    foreach ($cas_attributes['content_profile'] as $type_name => $fields) {

      // Content profile works by allowing each use to create exactly one node
      // of type 'profile'. If the user already has their node, we use that.
      // Otherwise we prepare an empty $node object to be populated.
      $node = content_profile_load($type_name, $account->uid);
      if (!$node) {
        $node = (object) array(
          'type' => $type_name,
          'uid' => $account->uid,
        );
      }
      foreach ($fields as $field_name => $text) {
        $result = trim(token_replace_multiple($text, $data, TOKEN_PREFIX, TOKEN_SUFFIX, array(
          'clear' => TRUE,
        )));
        if (!empty($result)) {
          if (!isset($node->{$field_name})) {
            $node->{$field_name} = array(
              0 => array(
                'value' => NULL,
              ),
            );
          }
          $node->{$field_name}[0]['value'] = $result;
        }
      }
      node_save($node);
    }
  }

  // Manage Roles
  // Make sure there are attributes to check.
  if (!empty($cas_attributes['roles']['mapping'])) {

    // Get the users attributes.
    $user_attributes = cas_phpcas_attributes($data['cas']);

    // Allow other modules to manipulate the attribute values.
    // Can't use module_invoke_all() because we need to pass byref.
    $arguments = array(
      &$user_attributes,
    );
    foreach (module_implements('cas_attributes_roles_modify') as $module) {
      $function = $module . '_cas_attributes_roles_modify';
      call_user_func_array($function, $arguments);
    }

    // Build all the attirbutes to check.
    $cas_user_roles = array();
    $attributes_to_check = explode("\n", $cas_attributes['roles']['mapping']);
    foreach ($attributes_to_check as $attribute) {
      if (!empty($user_attributes[$attribute])) {
        if (is_array($user_attributes[$attribute])) {
          $cas_user_roles = array_merge($cas_user_roles, $user_attributes[$attribute]);
        }
        else {
          $cas_user_roles[] = $user_attributes[$attribute];
        }
      }
    }

    // Loop through all the managed roles and see if the user has access to them
    // and set accordingly.
    $roles = user_roles();
    foreach ($cas_attributes['roles']['manage'] as $rid) {
      if (!empty($rid)) {
        if (in_array($roles[$rid], $cas_user_roles)) {
          $edit['roles'][$rid] = $roles[$rid];
        }
        else {
          unset($edit['roles'][$rid]);
        }
      }
    }
  }
}

/**
 * Retrieve profile fields.
 */
function _cas_attributes_get_profile_fields() {
  $fields = array();
  if (module_exists('profile')) {
    $result = db_query("SELECT fid, name, title, type FROM {profile_fields}");
    while ($row = db_fetch_object($result)) {
      $fields[$row->fid] = $row;
    }
  }
  return $fields;
}