commerce_addressbook.module in Commerce Addressbook 7.3
Same filename and directory in other branches
Defines addressbook functionality for customer profiles, allowing them to be reused and managed on a per-user basis.
File
commerce_addressbook.moduleView 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;
}
}