You are here

commerce_addressbook.module in Commerce Addressbook 7.3

Same filename and directory in other branches
  1. 7 commerce_addressbook.module
  2. 7.2 commerce_addressbook.module

Defines addressbook functionality for customer profiles, allowing them to be reused and managed on a per-user basis.

File

commerce_addressbook.module
View source
<?php

/**
 * @file
 * Defines addressbook functionality for customer profiles, allowing them to be
 * reused and managed on a per-user basis.
 */

/**
 * Implements hook_admin_paths().
 */
function commerce_addressbook_admin_paths() {
  return array(
    'user/*/addressbook/*/create' => TRUE,
    'user/*/addressbook/*/edit/*' => TRUE,
    'user/*/addressbook/*/delete/*' => TRUE,
  );
}

/**
 * Implements hook_hook_info().
 */
function commerce_addressbook_hook_info() {
  $hooks = array(
    'commerce_addressbook_labels_alter' => array(
      'group' => 'commerce',
    ),
  );
  return $hooks;
}

/**
 * Implements hook_menu().
 */
function commerce_addressbook_menu() {
  $items = array();
  $items['user/%user/addressbook'] = array(
    'title' => 'Address Book',
    'page callback' => 'commerce_addressbook_page',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'commerce_addressbook_page_access',
    'access arguments' => array(
      1,
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'includes/commerce_addressbook.user.inc',
    'weight' => 20,
  );

  // Custom administrative components for managing customer profile entities
  // from the user pages.
  foreach (commerce_customer_profile_types() as $type => $profile_type) {
    $items['user/%user/addressbook/' . $type] = array(
      'page callback' => 'commerce_addressbook_profile_page',
      'page arguments' => array(
        1,
        $type,
      ),
      'access callback' => 'commerce_addressbook_profile_page_access',
      'access arguments' => array(
        1,
        $type,
      ),
      'title' => $profile_type['name'],
      'type' => MENU_LOCAL_TASK,
      'file' => 'includes/commerce_addressbook.user.inc',
    );
    $items['user/%user/addressbook/' . $type . '/create'] = array(
      'page callback' => 'commerce_addressbook_profile_create',
      'page arguments' => array(
        1,
        $type,
      ),
      'access callback' => 'commerce_addressbook_profile_create_access',
      'access arguments' => array(
        1,
        $type,
      ),
      'title' => 'Add an address',
      'type' => MENU_LOCAL_ACTION,
      'file' => 'includes/commerce_addressbook.user.inc',
    );
    $items['user/%user/addressbook/' . $type . '/edit/%commerce_customer_profile'] = array(
      'title callback' => 'commerce_addressbook_profile_edit_title',
      'title arguments' => array(
        3,
      ),
      'page callback' => 'commerce_addressbook_profile_options_edit',
      'page arguments' => array(
        1,
        5,
      ),
      'access callback' => 'commerce_customer_profile_access',
      'access arguments' => array(
        'update',
        5,
      ),
      'type' => MENU_CALLBACK,
      'file' => 'includes/commerce_addressbook.user.inc',
    );
    $items['user/%user/addressbook/' . $type . '/default/%commerce_customer_profile'] = array(
      'page callback' => 'commerce_addressbook_profile_options_default',
      'page arguments' => array(
        1,
        5,
      ),
      'access callback' => 'commerce_customer_profile_access',
      'access arguments' => array(
        'update',
        5,
      ),
      'type' => MENU_CALLBACK,
      'file' => 'includes/commerce_addressbook.user.inc',
    );
    $items['user/%user/addressbook/' . $type . '/delete/%commerce_customer_profile'] = array(
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'commerce_addressbook_profile_options_delete_form',
        1,
        5,
      ),
      'access callback' => 'commerce_customer_profile_access',
      'access arguments' => array(
        'delete',
        5,
      ),
      'type' => MENU_CALLBACK,
      'file' => 'includes/commerce_addressbook.user.inc',
    );
  }
  return $items;
}

/**
 * Title callback for profile edit page.
 *
 * @param $type
 *   Machine name of customer profile type.
 *
 * @return string
 *   Translatable page title.
 */
function commerce_addressbook_profile_edit_title($type) {
  return t('Edit @type profile', array(
    '@type' => str_replace('_', ' ', $type),
  ));
}

/**
 * Access callback for path /user/%user/addressbook.
 *
 * Return the first enabled profile type if there's one, or FALSE.
 */
