You are here

party_user.module in Party 8.2

Same filename and directory in other branches
  1. 7 modules/party_user/party_user.module

Support for linking users to parties

File

modules/party_user/party_user.module
View source
<?php

/**
 * @file
 * Support for linking users to parties
 */

/**
 * Implements hook_party_data_set_info()
 */
function party_user_party_data_set_info() {
  $sets['user'] = array(
    'label' => t("User account"),
    'entity type' => 'user',
    'class' => 'PartyUserDataSet',
    'singleton' => TRUE,
    'max cardinality' => 1,
    'admin' => array(
      'edit' => 'admin/config/people/accounts',
      'manage fields' => 'admin/config/people/accounts/fields',
      'manage display' => 'admin/config/people/accounts/display',
    ),
    'form callback' => 'party_user_form_user',
    // Provide a piece corresponding to the data set.
    'piece' => array(
      'path' => 'user',
      'maker' => 'core',
      // @todo: these don't have any effect yet.
      // @see http://drupal.org/node/1669774.
      'weight' => -8,
    ),
    'actions' => array(
      'attach' => array(
        'controller' => 'PartyUserDataSetUIAttach',
        'action label' => 'Attach existing user',
      ),
      'add' => array(
        'controller' => 'PartyUserDataSetUIAdd',
        'action label' => 'Add a new user',
      ),
    ),
    // Some of our permissions require a warning.
    'permissions' => array(
      // Attaching a user account to a party potentially grants a new user
      // access to data on that party.
      'attach' => array(
        'restrict access' => TRUE,
      ),
      'edit' => array(
        'restrict access' => TRUE,
      ),
    ),
  );
  return $sets;
}

/**
 * Implements hook_menu()
 */
