commerce_coupon.module in Commerce Coupon 7
Same filename and directory in other branches
Coupon System for Drupal Commerce.
This file contains all the major functionality for providing a coupon system to the Drupal Commerce system.
File
commerce_coupon.moduleView source
<?php
/**
* @file
* Coupon System for Drupal Commerce.
*
* This file contains all the major functionality for providing a coupon system
* to the Drupal Commerce system.
*/
/**
* Implements hook_entity_info().
*
* This function provides information about the coupon entities.
*/
function commerce_coupon_entity_info() {
$entity_info['commerce_coupon'] = array(
'label' => t('Commerce Coupon'),
'plural label' => t('Commerce Coupons'),
'controller class' => 'CommerceCouponEntityController',
'base table' => 'commerce_coupon',
'fieldable' => TRUE,
'entity keys' => array(
'id' => 'coupon_id',
'bundle' => 'type',
),
'bundles' => array(),
'bundle keys' => array(
'bundle' => 'type',
),
'module' => 'commerce_coupon',
'permission labels' => array(
'singular' => t('coupon'),
'plural' => t('coupons'),
),
'access callback' => 'commerce_entity_access',
'access arguments' => array(
'user key' => 'uid',
'access tag' => 'commerce_coupon_access',
),
);
$entity_info['commerce_coupon_type'] = array(
'label' => t('Commerce Coupon Type'),
'plural label' => t('Commerce Coupon Types'),
'entity class' => 'CommerceCouponType',
'controller class' => 'EntityAPIControllerExportable',
'base table' => 'commerce_coupon_type',
'fieldable' => FALSE,
'bundle of' => 'commerce_coupon',
'exportable' => FALSE,
'entity keys' => array(
'id' => 'type',
'label' => 'label',
),
'access callback' => 'commerce_coupon_type_access',
'module' => 'commerce_coupon',
);
return $entity_info;
}
/**
* Callback for getting coupon properties.
* @see commerce_coupon_entity_property_info()
*/
function commerce_coupon_get_properties($coupon, array $options, $name) {
switch ($name) {
case 'price_component_name':
$coupon_machine_name = commerce_coupon_machine_name_code($coupon);
return $coupon->type . '_' . $coupon_machine_name;
break;
case 'times_used':
return commerce_coupon_get_number_of_uses($coupon->coupon_id);
break;
}
}
/**
* Implements hook_entity_info_alter().
*
* Use this hook to specify commerce coupon bundles to avoid a recursion, as
* loading the commerce coupon types needs the entity info too.
*/
function commerce_coupon_entity_info_alter(&$entity_info) {
foreach (commerce_coupon_get_types() as $type => $info) {
$entity_info['commerce_coupon']['bundles'][$type]['label'] = $info->label;
}
}
/**
* Implements hook_views_api().
*/
function commerce_coupon_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'commerce_coupon') . '/includes/views',
);
}
/**
* Implements hook_commerce_checkout_pane_info().
*/
function commerce_coupon_commerce_checkout_pane_info() {
$checkout_panes['commerce_coupon'] = array(
'title' => t('Coupons'),
'page' => 'checkout',
'locked' => FALSE,
'file' => 'includes/commerce_coupon.checkout_pane.inc',
'base' => 'commerce_coupon_pane',
'weight' => 9,
);
return $checkout_panes;
}
/**
* Access callback for coupon types.
*/
function commerce_coupon_type_access($op, $type = NULL, $account = NULL) {
return user_access('administer coupon types', $account);
}
/**
* Checks coupon access for various operations.
*
* @param $op
* The operation being performed. One of 'view', 'update', 'create' or
* 'delete'.
* @param $coupon
* Optionally a coupon to check access for. If nothing is given access
* permissions for all coupons are returned.
* @param $account
* The user to check for. Leave it to NULL to check for the current user.
* @return bool
*/
function commerce_coupon_access($op, $coupon = NULL, $account = NULL) {
return commerce_entity_access($op, $coupon, $account, 'commerce_coupon');
}
/**
* Implements hook_permission().
*
* Provides the basic access objects
*/
function commerce_coupon_permission() {
$permissions = array(
'administer coupon settings' => array(
'title' => t('Administer Coupon Settings'),
'description' => t('Allows users to manage coupon settings.'),
),
'administer coupon types' => array(
'title' => t('Administer Coupon Types'),
'description' => t('Allows users to manage coupon types.'),
),
);
$permissions += commerce_entity_access_permissions('commerce_coupon');
return $permissions;
}
/**
* Generates a new unique coupon code.
*
* @param $length
* Optional The length of the new code.
* @return String
* The new coupon code.
*/
function commerce_coupon_generate_coupon_code($length = NULL) {
// We define the possible characters. No 'l','1', 'i' to prevent
// reconisation problems.
$characters = array(
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'J',
'K',
'L',
'M',
'N',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'j',
'k',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
);
$numberOfCharacters = count($characters);
$codeFound = FALSE;
if ($length == NULL) {
$length = variable_get('commerce_coupon_default_code_size', 8);
}
// We need to check if the produced coupon code is already in the
// database. We try this for 1000 iteration. If we then not found a
// a code, we stop. There must be an error in this case.
for ($i = 0; $i < 1000 && $codeFound == FALSE; $i++) {
$code = '';
// Create the code per character
for ($c = 0; $c < $length; $c++) {
$randIndex = mt_rand(0, $numberOfCharacters - 1);
$code .= $characters[$randIndex];
}
// Check in the database if the generated code is already defined.
if (commerce_coupon_code_exists($code) == FALSE) {
$codeFound = TRUE;
}
}
return $code;
}
/**
* Checks if a given coupon is valid for a given order. The validation is done
* by the rules engine.
*
* @TODO: We can throw exception with error message, instead of set the error
* message to a global variable.
*
* @param $code
* The coupon code to validate.
* @param $order
* The order at against the $code should be validated.
* @return boolean
* Returns TRUE if the code is valid else FALSE.
*/
function commerce_coupon_code_is_valid($code, $order) {
global $_commerce_coupon_validation_error_message;
// Trim trailing spaces
$code = trim($code);
$coupon = commerce_coupon_load_by_code($code);
// if no such coupon found, the $code is invalid
if (!is_object($coupon)) {
// $commerce_coupon_validation_error_message = t('Coupon code is invalid.');
return FALSE;
}
// Check if the coupon is already applied to this order. In any case we
// never want that a coupon is applied twice.
if (commerce_coupon_code_is_in_order($code, $order)) {
$_commerce_coupon_validation_error_message = t('Sorry, you can only apply a coupon once per order.');
return FALSE;
}
// Check coupon status.
if ($coupon->is_active == FALSE) {
return FALSE;
}
// We use the drupal_static function to generate a global variable.
// We set per default the result to TRUE. The rules can modify this values,
// by invoking the valid or invalid action.
$validation_results =& drupal_static('commerce_coupon_action_validation_results');
$validation_results = TRUE;
// We invoke the rules. The defined action callback methods sets then the
// validation result appropriate.
rules_invoke_event('commerce_coupon_validate', $coupon, $order);
// We get our global variable and return the result.
return drupal_static('commerce_coupon_action_validation_results');
}
/**
* Redeem a coupon. For calculating the coupon value the rules engine is used.
*
* @param $coupon
* The coupon to redeem.
* @param $order
* The order on which the coupon should be redeemed.
* @return void
*/
function commerce_coupon_redeem_coupon($coupon, $order) {
if (!isset($order->order_id) or !isset($coupon->coupon_id)) {
drupal_set_message(t('Your coupon code cannot be redeemed.'), 'error');
return;
}
// We invoke the rule. The defined action callback methods sets then the
// coupon value appropriate.
rules_invoke_event('commerce_coupon_redeem', $coupon, $order);
commerce_order_save($order);
}
/**
* Create a new type coupon object.
*
* @param $values
* List of initial object attributes.
* @return CommerceCoupon
* The new CommerceCouponType object.
*/
function commerce_coupon_type_create(array $values = array()) {
$values['is_new'] = TRUE;
return new CommerceCouponType($values);
}
/**
* Gets an array of all coupon types, keyed by the type name.
*
* @param $coupon_type_name
* If set, the type with the given name is returned.
* @return CouponType[]
* Depending whether $type isset, an array of coupon types or a single one.
*/
function commerce_coupon_get_types($coupon_type_name = NULL) {
$types = entity_load('commerce_coupon_type', isset($coupon_type_name) ? array(
$coupon_type_name,
) : FALSE);
return isset($coupon_type_name) ? $types[$coupon_type_name] : $types;
}
/**
* Menu argument loader; Load a coupon type by string.
*
* @param $coupon_type_name
* The machine-readable name of a coupon type to load.
* @return
* A commerce coupon type array or FALSE if $type does not exist.
*/
function commerce_coupon_type_load($coupon_type_name) {
$coupon_type_name = strtr($coupon_type_name, array(
'-' => '_',
));
$coupon_types = commerce_coupon_get_types();
return !empty($coupon_types[$coupon_type_name]) ? $coupon_types[$coupon_type_name] : FALSE;
}
/**
* Saves a coupon type to the database.
*
* @param $type
* The CommerceCouponType object to store.
* @param $reset
* Optional Should add the configuration to coupon type. (default: TRUE)
* @return CommerceCouponType
* The stored CommerceCouponType object.
*/
function commerce_coupon_type_save(CommerceCouponType $type, $reset = FALSE) {
// Store the entity, must be done before they are configured
$type
->save();
// Configure the type
commerce_coupon_type_configure($type->type, $reset);
// Ensure the creation of the rules (components)
entity_defaults_rebuild();
return $type;
}
/**
* Deletes a coupon type.
*
* @param $coupon_type
* Machine name of the coupon type to delete
* @return void
*/
function commerce_coupon_type_delete($coupon_type_name) {
return commerce_coupon_type_delete_multiple(array(
$coupon_type_name,
));
}
/**
* Delete multiple coupon types.
*
* @param $commerce_coupon_type_names
* An array of coupon type machine names.
*/
function commerce_coupon_type_delete_multiple(array $coupon_type_names) {
return entity_get_controller('commerce_coupon_type')
->delete($coupon_type_names);
}
/**
* Disables a coupon type and set as inactive all the coupons from the type.
*
* @param string $coupon_type_name
* A machine name for the coupon type to disable.
*/
function commerce_coupon_type_disable($coupon_type_name) {
$coupon_type = commerce_coupon_type_load($coupon_type_name);
if (!empty($coupon_type)) {
// Disable the coupon type.
$coupon_type->status = 0;
commerce_coupon_type_save($coupon_type, TRUE);
// Also disable the coupons for the type.
$coupons = commerce_coupon_load_multiple(array(), array(
'type' => $coupon_type_name,
));
foreach ($coupons as $coupon) {
$coupon->is_active = 0;
commerce_coupon_save($coupon);
}
menu_rebuild();
}
}
/**
* Enables a coupon type.
*
* @param string $coupon_type_name
* A machine name for the coupon type to disable.
*/
function commerce_coupon_type_enable($coupon_type_name) {
$coupon_type = commerce_coupon_type_load($coupon_type_name);
if (!empty($coupon_type)) {
$coupon_type->status = 1;
commerce_coupon_type_save($coupon_type, TRUE);
menu_rebuild();
}
}
/**
* Implements hook_commerce_coupon_type_delete().
*/
function commerce_coupon_commerce_coupon_type_delete($type) {
// Delete all coupons of this type.
if ($pids = array_keys(commerce_coupon_load_multiple(FALSE, array(
'type' => $type->type,
)))) {
commerce_coupon_delete_multiple($pids);
}
// Rebuild the menu as any (user-category) menu items should be gone now.
menu_rebuild();
}
/**
* Ensures a base price field is present on a coupon type bundle.
*
* @param $bundle
* The coupon type string to configure.
* @param $reset
*/
function commerce_coupon_type_configure($bundle, $reset) {
$entity_type = 'commerce_coupon';
// Look for or add the specified coupon code
$field_name = 'commerce_coupon_code';
$field = field_info_field($field_name);
$instance = field_read_instance($entity_type, $field_name, $bundle);
if (empty($field) || $reset) {
$field_data = array(
'field_name' => $field_name,
'type' => 'text',
'cardinality' => 1,
'entity_types' => array(
$entity_type,
),
'translatable' => FALSE,
'locked' => TRUE,
'settings' => array(),
);
if (empty($field)) {
field_create_field($field_data);
}
else {
field_update_field($field_data);
}
}
if (empty($instance) || $reset) {
$instance_data = array(
'field_name' => $field_name,
'entity_type' => $entity_type,
'bundle' => $bundle,
'label' => 'Coupon Code',
'required' => FALSE,
'settings' => array(),
'display' => array(),
);
if (empty($instance)) {
field_create_instance($instance_data);
}
else {
field_update_instance($instance_data);
}
}
// Look for or add the number of uses.
$field_name = 'commerce_coupon_number_of_uses';
$field = field_info_field($field_name);
$instance = field_info_instance($entity_type, $field_name, $bundle);
if (empty($field) || $reset) {
$field_data = array(
'field_name' => $field_name,
'type' => 'number_integer',
'cardinality' => 1,
'entity_types' => array(
$entity_type,
),
'translatable' => FALSE,
'locked' => FALSE,
'settings' => array(),
);
if (empty($field)) {
field_create_field($field_data);
}
else {
field_update_field($field_data);
}
}
if (empty($instance) || $reset) {
$instance_data = array(
'field_name' => $field_name,
'entity_type' => $entity_type,
'bundle' => $bundle,
'label' => 'Maximum number of Uses',
'description' => 'Number of times that coupon code can be used by any customer on the site, before it is set to inactive',
'required' => FALSE,
'display' => array(),
'settings' => array(
'min' => '0',
),
'default_value' => array(
0 => array(
'value' => 1,
),
),
);
if (empty($instance)) {
field_create_instance($instance_data);
}
else {
field_update_instance($instance_data);
}
}
// Allow other modules to configure coupon types:
module_invoke_all('commerce_coupon_type_configure', $bundle, $reset);
}
/**
* Returns the name of the specified coupon type or all names keyed by type if
* no type is specified.
*
* @param $type
* Optional parameter specifying the type whose name to return.
*
* @return CouponType Either the specified name, defaulting to the type
* itself if the name is not found, or an array of all names keyed by type if no type is passed in.
*/
function commerce_coupon_type_get_name($type = NULL) {
$coupon_types = commerce_coupon_get_types();
// Return a type name if specified and it exists.
if (!empty($type)) {
if (isset($coupon_types[$type])) {
return $coupon_types[$type]->label;
}
else {
// Return FALSE if it does not exist.
return FALSE;
}
}
// Otherwise turn the array values into the type name only.
foreach ($coupon_types as $key => $value) {
$coupon_types[$key] = $value->label;
}
return $coupon_types;
}
/**
* Wraps commerce_coupon_type_get_name() for the Entity module.
*/
function commerce_coupon_type_options_list() {
return commerce_coupon_type_get_name();
}
/**
* Fetch a coupon object.
*
* @param $commerce_coupon_id
* Integer specifying the coupon id.
* @param bool $reset
* A boolean indicating that the internal cache should be reset.
* @return mixed A fully-loaded $commerce_coupon object or FALSE if it cannot be loaded.@see commerce_coupon_load_multiple()
*/
function commerce_coupon_load($commerce_coupon_id, $reset = FALSE) {
$commerce_coupons = commerce_coupon_load_multiple(array(
$commerce_coupon_id,
), array(), $reset);
return reset($commerce_coupons);
}
/**
* Load multiple coupons based on certain conditions.
*
* @param array $commerce_coupon_ids
* An array of coupon IDs.
* @param array $conditions
* An array of conditions to match against the {commerce_coupon} table.
* @param bool $reset
* A boolean indicating that the internal cache should be reset.
* @return array An array of coupon objects, indexed by coupon id.@see entity_load()
* @see commerce_coupon_load()
*/
function commerce_coupon_load_multiple($commerce_coupon_ids = array(), $conditions = array(), $reset = FALSE) {
if (empty($commerce_coupon_ids) && empty($conditions)) {
return array();
}
return entity_load('commerce_coupon', $commerce_coupon_ids, $conditions, $reset);
}
/**
* Loads a coupon by its coupon code.
*
* @param $code
* A code of a coupon.
* @return mixed A coupon object corresponding to the coupon code.
*/
function commerce_coupon_load_by_code($code) {
$query = new EntityFieldQuery();
$result = $query
->entityCondition('entity_type', 'commerce_coupon')
->fieldCondition('commerce_coupon_code', 'value', $code, '=')
->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT')
->execute();
if (empty($result)) {
return;
}
$commerce_coupon = reset($result['commerce_coupon']);
return commerce_coupon_load($commerce_coupon->coupon_id);
}
/**
* Removes a coupon from the order context.
* references.
*
* @param $order
* Order object to affect in the coupon removal.
* @param $coupon
* Coupon object to remove.
*/
function commerce_coupon_remove_coupon_from_order($order, $coupon) {
$original_order = clone $order;
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
// Remove the coupons from the order relationship.
foreach ($order_wrapper->commerce_coupon_order_reference as $delta => $coupon_wrapper) {
if ($coupon_wrapper->coupon_id
->value() == $coupon->coupon_id) {
$order_wrapper->commerce_coupon_order_reference
->offsetUnset($delta);
}
}
if ($original_order != $order) {
commerce_order_save($order);
}
// Make a EFQ to get coupon line items in that order that match to the coupon.
$query = new EntityFieldQuery();
$result = $query
->entityCondition('entity_type', 'commerce_line_item')
->propertyCondition('order_id', $order->order_id)
->propertyCondition('type', 'commerce_coupon')
->fieldCondition('commerce_coupon_reference', 'target_id', $coupon->coupon_id, '=')
->execute();
if (empty($result)) {
return;
}
$line_item_ids = array_keys($result['commerce_line_item']);
if (!empty($line_item_ids)) {
// First remove the line items from the order and save it to avoid
// conflicts.
foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
if (in_array($line_item_wrapper->line_item_id
->value(), $line_item_ids)) {
$order_wrapper->commerce_line_items
->offsetUnset($delta);
}
}
commerce_line_item_delete_multiple($line_item_ids);
}
}
/**
* Removes all coupons from a given order.
* references.
*
* @param $order
* Order object to affect in the coupon removal.
*/
function commerce_coupon_remove_all_coupons_from_order($order) {
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
$coupons = $order_wrapper->commerce_coupon_order_reference
->value();
foreach ($coupons as $coupon) {
commerce_coupon_remove_coupon_from_order($order, $coupon);
}
}
/**
* Create a new coupon object.
*
* @param $values
* List of initial object attributes.
* @return CommerceCoupon
* The new CommerceCoupon object.
*/
function commerce_coupon_create($type = '') {
return entity_get_controller('commerce_coupon')
->create(array(
'type' => $type,
));
}
/**
* Saves a coupon.
*
* @param $commerce_coupon
* The full coupon object to save.
*
* @return
* SAVED_NEW or SAVED_UPDATED depending on the operation performed.
*/
function commerce_coupon_save($commerce_coupon) {
return entity_get_controller('commerce_coupon')
->save($commerce_coupon);
}
/**
* Deletes a coupon.
*
* @param $commerce_coupon_id
* Id of the coupon to delete.
* @return void
*/
function commerce_coupon_delete($commerce_coupon_id) {
return commerce_coupon_delete_multiple(array(
$commerce_coupon_id,
));
}
/**
* Delete multiple coupons.
*
* @param $commerce_coupon_ids
* An array of coupon IDs.
*/
function commerce_coupon_delete_multiple(array $commerce_coupon_ids) {
return entity_get_controller('commerce_coupon')
->delete($commerce_coupon_ids);
}
/**
* Determines whether or not the give coupon can be deleted.
*
* @param $coupon
* The coupon to be checked for deletion.
*
* @return
* Boolean indicating whether or not the coupon can be deleted.
*
* @see commerce_product_can_delete()
*/
function commerce_coupon_can_delete($coupon) {
// Return FALSE if the given coupon does not have an ID; it need not be
// deleted, which is functionally equivalent to cannot be deleted as far as
// code depending on this function is concerned.
if (empty($coupon->coupon_id)) {
return FALSE;
}
// If any module implementing hook_commerce_coupon_can_delete() returns FALSE
// the coupon cannot be deleted. Return TRUE if none return FALSE.
return !in_array(FALSE, module_invoke_all('commerce_coupon_can_delete', $coupon));
}
/**
* Implements commerce_coupon_can_delete().
*/
function commerce_coupon_commerce_coupon_can_delete($coupon) {
// Use EntityFieldQuery to look for orders referencing this coupon and don't
// allow the delete to occur if one exists.
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', 'commerce_order', '=')
->fieldCondition('commerce_coupon_order_reference', 'target_id', $coupon->coupon_id, '=')
->count();
return $query
->execute() == 0;
}
/**
* Checks if a given coupon code exists.
*
* @param $code
* Coupon code to check.
*
* @return boolean
* Returns TRUE if the coupon exists, otherwise return FALSE.
*/
function commerce_coupon_code_exists($code) {
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', 'commerce_coupon')
->fieldCondition('commerce_coupon_code', 'value', $code, '=');
$result = $query
->execute();
if (empty($result)) {
return FALSE;
}
return TRUE;
}
/**
* Returns the number of uses for this coupon.
*
* @param $coupon_id
* Coupon id to check.
*
* @return integer
* Returns number of uses of the coupon in all orders.
*/
function commerce_coupon_get_number_of_uses($coupon_id) {
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', 'commerce_order')
->fieldCondition('commerce_coupon_order_reference', 'target_id', $coupon_id, '=');
return $query
->count()
->execute();
}
/**
* Finds out if a given coupon code is present in an order.
*
* @param $code
* Coupon code to check.
* @param $order
* Commerce order object.
*
* @return boolean
* Returns TRUE if the coupon is in the order, otherwise return FALSE.
*/
function commerce_coupon_code_is_in_order($code, $order) {
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
foreach ($order_wrapper->commerce_coupon_order_reference as $coupon_wrapper) {
if (strcasecmp($coupon_wrapper->commerce_coupon_code
->raw(), $code) == 0) {
return TRUE;
}
}
return FALSE;
}
/**
* Checks if a given coupon code is active or not.
*
* @param $code
* Coupon code to check.
* @return void
* Returns TRUE if it is active else FALSE
*/
function commerce_coupon_code_is_active($code) {
// @TODO: Replace this query with drupal 7 query API
$rs = db_query('SELECT * FROM {commerce_coupon} WHERE code = :code AND is_active = 1', array(
':code' => $code,
));
$codeObject = $rs
->fetchObject();
if ($codeObject == NULL) {
return FALSE;
}
return TRUE;
}
/**
* Implements hook_commerce_price_component_type_info().
*
* Creates a new price component for each coupon type.
*/
function commerce_coupon_commerce_price_component_type_info() {
$components = array();
$coupons = commerce_coupon_load_multiple(array(), array(
'is_active' => TRUE,
));
// Add a price component type per each coupon.
foreach ($coupons as $coupon) {
$name = commerce_coupon_type_get_name($coupon->type);
$coupon_machine_name = commerce_coupon_machine_name_code($coupon);
$components[$coupon->type . '_' . $coupon_machine_name] = array(
'title' => $name,
'display_title' => $name,
'coupon_type' => $coupon->type,
'coupon_code' => $coupon_machine_name,
);
}
return $components;
}
/**
* Generates a machine name for a coupon code.
*
* @param $coupon
* A commerce coupon object
* @retrun string
* A generated machine name for the coupon code.
*/
function commerce_coupon_machine_name_code($coupon) {
$coupon_code = $coupon->commerce_coupon_code[LANGUAGE_NONE][0]['value'];
// Set the pattern replacement to the default one that drupal uses for
// machine names.
// @see form_process_machine_name()
return preg_replace('/_+/', '_', preg_replace('/[^a-z0-9]/', '_', drupal_strtolower($coupon_code)));
}
/**
* Implements hook_commerce_line_item_type_info().
*/
function commerce_coupon_commerce_line_item_type_info() {
return array(
'commerce_coupon' => array(
'type' => 'commerce_coupon',
'name' => t('Coupon'),
'description' => t('Coupon line item.'),
'add_form_submit_value' => t('Add coupon'),
'base' => 'commerce_coupon_line_item',
),
);
}
/**
* Returns an appropriate title for this line item.
*/
function commerce_coupon_line_item_title($line_item) {
$line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
$fields = $line_item_wrapper
->getPropertyInfo();
if (isset($fields['commerce_coupon_reference']) && isset($line_item_wrapper->commerce_coupon_reference)) {
$coupon_wrapper = $line_item_wrapper->commerce_coupon_reference;
$coupon = $coupon_wrapper
->value();
if (!empty($coupon)) {
$type = commerce_coupon_get_types($coupon_wrapper
->value()->type);
if (is_object($type)) {
return $type->label . ': ' . $coupon_wrapper->commerce_coupon_code
->value();
}
}
}
return t('Coupon');
}
/**
* Creates a new coupon line item populated with the proper coupon values.
*
* @param $commerce_coupon
* The fully loaded coupon to add.
* @param $order_id
* Order to add this coupon.
*
* @return
* Line item object with default values.
*/
function commerce_coupon_line_item_new($coupon, $order_id) {
$coupon_wrapper = entity_metadata_wrapper('commerce_coupon', $coupon);
// Create the new line item.
$line_item = entity_create('commerce_line_item', array(
'type' => 'commerce_coupon',
'order_id' => $order_id,
'quantity' => 1,
));
$line_item->sku = $coupon->type . '_' . $coupon->coupon_id;
$line_item->line_item_label = $coupon->type . ': ' . $coupon_wrapper->commerce_coupon_code
->value();
$line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
$line_item_wrapper->commerce_coupon_reference = $coupon->coupon_id;
// Return the line item.
return $line_item_wrapper
->value();
}
/**
* Ensures the coupon line item type contains a coupon reference field.
*
* This function is called by the line item module when it is enabled or this
* module is enabled. It invokes this function using the configuration_callback
* as specified above.
*/
function commerce_coupon_line_item_configuration() {
$entity_type = 'commerce_line_item';
$bundle = 'commerce_coupon';
// Look for or add the specified coupon code
$field_name = 'commerce_coupon_reference';
$field = field_info_field($field_name);
$instance = field_info_instance($entity_type, $field_name, $bundle);
if (empty($field)) {
$field = commerce_coupon_reference_field($field_name, 1);
field_create_field($field);
}
if (empty($instance)) {
$instance = array(
'field_name' => $field_name,
'entity_type' => $entity_type,
'bundle' => $bundle,
'label' => t('Coupon'),
'required' => FALSE,
'settings' => array(),
'display' => array(),
'widget' => array(
'type' => 'entityreference_autocomplete',
'module' => 'entityreference',
),
);
field_create_instance($instance);
}
}
/**
* Implements hook_enable().
*/
function commerce_coupon_enable() {
// Add the coupon reference field to the order.
commerce_coupon_order_configuration();
}
/**
* Ensures the coupon reference field is present on the default order bundle.
*/
function commerce_coupon_order_configuration($type = 'commerce_order') {
// If a field type we know should exist isn't found, clear the Field cache.
if (!field_info_field_types('entityreference')) {
field_cache_clear();
}
// Look for or add a coupon reference field to the order type.
$field_name = 'commerce_coupon_order_reference';
$field = field_info_field($field_name);
$instance = field_info_instance('commerce_order', $field_name, $type);
if (empty($field)) {
$field = commerce_coupon_reference_field($field_name, FIELD_CARDINALITY_UNLIMITED);
field_create_field($field);
}
if (empty($instance)) {
$instance = array(
'field_name' => $field_name,
'entity_type' => 'commerce_order',
'bundle' => $type,
'label' => t('Coupon'),
'settings' => array(),
'widget' => array(
'type' => 'entityreference_autocomplete',
'module' => 'entityreference',
),
);
// Set the default display formatters for various view modes.
foreach (array(
'default',
'customer',
'administrator',
) as $view_mode) {
$instance['display'][$view_mode] = array(
'label' => 'hidden',
'type' => 'hidden',
);
}
field_create_instance($instance);
}
}
function commerce_coupon_reference_field($field_name, $cardinality) {
$field = array(
'field_name' => $field_name,
'type' => 'entityreference',
'cardinality' => $cardinality,
'entity_types' => array(
'commerce_order',
'commerce_line_item',
),
'module' => 'entityreference',
'translatable' => FALSE,
'settings' => array(
'target_type' => 'commerce_coupon',
'handler' => 'coupon',
'handler_settings' => array(),
),
);
return $field;
}
/**
* Implements hook_ctools_plugin_directory().
*/
function commerce_coupon_ctools_plugin_directory($module, $plugin) {
if ($module == 'entityreference' && $plugin == 'selection') {
return 'plugins/' . $plugin;
}
}
/**
* Implements hook_commerce_cart_order_refresh().
*
* If the coupon has been removed from the order somehow, keep consistency.
*/
function commerce_coupon_commerce_cart_order_refresh($order_wrapper) {
$order = $order_wrapper
->value();
$coupons = $order_wrapper->commerce_coupon_order_reference
->value();
foreach ($order_wrapper->commerce_line_items as $line_item_wrapper) {
$line_item = $line_item_wrapper
->value();
if ($line_item->type == 'commerce_coupon') {
$coupon = $line_item_wrapper->commerce_coupon_reference
->value();
if (!in_array($coupon, $coupons)) {
commerce_coupon_remove_coupon_from_order($order, $coupon);
}
}
}
}
/**
* Returns the number of uses for this coupon.
*
* @param $order_id
* Id from the Commerce order.
*
* @return integer
* Returns number of uses of the coupon in all orders.
*/
function commerce_coupon_get_coupons_in_order($order_id) {
$order_wrapper = entity_metadata_wrapper('commerce_order', $order_id);
$coupons = array();
foreach ($order_wrapper->commerce_coupon_order_reference as $coupon_wrapper) {
if ($coupon_wrapper
->value()->is_active == 1) {
$coupons[] = $coupon_wrapper
->value();
}
}
return $coupons;
}
/**
* Returns a list of coupons that have been attached to the order.
*
* @param $commerce_order
* The order which is to be checked.
* @return array
*/
function commerce_coupon_action_get_coupons_for_order($commerce_order) {
if (!$commerce_order) {
return array();
}
return array(
'order_coupons' => commerce_coupon_get_coupons_in_order($commerce_order->order_id),
);
}
Functions
Name | Description |
---|---|
commerce_coupon_access | Checks coupon access for various operations. |
commerce_coupon_action_get_coupons_for_order | Returns a list of coupons that have been attached to the order. |
commerce_coupon_can_delete | Determines whether or not the give coupon can be deleted. |
commerce_coupon_code_exists | Checks if a given coupon code exists. |
commerce_coupon_code_is_active | Checks if a given coupon code is active or not. |
commerce_coupon_code_is_in_order | Finds out if a given coupon code is present in an order. |
commerce_coupon_code_is_valid | Checks if a given coupon is valid for a given order. The validation is done by the rules engine. |
commerce_coupon_commerce_cart_order_refresh | Implements hook_commerce_cart_order_refresh(). |
commerce_coupon_commerce_checkout_pane_info | Implements hook_commerce_checkout_pane_info(). |
commerce_coupon_commerce_coupon_can_delete | Implements commerce_coupon_can_delete(). |
commerce_coupon_commerce_coupon_type_delete | Implements hook_commerce_coupon_type_delete(). |
commerce_coupon_commerce_line_item_type_info | Implements hook_commerce_line_item_type_info(). |
commerce_coupon_commerce_price_component_type_info | Implements hook_commerce_price_component_type_info(). |
commerce_coupon_create | Create a new coupon object. |
commerce_coupon_ctools_plugin_directory | Implements hook_ctools_plugin_directory(). |
commerce_coupon_delete | Deletes a coupon. |
commerce_coupon_delete_multiple | Delete multiple coupons. |
commerce_coupon_enable | Implements hook_enable(). |
commerce_coupon_entity_info | Implements hook_entity_info(). |
commerce_coupon_entity_info_alter | Implements hook_entity_info_alter(). |
commerce_coupon_generate_coupon_code | Generates a new unique coupon code. |
commerce_coupon_get_coupons_in_order | Returns the number of uses for this coupon. |
commerce_coupon_get_number_of_uses | Returns the number of uses for this coupon. |
commerce_coupon_get_properties | Callback for getting coupon properties. |
commerce_coupon_get_types | Gets an array of all coupon types, keyed by the type name. |
commerce_coupon_line_item_configuration | Ensures the coupon line item type contains a coupon reference field. |
commerce_coupon_line_item_new | Creates a new coupon line item populated with the proper coupon values. |
commerce_coupon_line_item_title | Returns an appropriate title for this line item. |
commerce_coupon_load | Fetch a coupon object. |
commerce_coupon_load_by_code | Loads a coupon by its coupon code. |
commerce_coupon_load_multiple | Load multiple coupons based on certain conditions. |
commerce_coupon_machine_name_code | Generates a machine name for a coupon code. |
commerce_coupon_order_configuration | Ensures the coupon reference field is present on the default order bundle. |
commerce_coupon_permission | Implements hook_permission(). |
commerce_coupon_redeem_coupon | Redeem a coupon. For calculating the coupon value the rules engine is used. |
commerce_coupon_reference_field | |
commerce_coupon_remove_all_coupons_from_order | Removes all coupons from a given order. references. |
commerce_coupon_remove_coupon_from_order | Removes a coupon from the order context. references. |
commerce_coupon_save | Saves a coupon. |
commerce_coupon_type_access | Access callback for coupon types. |
commerce_coupon_type_configure | Ensures a base price field is present on a coupon type bundle. |
commerce_coupon_type_create | Create a new type coupon object. |
commerce_coupon_type_delete | Deletes a coupon type. |
commerce_coupon_type_delete_multiple | Delete multiple coupon types. |
commerce_coupon_type_disable | Disables a coupon type and set as inactive all the coupons from the type. |
commerce_coupon_type_enable | Enables a coupon type. |
commerce_coupon_type_get_name | Returns the name of the specified coupon type or all names keyed by type if no type is specified. |
commerce_coupon_type_load | Menu argument loader; Load a coupon type by string. |
commerce_coupon_type_options_list | Wraps commerce_coupon_type_get_name() for the Entity module. |
commerce_coupon_type_save | Saves a coupon type to the database. |
commerce_coupon_views_api | Implements hook_views_api(). |