function commerce_addressbook_page_access($account) {
  foreach (commerce_customer_profile_types() as $type => $profile_type) {
    if (commerce_addressbook_profile_page_access($account, $type)) {
      return $type;
    }
  }
  return FALSE;
}

/**
 * Access callback: determine if the user can create a customer profile of the
 * given type.
 */
function commerce_addressbook_profile_create_access($account, $type) {
  global $user;

  // The user has admin privileges, or is on his own pages.
  if (user_access('administer commerce_customer_profile entities') || $user->uid == $account->uid) {
    if (user_access('create commerce_customer_profile entities') || user_access('create commerce_customer_profile entities of bundle ' . $type)) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Access callback: determine if the user can access the listing page of a
 * given profile type.
 */
function commerce_addressbook_profile_page_access($account, $profile_type) {
  global $user;

  // Check if the user can access any page.
  if (user_access('administer commerce_customer_profile entities') || user_access('view any commerce_customer_profile entity') || user_access('view any commerce_customer_profile entity of bundle ' . $profile_type) || user_access('edit any commerce_customer_profile entity') || user_access('edit any commerce_customer_profile entity of bundle ' . $profile_type)) {
    return TRUE;
  }

  // Check if the user can access his own page.
  if ($user->uid == $account->uid) {
    if (user_access('view own commerce_customer_profile entities') || user_access('create commerce_customer_profile entities') || user_access('create commerce_customer_profile entities of bundle ' . $profile_type) || user_access('view own commerce_customer_profile entities of bundle ' . $profile_type) || user_access('edit own commerce_customer_profile entities') || user_access('edit own commerce_customer_profile entities of bundle ' . $profile_type)) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Implements hook_commerce_checkout_pane_info_alter().
 *
 * Changes all customer profile panes to use the addressbook pane code
 * instead.
 */
function commerce_addressbook_commerce_checkout_pane_info_alter(&$checkout_panes) {
  foreach (commerce_customer_profile_types() as $type => $profile_type) {
    $checkout_panes['customer_profile_' . $type]['module'] = 'commerce_addressbook';
    $checkout_panes['customer_profile_' . $type]['file'] = 'commerce_addressbook.checkout_pane.inc';
    $checkout_panes['customer_profile_' . $type]['base'] = 'commerce_addressbook_pane';
  }
  return $checkout_panes;
}

/**
 * Loads the active customer profiles of the specified type for a given user.
 *
 * @param $uid
 *   The uid of the user.
 * @param $type
 *   The type of customer profile to look up.
 *
 * @return array
 *   An array of customer profiles of the specified type for a given user.
 */
function commerce_addressbook_get_active_profiles($uid, $type) {
  if (!$uid) {
    return array();
  }
  $query = new EntityFieldQuery();
  $query
    ->entityCondition('entity_type', 'commerce_customer_profile')
    ->entityCondition('bundle', $type)
    ->propertyCondition('uid', $uid)
    ->propertyCondition('status', TRUE)
    ->entityOrderBy('entity_id', 'DESC')
    ->addTag('commerce_addressbook')
    ->range(0, 10);
  $results = $query
    ->execute();
  if (isset($results['commerce_customer_profile'])) {
    return commerce_customer_profile_load_multiple(array_keys($results['commerce_customer_profile']));
  }
  return array();
}

/**
 * Returns whether the provided customer profile is incomplete.
 *
 * Incomplete profiles need to be presented to the customer and completed
 * before checkout is completed.
 *
 * A profile is incomplete if:
 * - $profile->data['incomplete'] = TRUE, meaning that it was created with the
 * intention of being edited during the customer's first checkout.
 * - validation via the Entity Wrapper fails, because a required field is
 * empty or a validation callback specified by the field type returned FALSE.
 *
 * @param $profile
 *   The customer profile entity.
 *
 * @return
 *   TRUE if the customer profile is incomplete and should be presented
 *   to the customer for editing. Otherwise, FALSE.
 */
function commerce_addressbook_profile_is_incomplete($profile) {
  if (!empty($profile->data['incomplete'])) {
    return TRUE;
  }
  $wrapper = entity_metadata_wrapper('commerce_customer_profile', $profile);
  foreach (field_info_instances('commerce_customer_profile', $profile->type) as $instance) {
    $value = $wrapper->{$instance['field_name']}
      ->value();
    if (!$wrapper->{$instance['field_name']}
      ->validate($value)) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Sets the given customer profile as the default one.
 *
 * @param $profile
 *   The customer profile object.
 */
function commerce_addressbook_set_default_profile($profile) {
  if (empty($profile->profile_id) || !$profile->uid) {
    return;
  }
  db_merge('commerce_addressbook_defaults')
    ->key(array(
    'uid' => $profile->uid,
    'type' => $profile->type,
  ))
    ->fields(array(
    'profile_id' => $profile->profile_id,
  ))
    ->execute();

  // Allow modules to react to change in customer profile default change.
  rules_invoke_all('commerce_addressbook_set_default', $profile);
}

/**
 * Returns the default customer profile id for a given user id and profile type.
 *
 * @param $uid
 *   The uid of the user whose default profile id should be returned.
 * @param $type
 *   The type of customer profile to look up.
 *
 * @return
 *   The id of the default profile if set, FALSE otherwise.
 */
function commerce_addressbook_get_default_profile_id($uid, $type) {
  $results =& drupal_static(__FUNCTION__, array());
  if (isset($results[$uid][$type])) {
    return $results[$uid][$type];
  }
  $query = db_select('commerce_addressbook_defaults', 'cad')
    ->fields('cad', array(
    'profile_id',
  ))
    ->condition('uid', $uid)
    ->condition('type', $type)
    ->execute();
  $record = $query
    ->fetchObject();
  $results[$uid][$type] = $record ? $record->profile_id : FALSE;
  return $results[$uid][$type];
}

/**
 * Deletes the default customer profile for a given type.
 *
 * @param $uid
 *   The uid of the user whose default profile should be deleted.
 * @param $type
 *   The type of customer profile to delete.
 */
function commerce_addressbook_delete_default_profile($uid, $type) {
  db_delete('commerce_addressbook_defaults')
    ->condition('uid', $uid)
    ->condition('type', $type)
    ->execute();
}

/**
 * Implements hook_commerce_customer_profile_insert().
 *
 * Set the new customer profile as default if there's none.
 */
function commerce_addressbook_commerce_customer_profile_insert($profile) {
  if ($profile->uid) {
    $default_profile_id = commerce_addressbook_get_default_profile_id($profile->uid, $profile->type);
    if (!$default_profile_id) {
      commerce_addressbook_set_default_profile($profile);
    }
  }
}

/**
 * Implements hook_commerce_customer_profile_update().
 *
 * Set the last updated customer profile as default if there's none.
 */
function commerce_addressbook_commerce_customer_profile_update($profile) {
  if ($profile->uid) {
    $default_profile_id = commerce_addressbook_get_default_profile_id($profile->uid, $profile->type);
    if (!$default_profile_id) {
      commerce_addressbook_set_default_profile($profile);
    }
  }
}

/**
 * Implements hook_commerce_customer_profile_delete().
 */
function commerce_addressbook_commerce_customer_profile_delete($profile) {
  if ($profile->uid) {
    $default_profile_id = commerce_addressbook_get_default_profile_id($profile->uid, $profile->type);
    if ($default_profile_id == $profile->profile_id) {
      commerce_addressbook_delete_default_profile($profile->uid, $profile->type);
    }
  }
}

/**
 * Implements hook_views_api().
 */
function commerce_addressbook_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'commerce_addressbook') . '/includes/views',
  );
}

/**
 * Retrieves the specified view.
 *
 * @param $name
 *   The name of the view to retrieve.
 * @param $display_id
 *   The ID of the display of the view.
 * @param $arguments
 *   An array of arguments to pass to the view.
 * @param $override_url
 *   A url that overrides the url of the current view.
 *
 * @return
 *   The view object, you'll have to call render if to render it.
 */
function commerce_addressbook_retrieve_view($name, $display_id, $arguments, $override_url = '') {

  // Load the specified view.
  $view = views_get_view($name);
  $view
    ->set_display($display_id);

  // Set the specific arguments passed in.
  $view
    ->set_arguments($arguments);

  // Override the view url, if an override was provided.
  if (!empty($override_url)) {
    $view->override_url = $override_url;
  }

  // Prepare and execute the view query.
  $view
    ->pre_execute();
  $view
    ->execute();
  return $view;
}

/**
 * Implements hook_entity_info_alter().
 */
function commerce_addressbook_entity_info_alter(&$info) {
  $info['commerce_customer_profile']['view modes']['addressbook'] = array(
    'label' => t('Addressbook'),
    'custom settings' => FALSE,
  );
}

/**
 * Implements hook_forms().
 */
function commerce_addressbook_forms() {
  $forms = array();

  // Define a wrapper ID for the customer profile form used by addressbook.
  $forms['commerce_addressbook_customer_profile_form'] = array(
    'callback' => 'commerce_customer_customer_profile_form',
  );
  return $forms;
}

/**
 * Implements hook_entity_view().
 *
 * Adds the "edit", "delete" and "set as default" links to the customer profile.
 */
function commerce_addressbook_entity_view($entity, $type, $view_mode, $langcode) {
  if ($type != 'commerce_customer_profile' || $view_mode != 'addressbook') {
    return;
  }
  $links = array();
  global $user;
  if (commerce_customer_profile_access('update', $entity)) {
    $default_profile_id = commerce_addressbook_get_default_profile_id($user->uid, $entity->type);
    drupal_add_library('system', 'drupal.ajax');
    if (!$default_profile_id || $default_profile_id != $entity->profile_id) {
      $links['default'] = array(
        '#theme' => 'link',
        '#text' => t('set as default'),
        '#path' => 'user/' . $entity->uid . '/addressbook/' . $entity->type . '/default/' . $entity->profile_id . '/nojs',
        '#options' => array(
          'attributes' => array(
            'class' => array(
              'use-ajax',
            ),
          ),
          'html' => FALSE,
        ),
      );
    }
    $links['edit'] = array(
      '#theme' => 'link',
      '#text' => t('edit'),
      '#path' => 'user/' . $entity->uid . '/addressbook/' . $entity->type . '/edit/' . $entity->profile_id,
      '#options' => array(
        'attributes' => array(),
        'html' => FALSE,
      ),
    );
  }
  if (commerce_customer_profile_access('delete', $entity)) {
    $links['delete'] = array(
      '#theme' => 'link',
      '#text' => t('delete'),
      '#path' => 'user/' . $entity->uid . '/addressbook/' . $entity->type . '/delete/' . $entity->profile_id,
      '#options' => array(
        'attributes' => array(),
        'html' => FALSE,
      ),
    );
  }
  if ($links) {

    // Add suffixes for each link except the last one.
    $last_link = end($links);
    foreach ($links as $key => $link) {
      if ($last_link !== $link) {
        $links[$key]['#suffix'] = ' | ';
      }
    }
    $entity->content['commerce_addressbook_options'] = array_merge(array(
      '#weight' => 100,
      '#prefix' => '<div class="addressbook-links">',
      '#suffix' => '</div>',
    ), $links);
  }
}

/**
 * Implements hook_form_alter().
 */
function commerce_addressbook_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'commerce_addressbook_customer_profile_form') {

    // Make sure the submit handlers run.
    rsort($form['actions']['submit']['#submit']);
    foreach ($form['actions']['submit']['#submit'] as $callback) {
      array_unshift($form['#submit'], $callback);
    }
    unset($form['actions']['submit']['#submit']);

    // Hide the "Additional settings" vertical tabs.
    $form['additional_settings']['#access'] = FALSE;
  }
}

Functions

Namesort descending Description
commerce_addressbook_admin_paths Implements hook_admin_paths().
commerce_addressbook_commerce_checkout_pane_info_alter Implements hook_commerce_checkout_pane_info_alter().
commerce_addressbook_commerce_customer_profile_delete Implements hook_commerce_customer_profile_delete().
commerce_addressbook_commerce_customer_profile_insert Implements hook_commerce_customer_profile_insert().
commerce_addressbook_commerce_customer_profile_update Implements hook_commerce_customer_profile_update().
commerce_addressbook_delete_default_profile Deletes the default customer profile for a given type.
commerce_addressbook_entity_info_alter Implements hook_entity_info_alter().
commerce_addressbook_entity_view Implements hook_entity_view().
commerce_addressbook_forms Implements hook_forms().
commerce_addressbook_form_alter Implements hook_form_alter().
commerce_addressbook_get_active_profiles Loads the active customer profiles of the specified type for a given user.
commerce_addressbook_get_default_profile_id Returns the default customer profile id for a given user id and profile type.
commerce_addressbook_hook_info Implements hook_hook_info().
commerce_addressbook_menu Implements hook_menu().
commerce_addressbook_page_access Access callback for path /user/%user/addressbook.
commerce_addressbook_profile_create_access Access callback: determine if the user can create a customer profile of the given type.
commerce_addressbook_profile_edit_title Title callback for profile edit page.
commerce_addressbook_profile_is_incomplete Returns whether the provided customer profile is incomplete.
commerce_addressbook_profile_page_access Access callback: determine if the user can access the listing page of a given profile type.
commerce_addressbook_retrieve_view Retrieves the specified view.
commerce_addressbook_set_default_profile Sets the given customer profile as the default one.
commerce_addressbook_views_api Implements hook_views_api().