function party_user_menu() {
  $items['admin/config/party/user'] = array(
    'title' => 'User Integration',
    'description' => 'Configure Party User Integration',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'party_user_settings_form',
    ),
    'access arguments' => array(
      'administer crm settings',
    ),
    'file' => 'party_user.admin.inc',
  );
  $items['admin/config/party/user/settings'] = array(
    'title' => 'User Integration',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'party_user_settings_form',
    ),
    'access arguments' => array(
      'administer crm settings',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'file' => 'party_user.admin.inc',
    'weight' => -10,
  );
  $items['admin/config/party/user/sync'] = array(
    'title' => 'Sync Users',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'party_user_sync_form',
    ),
    'access arguments' => array(
      'administer crm settings',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'party_user.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_permission()
 *
 * In this case 'own' means attached to a Party the user is also attached to.
 */
function party_user_permission() {
  $permissions = array(
    'view own party' => array(
      'title' => t('View own party'),
    ),
    'edit own party' => array(
      'title' => t('Edit own party'),
    ),
  );

  // Add permissions for each data set.
  foreach (party_get_data_set_info() as $data_set_name => $data_set) {
    $permissions['view own party attached ' . $data_set_name] = array(
      'title' => t('View own party attached %name', array(
        '%name' => $data_set['label'],
      )),
    );
    $permissions['edit own party attached ' . $data_set_name] = array(
      'title' => t('Edit own party attached %name', array(
        '%name' => $data_set['label'],
      )),
    );
    $permissions['detach own party attached ' . $data_set_name] = array(
      'title' => t('Remove own party attached %name', array(
        '%name' => $data_set['label'],
      )),
    );
    $permissions['attach own party ' . $data_set_name] = array(
      'title' => t('Add own party attached %name', array(
        '%name' => $data_set['label'],
      )),
    );
  }
  return $permissions;
}

/**
 * Implements hook_party_access()
 */
function party_user_party_access($op, $party, $data_set, $account) {

  // If we haven't been passed a party, it's outside of the scope of these
  // checks.
  if (!isset($party)) {
    return NULL;
  }

  // Prepare the data set controller.
  $controller = party_get_crm_controller($party, 'user');

  // Deny access for party deletions if the configuration says so.
  if (empty($data_set) && $op == 'delete' && count($controller
    ->getEntityIds()) && variable_get('party_user_party_delete_action', 'disallow') == 'disallow') {
    return FALSE;
  }

  // Check if this is their own party by getting the controller and checking
  // that $account is one of the attached entities for this party.
  if (!in_array($account->uid, $controller
    ->getEntityIds())) {
    return NULL;
  }

  // Set the data_set_name
  if (isset($data_set)) {
    $data_set_name = $data_set['set_name'];
  }

  // If we're looking at permission for a particular data set we check these.
  if (isset($data_set_name)) {

    // Determine which permission we need to check.
    switch ($op) {
      case 'view':
        $permission_string = 'view own party attached ' . $data_set_name;
        break;
      case 'edit':
        $permission_string = 'edit own party attached ' . $data_set_name;
        break;
      case 'detach':
        $permission_string = 'detach own party attached ' . $data_set_name;
        break;
      case 'attach':
      case 'add':
        $permission_string = 'attach own party ' . $data_set_name;
        break;
    }
  }
  else {

    // If we're not being asked about attachments, just use plain permissions.
    switch ($op) {
      case 'view':
        $permission_string = 'view own party';
        break;
      case 'edit':
        $permission_string = 'edit own party';
        break;
    }
  }

  // If we have a valid permission, check it. In this hook we only grant access
  // with the permissions, not deny it. In other words, the permission
  // 'view party attached foo' is sufficient but not neccessary, it is
  // advisable to use these blanket permissions sparingly.
  // @todo: add explanation of this to the party_access() docblock.
  if (isset($permission_string) && user_access($permission_string, $account)) {
    return TRUE;
  }

  // If we get here - say nothing.
  return NULL;
}

/**
 * Implements hook_ctools_plugin_directory().
 */
function party_user_ctools_plugin_directory($owner, $plugin_type) {
  if ($owner == 'party' || $owner == 'ctools' && $plugin_type == 'relationships') {
    return "plugins/{$plugin_type}";
  }
}

/**
 * Menu access callback for the party user piece.
 */
function party_user_party_view_user_access($party) {

  // @todo:
  // - check user_access() for viewing user accounts
  // - check there actually is a user account to show
  // @todo:
  // nice touch, maybe: if there is no user account to show, instead offer a
  // form to connect one?
  return TRUE;
}

/**
 * Page callback for user party piece.
 */
function party_user_party_view_user($party) {

  // @todo: display the user here.
  return 'The user is shown here.';
}

/**
 * Form to edit an attached user.
 */
function party_user_form_user(&$form, &$form_state, $data_set, $delta, $party) {
  module_load_include('inc', 'user', 'user.pages');
  $form += user_profile_form($form, $form_state, $data_set
    ->getEntity($delta));
  unset($form['actions']);
}

/**
 * Validate the user data set form
 *
 * @todo: Implement
 */
function party_user_form_user_validate($element, &$form_state, $data_set, $delta, $party) {
  return TRUE;
}

/**
 * Submit the user data set form
 */
function party_user_form_user_submit($element, &$form_state, $data_set, $delta, $party) {
  $account = $data_set
    ->getEntity($delta);
  $account_unchanged = clone $account;
  $category = $element['#user_category'];
  $values = drupal_array_get_nested_value($form_state['values'], $element['#parents']);

  // This code is taken out of entity_form_submit_build_entity
  // Flatten the $form_state values for the user.
  $account_values = array();
  $account_values += isset($values['account']) ? $values['account'] : array();
  $account_values += isset($values['signature_settings']) ? $values['signature_settings'] : array();
  $account_values += isset($values['picture']) ? $values['picture'] : array();
  $values_excluding_fields = array_diff_key($account_values, field_info_instances('user', 'user'));
  foreach ($values_excluding_fields as $key => $value) {
    $account->{$key} = $value;
  }
  field_attach_submit('user', $account, $element, $form_state);
  $edit = array_intersect_key((array) $account, $account_values);
  user_save($account_unchanged, $edit, $category);
}

/**
 * Implements hook_user_view().
 *
 * Add party action links to the user.
 */
function party_user_user_view($account, $view_mode, $langcode) {
  if ($view_mode == 'party') {
    $party = party_user_get_party($account);
    $data_set_controller = party_get_crm_controller($party, 'user');
    $account->content['party_actions'] = array(
      '#theme' => 'links',
      '#links' => $data_set_controller
        ->getActions($party->pid, $account->uid),
      '#attributes' => array(
        'class' => array(
          'links inline crm-set-action-links',
        ),
      ),
      '#weight' => 100,
    );
  }
}

/**
 * Implements hook_username_alter().
 */
function party_user_username_alter(&$name, $account) {
  if (!variable_get('party_user_format_username', TRUE)) {
    return;
  }
  else {
    if (!($party = party_user_get_party($account))) {
      return;
    }
    else {
      if (empty($party->label)) {
        return;
      }
    }
  }
  $name = $party->label;
}

// ========================================================================
// API Functions

/**
 * party_user_create_party_for_user
 *
 * Create a Party for a user and relate them
 *
 * @param mixed $user The user object or ID
 * @param array $options Hardcoded options to get passed to party_create
 *
 * @return Party a Party object
 *
 * @see party_create
 */
function party_user_create_party_for_user($user, $options = array()) {
  $party = party_create($options);
  if (module_exists('party_hat')) {

    // Add in our hats.
    $hats = array();
    foreach (variable_get('party_user_registration_hats', array()) as $hat_name) {
      $hats[] = $hat_name;
    }
    party_hat_hats_assign($party, $hats);
  }
  party_save($party);
  $data_set_controller = party_get_crm_controller($party, 'user');
  $account = is_object($user) ? $user : user_load($user);
  $data_set_controller
    ->attachEntity($account);
  $data_set_controller
    ->save();

  // This will fail if a plugin that relies on anything other than user is used
  $party = party_save($party);
}

/**
 * Get a User's Party
 *
 * @param mixed $user The user entity or uid
 *
 * @return Party a Party Object
 */
function party_user_get_party($user) {
  if (is_object($user)) {
    $user = $user->uid;
  }
  $result = db_select('party_attached_entity', 'pae')
    ->fields('pae', array(
    'pid',
  ))
    ->condition('eid', $user, '=')
    ->condition('data_set', 'user')
    ->execute()
    ->fetchCol();
  $party_id = reset($result);
  return party_load($party_id);
}

/**
 * Implements hook_module_implements_alter()
 *
 * We're just going to stop profile2 from doing anything with the user page
 * for now. This should supress the thousands of errors we get on that page.
 */
function party_user_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'user_view') {
    unset($implementations['profile2']);
  }
}

/**
 * Implements hook_user_insert().
 *
 * If we have set up Party Acquisition, perform a party match based off of the
 * mail of the account being created. If it exists, this user will acquire the
 * party, if not we'll create a party. We will also create a user if we don't
 * use Party Acquisition but we have set that we want to create a party when a
 * user registers.
 */
function party_user_user_insert(&$edit, $account, $category) {
  if ($category == 'account') {
    $action = variable_get('party_user_on_registration', 'nothing');
    if ($action == 'acquire') {

      // Perform our matching query and load the party.
      $query = db_select('party');
      $query
        ->addField('party', 'pid');
      $query
        ->condition('party.email', $account->mail);
      $query
        ->range(0, 1);
      $party = $query
        ->execute()
        ->fetchField();

      // Attempt to load the party.
      if ($party) {
        $party = party_load($party);
      }
      else {

        // Indicate that we need to create a party.
        $action = 'create';
      }
    }

    // If we need to create a party, lets do it.
    if ($action == 'create') {
      $party = party_create();
      party_save($party);
    }
    if (!empty($party)) {
      if (module_exists('party_hat')) {

        // Add in our hats.
        $hats = array();
        foreach (variable_get('party_user_registration_hats', array()) as $hat_name) {
          $hats[] = $hat_name;
        }
        party_hat_hats_assign($party, $hats);
      }

      // Get our controller and attach the user.
      $controller = party_get_crm_controller($party, 'user');

      // Check there isn't already an account attached.
      $user_ids = $controller
        ->getEntityIds();
      if (empty($user_ids)) {
        $account_clone = clone $account;
        unset($account_clone->is_new);
        $controller
          ->attachEntity($account_clone);
        $controller
          ->save();
      }
      module_invoke_all('party_user_acquisition', $party, $user, $action);
    }
  }
}

/**
 * Implements hook_user_update().
 *
 * Performs the email synchronisation.
 */
function party_user_user_update($edit, $account, $category) {
  if ($category != 'account') {

    // We only want to deal with account, as that is where mail is.
    return;
  }

  // Get our array of fields to update
  $fields = variable_get('party_user_email_sync_fields', array());

  // Check that we have some fields to work with to avoid unnecessary loads
  if (count($fields) > 0 && ($party = party_user_get_party($account))) {

    // Iterate over our fields
    $data_sets = array();
    foreach ($fields as $data_set => $field) {
      list($data_set, $field) = explode(':', $field);
      if (!isset($data_sets[$data_set])) {

        // Load the entity, assume there's only one
        $data_sets[$data_set] = reset(party_get_attached_entities($party, $data_set));
      }
      if ($data_sets[$data_set]) {

        // Update the field and save
        $data_sets[$data_set]->{$field}[LANGUAGE_NONE][0]['value'] = $account->mail;
        $data_sets[$data_set]
          ->save();
      }
    }
  }
}

Functions

Namesort descending Description
party_user_create_party_for_user party_user_create_party_for_user
party_user_ctools_plugin_directory Implements hook_ctools_plugin_directory().
party_user_form_user Form to edit an attached user.
party_user_form_user_submit Submit the user data set form
party_user_form_user_validate Validate the user data set form
party_user_get_party Get a User's Party
party_user_menu Implements hook_menu()
party_user_module_implements_alter Implements hook_module_implements_alter()
party_user_party_access Implements hook_party_access()
party_user_party_data_set_info Implements hook_party_data_set_info()
party_user_party_view_user Page callback for user party piece.
party_user_party_view_user_access Menu access callback for the party user piece.
party_user_permission Implements hook_permission()
party_user_username_alter Implements hook_username_alter().
party_user_user_insert Implements hook_user_insert().
party_user_user_update Implements hook_user_update().
party_user_user_view Implements hook_user_view().