' . t('No mail will be sent to the user.') . '

'; case 'admin/store/search': return t('Use this search form to find transaction related information.'); } } /** * Implements hook_menu(). */ function ec_store_menu() { global $user; $items = array(); $store_settings = array(EC_PERM_SETTINGS); $store_report = array(EC_PERM_REPORT); $store_manage = array(EC_PERM_MANAGE); $items['store/transaction/%ec_store_transaction/view'] = array( 'title callback' => 'ec_store_transaction_t', 'title arguments' => array('View invoice @txnid', 2), 'description' => 'view an invoice', 'access callback' => 'ec_customer_check_access', 'access arguments' => array('transaction', 2), 'page callback' => 'ec_store_invoice', 'page arguments' => array(2), 'type' => MENU_CALLBACK, 'file' => 'ec_store.inc', ); $items['store/transaction/%ec_store_transaction/cancel'] = array( 'title callback' => 'ec_store_transaction_t', 'title arguments' => array('Cancel invoice @txnid', 2), 'description' => 'Cancel an invoice', 'access callback' => 'ec_customer_check_access', 'access arguments' => array('transaction', 2), 'page callback' => 'drupal_get_form', 'page arguments' => array('ec_store_invoice_cancel', 2), 'type' => MENU_CALLBACK, 'file' => 'ec_store.inc', ); $items['admin/store/transaction/product/view'] = array( 'title' => 'Admin items ordered', 'page callback' => 'ec_store_transaction_items', 'type' => MENU_CALLBACK, ); $items['admin/store/transaction/product/edit'] = array( 'title' => 'Edit transaction items', 'page callback' => 'ec_store_transaction_edit_items', 'type' => MENU_CALLBACK, ); $items['admin/config/store/store'] = array( 'title' => 'Store', 'description' => 'General settings for your e-Commerce installation. Store transaction notices. Email notifications. Behaviour of cart links.', 'page callback' => 'drupal_get_form', 'page arguments' => array('ec_store_ec_settings'), 'access arguments' => $store_settings, 'weight' => -1, 'file' => 'ec_store.admin.inc', ); $items['admin/config/store/store/default'] = array( 'title' => 'Default', 'type' => MENU_DEFAULT_LOCAL_TASK, 'access arguments' => $store_settings, ); $items['admin/config/store/store/location'] = array( 'title' => 'Location', 'description' => 'Location settings that may be used by modules such as shipping. Default country and units of measure.', 'page callback' => 'drupal_get_form', 'page arguments' => array('ec_store_location_settings_form'), 'access arguments' => $store_settings, 'file' => 'ec_store.localization.inc', 'type' => MENU_LOCAL_TASK, ); $items['admin/config/store/store/workflow'] = array( 'title' => 'Workflow', 'description' => 'Manage e-Commerce workflow statuses to allow better management of the purchases on the site.', 'page callback' => 'drupal_get_form', 'page arguments' => array('ec_store_workflow_settings'), 'access arguments' => $store_settings, 'file' => 'ec_store.admin.inc', 'type' => MENU_LOCAL_TASK, ); $items['admin/config/store/store/workflow/add'] = array( 'title' => 'Add workflow', 'page callback' => 'drupal_get_form', 'page arguments' => array('ec_store_workflow_settings_edit'), 'access arguments' => $store_settings, 'file' => 'ec_store.admin.inc', 'type' => MENU_LOCAL_ACTION, ); $items['admin/config/store/store/workflow/%/edit'] = array( 'title callback' => 'ec_store_workflow_settings_title', 'title arguments' => array(5), 'page callback' => 'drupal_get_form', 'page arguments' => array('ec_store_workflow_settings_edit', 5), 'access arguments' => $store_settings, 'file' => 'ec_store.admin.inc', 'type' => MENU_CALLBACK, ); $items['admin/config/store/store/workflow/%/delete'] = array( 'title callback' => 'ec_store_workflow_settings_title', 'title arguments' => array(5), 'page callback' => 'drupal_get_form', 'page arguments' => array('ec_store_workflow_settings_delete', 5), 'access arguments' => $store_settings, 'file' => 'ec_store.admin.inc', 'type' => MENU_CALLBACK, ); // Provide a flexible access transaction view url. $items['admin/store/transaction/view'] = array( 'title' => 'View transaction', 'type' => MENU_CALLBACK, ); return $items; } /** * Implements hook_entity_info(). */ function ec_store_entity_info() { return array( 'ec_transaction' => array( 'label' => t('Transaction'), 'base table' => 'ec_transaction', 'entity keys' => array( 'id' => 'txnid', ), 'load hook' => 'entity_transaction_load', ), ); } /** * Implements hook_theme(). */ function ec_store_theme() { return array( 'formatted_address' => array( 'variables' => array( 'address' => array(), 'include_name' => TRUE, ), 'pattern' => 'formatted_address__', 'template' => 'formatted-address', 'path' => drupal_get_path('module', 'ec_store') . '/templates', 'file' => 'theme.inc', ), 'invoice' => array( 'variables' => array('transaction' => array()), 'pattern' => 'invoice__', 'template' => 'invoice', 'path' => drupal_get_path('module', 'ec_store') . '/templates', 'file' => 'theme.inc', ), 'ec_store_format_address' => array( 'variables' => array( 'txn' => NULL, 'type' => 'shipping', 'html' => 'text', ), 'file' => 'ec_store.theme.inc', ), 'ec_store_workflow_settings' => array( 'render element' => 'form', 'file' => 'ec_store.theme.inc', ), ); } /** * Implements hook_views_api(). */ function ec_store_views_api() { return array('api' => 2.0); } /** * Implements hook_link(). */ function ec_store_link($type, $object = NULL, $teaser = FALSE) { $links = array(); if ($type == 'ec_customer_list') { $customer = & $object; $links['transactions'] = array( 'href' => 'admin/store/transaction', 'title' => t('Transactions'), 'query' => array( 'ecid' => $customer->ecid, ) ); } if ($type == 'ec_store_transaction') { $txn = & $object; $links['view_invoice'] = array( 'title' => t('View Invoice'), 'href' => 'store/transaction/' . $txn->txnid . '/view', ); if (ec_store_transaction_workflow('type_code', $txn->workflow) == EC_WORKFLOW_TYPE_IN_PROGRESS) { $links['cancel_invoice'] = array( 'title' => t('Cancel Invoice'), 'href' => 'store/transaction/' . $txn->txnid . '/cancel', 'query' => drupal_get_destination(), ); } } if ($type == 'ec_receipt') { $txnids = array(); $receipt = & $object; if (db_query("SELECT count(*) FROM {ec_receipt_allocation} WHERE type = :type AND erid = :erid GROUP BY etid", array(':type' => 'transaction', ':erid' => $receipt->erid))->fetchField()) { $links['ec_store_transactions'] = array( 'href' => 'admin/store/transaction', 'title' => t('View transactions'), 'query' => array( 'txnid' => $receipt->erid ), ); } } if ($type == 'ec_receipt_allocation') { $alloc = & $object; if ($alloc->type == 'transaction') { $links['view_invoice'] = array( 'title' => t('View Invoice'), 'href' => 'store/transaction/' . $alloc->etid . '/view', ); if (user_access(EC_PERM_MANAGE)) { $links['view_transaction'] = array( 'title' => t('View transaction'), 'href' => 'admin/store/transaction', 'query' => array( 'txnid' => $alloc->etid, ), ); } } } return $links; } /** * Implements hook_ec_transaction_load(). */ function ec_store_ec_transaction_load(&$txn) { if (empty($txn->mail)) { $txn->mail = ec_customer_get_email($txn->ecid); } $txn->misc = array(); $result = db_query('SELECT * FROM {ec_transaction_misc} WHERE txnid = :txnid ORDER BY weight ASC', array(':txnid' => $txn->txnid)); foreach ($result as $misc) { $txn->misc[] = $misc; } // Load Addressess. $txn->address = array(); $result = db_query('SELECT * FROM {ec_transaction_address} WHERE txnid = :txnid', array(':txnid' => $txn->txnid), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $address) { $txn->address[$address['type']] = $address; } // Load Fields $txn->fields = array(); $result = db_query('SELECT * FROM {ec_transaction_fields} WHERE txnid = :txnid', array(':txnid' => $txn->txnid), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $row) { $txn->fields[$row['name']] = $row['value']; } } /** * Implements hook_ec_transaction_insert(). */ function ec_store_ec_transaction_insert(&$txn) { _ec_store_ec_transaction_save($txn); } /** * Implements hook_ec_transaction_update(). */ function ec_store_ec_transaction_update(&$txn) { _ec_store_ec_transaction_save($txn); if (module_exists('search')) { db_update('search_dataset') ->fields(array( 'reindex' => REQUEST_TIME, )) ->condition('sid', $txn->txnid) ->condition('type', 'ec_transaction') ->execute(); } } /** * Helper function with common logic for inserting/updating transactions. */ function _ec_store_ec_transaction_save(&$txn) { module_load_include('inc', 'ec_store', 'ec_store'); ec_store_transaction_addresses_save($txn); if (isset($txn->misc)) { foreach ($txn->misc as $misc) { $misc->txnid = $txn->txnid; $misc->vid = isset($misc->vid) ? $misc->vid : 0; ec_store_transaction_save_misc($misc); } } db_delete('ec_transaction_fields') ->condition('txnid', $txn->txnid) ->execute(); if (isset($txn->fields)) { foreach ($txn->fields as $name => $value) { $record = array( 'txnid' => $txn->txnid, 'name' => $name, 'value' => $value, ); drupal_write_record('ec_transaction_fields', $record); } } } /** * Implements hook_ec_transaction_delete(). */ function ec_store_ec_transaction_delete(&$txn) { db_delete('ec_transaction_address') ->condition('txnid', $txn->txnid) ->execute(); db_delete('ec_transaction_misc') ->condition('txnid', $txn->txnid) ->execute(); db_delete('ec_transaction_fields') ->condition('txnid', $txn->txnid) ->execute(); } /** * Save a transaction to the database. * * @param $txn * Object, Transaction object to save. */ function ec_store_transaction_save($txn) { // @TODO: Remove this before final release if (is_array($txn)) { drupal_set_message(t('You have used a call to store_transaction_save that has passed the transaction as an array. This is deprecated. store_transaction save is converting to object but please look into converting your module to avoid this message.')); $txn = (object) $txn; } // Populate all the missing values with values from the existing transaction. // This also ensures that the current transaction is in the cache so we can // use it later. if (isset($txn->txnid)) { if ($existing = ec_store_transaction_load($txn->txnid)) { foreach ($existing as $key => $value) { if (!isset($txn->$key)) { $txn->$key = $value; } } } } else { $existing = new stdClass; } $txn->pass_by_ref = TRUE; rules_invoke_event('ec_store_event_transactions_bef_save', $txn, $existing); unset($txn->pass_by_ref); // Call any pre save hooks. ec_store_invoke_ec_transaction($txn, 'pre_save'); // If missing set changed time. if (empty($txn->changed)) { $txn->changed = REQUEST_TIME; } if (!empty($txn->txnid)) { drupal_write_record('ec_transaction', $txn, 'txnid'); ec_store_invoke_ec_transaction($txn, 'update'); } else { // Insert. If missing set created time to current time. if (empty($txn->created)) { $txn->created = REQUEST_TIME; } // If missing set workflow to default. if (empty($txn->workflow)) { $txn->workflow = 1; } drupal_write_record('ec_transaction', $txn); ec_store_invoke_ec_transaction($txn, 'insert'); } // Call any post save hooks. ec_store_invoke_ec_transaction($txn, 'post_save'); // Reset the cache so the next load will take this transaction from the // database and not the cache. ec_store_transaction_cache($txn->txnid, NULL, TRUE); // Call After transaction save event. $txn_save = clone $txn; rules_invoke_event('ec_store_event_transactions_save', $txn, $existing); return $txn->txnid; } /** * Save Miscellaneous transactions. */ function ec_store_transaction_save_misc($misc) { $misc_cache = & drupal_static(__FUNCTION__ . '_misc_cache', array()); if (empty($misc_cache[$misc->txnid])) { $result = db_query('SELECT type, vid FROM {ec_transaction_misc} WHERE txnid = :txnid', array(':txnid' => $misc->txnid)) ->fetchAll(); foreach ($result as $row) { $misc_cache[$misc->txnid][] = $row->type . '|' . $row->vid; } } if (isset($misc_cache[$misc->txnid]) && is_array($misc_cache[$misc->txnid]) && in_array("{$misc->type}|{$misc->vid}", $misc_cache[$misc->txnid])) { drupal_write_record('ec_transaction_misc', $misc, array('txnid', 'type', 'vid')); } else { drupal_write_record('ec_transaction_misc', $misc); $misc_cache[$misc->txnid][] = "$misc->type|$misc->vid"; } } /** * Implements hook_allocation_info(). */ function ec_store_allocation_info() { return array( 'transaction' => array( 'name' => t('e-Commerce transactions'), 'description' => t('Allocation interface for e-Commerce transactions.'), 'module' => array('ec_store'), 'file' => 'ec_store.alloc.inc', ), ); } /** * Implements hook_ec_transaction_post_save(). * * Check the transaction for changes in workflow and call hook_ec_txn_workflow() * to allow the module to update data outside of the transaction. */ function ec_store_ec_transaction_post_save(&$txn) { $orig_txn = ec_store_transaction_cache($txn->txnid); if (empty($orig_txn) || $orig_txn->allocation != $txn->allocation) { module_invoke_all('ec_txn_allocation', $txn, $orig_txn); } if (empty($orig_txn) || $orig_txn->workflow != $txn->workflow) { module_invoke_all('ec_txn_workflow', $txn, $orig_txn); } } /** * Invoke a hook_ec_transaction_[operation]() in all modules. * * @param &$txn * A transaction object. * @param $op * A string containing the name of the ec_transactionapi operation. * @param $a3, $a4 * Arguments to pass on to the hook, after the $txn and $op arguments. * @return * The returned value of the invoked hooks. */ function ec_store_invoke_ec_transaction(&$txn, $op, $a3 = NULL, $a4 = NULL) { $return = array(); foreach (module_implements('ec_transaction_' . $op) as $name) { $function = $name . '_ec_transaction_' . $op; $result = $function($txn, $a3, $a4); if (is_array($result)) { $return = array_merge($return, $result); } elseif (isset($result)) { $return[] = $result; } } return $return; } /** * Search for the Id of a country. */ function ec_store_get_country_id($name) { return array_search(drupal_strtolower($name), array_map('drupal_strtolower', ec_store_region_country_list())); } /** * Get the country name from the Id. */ function ec_store_get_country($id) { $country = ec_store_region_country_list(); return isset($country[$id]) ? $country[$id] : $id; } /** * Get a currently configured measure label. * * Pass 'weight' and 'KG' to get 'Kilograms'. If you leave $measure empty, the * saved value is used. * * @param $type * String, the measure type: weight, length, area or volume. * @param $measure * String, the measure value. * @return * String, the measure name. */ function ec_store_name_measure($type = 'weight', $measure = NULL) { module_load_include('inc', 'ec_store', 'ec_store.localization'); $all_measures = _ec_store_location_measures(); if (empty($measure)) { switch ($type) { case 'weight': $measure = variable_get('ec_measure_weight', 'LB'); break; case 'length': $measure = variable_get('ec_measure_length', 'IN'); break; case 'area': $measure = variable_get('ec_measure_area', 'IN2'); break; case 'volume': $measure = variable_get('ec_measure_volume', 'IN3'); break; default: watchdog('store', 'An unexpected measure type ' . $type . ' was encountered in ec_store_name_measure.', WATCHDOG_ERROR); return; } } return $all_measures[$type][$measure]; } /** * Sets the allocation state of the given transation to the state given. * This function accepts both the textual state and the numeric state. * If a textual state (valid values are in ec_store_transaction_workflow()) is * given it will be converted to the appropriate value. * * @param $txnid * Transaction ID. * @param $state * Either a textual or numeric state value. */ function ec_store_transaction_set_allocation($txnid, $state) { if (empty($state) || empty($txnid) || !is_numeric($txnid) || empty($txnid)) { return; } if (!is_numeric($state)) { $state = ec_store_transaction_get_allocation_id($state); } ec_store_transaction_save((object) array('txnid' => $txnid, 'allocation' => $state)); } /** * Sets the workflow state of the given transation to the state given. * * This function accepts both the textual state and the numeric state. If a * textual state (valid values are in ec_store_transaction_workflow()) is * given it will be converted to the appropriate value. * * @param $txnid * Transaction ID. * @param $state * Either a textual or numeric state value. */ function ec_store_transaction_set_workflow($txnid, $state) { if (empty($state) || empty($txnid) || !is_numeric($txnid) || empty($txnid)) { return; } if (!is_numeric($state)) { $state = ec_store_transaction_get_workflow_id($state); } ec_store_transaction_save((object) array('txnid' => $txnid, 'workflow' => $state)); } /** * Add all the invisible miscellaneous transaction to an item. */ function ec_store_adjust_misc(&$txn, $product) { $price = $product->price; if (isset($txn->misc)) { foreach ($txn->misc as $key => $misc) { if (!empty($misc->vid) && $misc->vid == $product->vid && $misc->invisible && (!isset($misc->displayonly) || !$misc->displayonly)) { $price += $misc->price; $txn->misc[$key]->seen = TRUE; } } } return $price; } /** * Recalculate product prices and associated charges on the transaction. * * While building a transaction, events may occur which will influence the * price of a product. An example of this is when a user logs into the system * becomming a registered user compared to being an anonymous user. If they a * member then the system may give discounts to the users on certain roles. * Also if a customer is purchasing a membership then the other products which * are on the transaction may also be eligible for discount. * Also in cases when the customer has made a purchase via the cart and has * not paid for the transaction, when the transaction is later paid for the * system should recalculate the transaction to allow for any price adjustments, * or removal of specials that no longer apply. * * @param $txn * The transaction which needs to be recalculated. */ function ec_store_recalc_transaction(&$txn) { $item_idx = array(); if (!empty($txn->items)) { foreach ($txn->items as $nid => $item) { // Reset price to original value. if ($node = node_load($item->nid)) { $txn->items[$nid]->price = $node->price; } $txn->items[$nid]->price = ec_product_price_adjust($txn->items[$nid], 'ec_cart', $txn); // Delete any current specials. if (!empty($txn->misc)) { foreach ($txn->misc as $key => $misc) { if ($misc->vid == $txn->items[$nid]->vid && $misc->description == 'special' && $misc->invisible) { unset($txn->misc[$key]); } } } // Process any specials and add them to misc. foreach (ec_product_specials_get($txn->items[$nid], 'cart', FALSE, $txn) as $type => $special) { $misc = new StdClass; $misc->type = $type; $misc->vid = $txn->items[$nid]->vid; $misc->description = 'special'; $misc->invisible = 1; $misc->price = $special; $misc->qty = ec_product_has_quantity($txn->items[$nid]) ? $txn->items[$nid]->qty : 1; $txn->misc[] = $misc; } $item_idx[$item->vid] = $nid; } } // Remove any misc items to products that have been deleted. if (!empty($txn->misc)) { foreach ($txn->misc as $key => $misc) { if (!empty($misc->vid) && $misc->description == 'special' && $misc->invisible && !isset($item_idx[$misc->vid])) { unset($txn->misc[$key]); } } } } /** * The purpose is to cache transactions in memory so that when loading the * same transaction more than once in the same session it will load from * memory instead of getting it from the database again. * * @param $txnid * The id for the transaction that is going to be stored or retrieved. * @param $txn * The transaction that needs to be saved. * @param $reset * Wipe the transaction from memory. * @return * The Transaction object from the $txnid. */ function ec_store_transaction_cache($txnid, $txn = NULL, $reset = FALSE) { $cache = & drupal_static(__FUNCTION__ . '_cache'); if ($reset) { unset($cache[$txnid]); return; } if (!empty($txn)) { $cache[$txnid] = clone $txn; } return isset($cache[$txnid]) ? clone $cache[$txnid] : FALSE; } /** * Calculate the total of the invoice. */ function ec_store_transaction_calc_gross($txn) { $total = 0; foreach ((array) $txn->items as $item) { $total += ec_product_has_quantity($item) ? $item->price * $item->qty : $item->price; } if (isset($txn->misc)) { foreach ($txn->misc as $key => $misc) { if (!empty($misc->callback) and function_exists($misc->callback)) { $f = $misc->callback; $amount = $f($txn, $misc, $total); } elseif (!empty($misc->qty)) { $amount = ($misc->price * $misc->qty); } else { $amount = $misc->price; } if (empty($misc->already_added) && (empty($misc->displayonly) || !$misc->displayonly)) { $total += $amount; } } } return $total; } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_transaction_cancel() { return drupal_get_form('ec_store_transaction_mail_form', arg(4), t('Cancel transaction notification'), MAILVAR_CANCEL_TXN, TRUE, TRUE); } /** * Load a transaction from database. * * @param $txnid * Transaction id of the transaction to be loaded. * @return * A fully-populated transaction object. */ function ec_store_transaction_load($txnid) { if ($txn = ec_store_transaction_cache($txnid)) { return $txn; } $txn = db_select('ec_transaction', 'st') ->fields('st') ->condition('st.txnid', $txnid) ->execute() ->fetchObject(); if (!$txn) { return FALSE; } if (isset($txn->additional)) { $txn->additional = unserialize($txn->additional); } if ($extra = ec_store_invoke_ec_transaction($txn, 'load')) { foreach ($extra as $key => $value) { $txn->$key = $value; } } ec_store_transaction_cache($txn->txnid, $txn); return $txn; } /** * Wrapper for ec_store_transaction_load() to allow it to work with entities. */ function ec_store_entity_transaction_load($txns) { foreach ($txns as $txnid => $txn) { $txns[$txnid] = ec_store_transaction_load($txnid); } } /** * Look for a miscellaneous items on a transaction. */ function ec_store_search_misc($needle, $txn) { if (!empty($txn->misc)) { foreach ($txn->misc as $key => $misc) { foreach ($needle as $k => $value) { if ($misc->$k != $value) { continue 2; } } return $key; } } return FALSE; } /** * Returns an array of allocation status IDs and corresponding descriptions. */ function ec_store_transaction_allocation() { return array( EC_ALLOC_PENDING => t('Pending'), EC_ALLOC_PART => t('Part'), EC_ALLOC_COMPLETED => t('Full'), ); } /** * Get the descriptive name of an allocation ID. */ function ec_store_transaction_get_allocation($id) { $allocation = ec_store_transaction_allocation(); return $allocation[$id]; } /** * Returns an array of workflow status IDs and corresponding descriptions. */ function ec_store_transaction_workflow($op = 'list', $type = NULL) { $workflow = & drupal_static(__FUNCTION__ . '_workflow', array()); $wf = & drupal_static(__FUNCTION__ . '_wf'); if (empty($workflow)) { $result = db_query('SELECT * FROM {ec_workflow_statuses} ORDER BY weight ASC', array(), array('fetch' => PDO::FETCH_ASSOC)); foreach ($result as $status) { $workflow[$status['workflow']] = $status; } $wf = array_map('_ec_store_transaction_workflow_map', $workflow); } if ($op == 'list') { return $wf; } elseif ($op == 'type_code') { if (isset($workflow[$type])) { return $workflow[$type]['type']; } return FALSE; } elseif ($op == 'type') { if (isset($workflow[$type])) { return $workflow[$type]; } return FALSE; } elseif ($op == 'types') { return $workflow; } } function _ec_store_transaction_workflow_map($a) { return $a['description']; } /** * Get the descriptive name of an workflow ID. */ function ec_store_transaction_get_workflow($id) { $workflow = ec_store_transaction_workflow(); return $workflow[$id]; } /** * Legacy, get a workflow ID by descriptive name. */ function ec_store_transaction_get_workflow_id($name) { return array_search(t($name), ec_store_transaction_workflow()); } /** * Legacy; determine if a passed workflow id is valid. */ function ec_store_transaction_valid_workflow($id) { return in_array($id, array_keys(ec_store_transaction_workflow())); } /** * Get a quick html header for printable pages. */ function ec_store_quicklist_header() { global $base_url; $base_url .= '/'; return '' . '' . '' . '' . '' . '' . '' . ''; } /** * Implements hook_rules_action_type_map(). */ function ec_store_rules_action_type_map() { return array( 'transaction' => array( 'module' => 'e-Commerce', 'arguments' => array( 'transaction' => array( 'label' => t('Transaction'), 'type' => 'transaction', ), ), ), ); } /** * Implements hook_object_info(). */ function ec_store_views_bulk_operations_object_info() { return array( 'transaction' => array( 'type' => 'transaction', 'base_table' => 'ec_transaction', 'load' => 'ec_store_transaction_load', 'title' => 'txnid', ), ); } /** * Implements hook_action_info(). */ function ec_store_action_info() { return array( 'ec_store_action_transaction_delete' => array( 'type' => 'ec_transaction', 'label' => t('Delete transaction'), 'configurable' => FALSE, 'triggers' => array( ), ), 'ec_store_action_set_allocation' => array( 'type' => 'ec_transaction', 'label' => t('Set transaction allocation status'), 'configurable' => TRUE, 'triggers' => array( 'ec_transactionapi_insert', 'ec_transactionapi_update', ), ), 'ec_store_action_set_workflow' => array( 'type' => 'ec_transaction', 'label' => t('Set transaction workflow status'), 'configurable' => TRUE, 'triggers' => array( 'ec_transactionapi_insert', 'ec_transactionapi_update', ), ), ); } /** * Action: Set transaction allocation. */ function ec_store_action_set_allocation($txn, $context = array()) { ec_store_transaction_set_allocation($txn->txnid, $context['allocation']); } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_action_set_allocation_form($edit = array()) { $form = array(); $edit += array('allocation' => ''); $form['allocation'] = array( '#type' => 'radios', '#title' => t('New allocation status'), '#default_value' => $edit['allocation'], '#options' => ec_store_transaction_allocation(), '#description' => t('Select the allocation that will be set by this action.'), ); return $form; } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_action_set_allocation_submit($form, &$form_state) { return array( 'allocation' => $form_state['values']['allocation'], ); } /** * Action: Set transaction workflow. */ function ec_store_action_set_workflow($txn, $context = array()) { ec_store_transaction_set_workflow($txn->txnid, $context['workflow']); } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_action_set_workflow_form($edit) { $form = array(); $form['workflow'] = array( '#type' => 'radios', '#title' => t('New workflow status'), '#default_value' => isset($edit['workflow']) ? $edit['workflow'] : NULL, '#options' => ec_store_transaction_workflow(), '#description' => t('Select the workflow that will be set by this action.'), ); return $form; } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_action_set_workflow_submit($form, &$form_state) { return array( 'workflow' => $form_state['values']['workflow'], ); } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_action_transaction_delete($txn, &$context) { if (user_access('delete transaction')) { module_load_include('inc', 'ec_store', 'ec_store.manage'); ec_store_transaction_delete($context['transaction']->txnid); } else { $context = FALSE; } } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_workflow_settings_title($workflowid) { $workflow = ec_store_transaction_workflow(); return drupal_ucfirst($workflow[$workflowid]); } /** * Implements hook_ec_charge_default_variables(). */ function ec_store_ec_charge_default_variables($type, $object) { $$type = & $object; $variables = array(); if (!$object) { return; } switch ($type) { case 'txn': $txn = clone $txn; $variables['gross'] = ec_store_transaction_calc_gross($txn); $variables['subtotal'] = 0; foreach ($txn->items as $nid => $item) { $variables['subtotal'] += ec_store_adjust_misc($txn, $item) * ec_product_check_qty($item, $item->qty); } break; } return $variables; } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_ec_charge_default_variables_description($type, $object, $variables) { switch ($type) { case 'txn': return array( 'gross' => t('Total values of the transaction'), 'subtotal' => t('The total value of the products'), ); break; } } /** * Implements hook_update_index(). */ function ec_store_update_index() { $limit = (int) variable_get('search_cron_limit', 100); $result = db_query_range("SELECT t.txnid FROM {ec_transaction} t LEFT JOIN {search_dataset} d ON d.type = 'ec_transacton' AND d.sid = t.txnid WHERE d.sid IS NULL OR d.reindex <> :d.reindex ORDER BY d.reindex ASC, t.txnid ASC", 0, $limit, array(':d.reindex' => 0)); foreach ($result as $txn) { $txn = ec_store_transaction_load($txn->txnid); $text = theme('invoice', array('transaction' => $txn)); search_index($txn->txnid, 'ec_transaction', $text); } } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_filter_misc($item, $init = 'process') { $params = & drupal_static(__FUNCTION__ . '_params'); if ($init == 'init') { $params = $item; } if (is_array($params)) { foreach ($params as $key => $value) { if (is_object($item) && ($item->$key != $value)) { return FALSE; } elseif (is_array($item) && ($item[$key] != $value)) { return FALSE; } } } return TRUE; } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_map_price($item) { return $item->price; } /** * Implements hook_checkout_info(). */ function ec_store_checkout_info() { return array( 'fields' => array( 'name' => t('Fields'), 'description' => t('Implements fields into the checkout process.'), 'module' => 'ec_store_fields', 'file' => 'ec_store.checkout.inc', 'weight' => 99, ), ); } /** * Implements hook_ec_charge_filter_info(). */ function ec_store_ec_charge_filter_info() { return array( 'misc_group' => array( 'name' => t('Charge Group'), 'description' => t('Allow filters to determine if there are an miscellaneous charges with a defined charge group.'), 'module' => 'ec_store_misc_group', 'file' => 'ec_store.charge.inc', ), 'txn_type' => array( 'name' => t('Transaction type'), 'description' => t('Allow the filtering of changes based upon the transaction type'), 'module' => 'ec_store_txn_type', 'file' => 'ec_store.charge.inc', ), 'field' => array( 'name' => t('Field'), 'description' => t('allow filtering based upon the value of a field.'), 'module' => 'ec_store_fields', 'file' => 'ec_store.charge.inc', ), 'address' => array( 'name' => t('Address'), 'description' => t('Allow filtering based upon the address information.'), 'module' => 'ec_store_address', 'file' => 'ec_store.charge.inc', ), ); } /** * Implements hook_ec_charge_variable_info(). */ function ec_store_ec_charge_variable_info() { return array( 'misc_group' => array( 'name' => t('Charge Group'), 'description' => t('Allow filters to determine if there are an miscellaneous charges with a defined charge group.'), 'module' => 'ec_store_misc_group', 'file' => 'ec_store.charge.inc', ), ); } /** * @todo Please document this function. * @see http://drupal.org/node/1354 */ function ec_store_transaction_t($title, $txn) { $values = array_filter((array) $txn, 'is_scalar'); return t($title, ec_build_arguments($values)); } /** * Calculate balance of receipts allocated for the transaction. * * @param $txnid * Transaction id. * @return * Transaction balance. */ function ec_store_transaction_balance($txnid) { $txns = & drupal_static(__FUNCTION__ . '_txns', array()); if (!isset($txns[$txnid])) { $txns[$txnid] = db_query("SELECT SUM(amount) FROM {ec_receipt_allocation} WHERE type = :type AND etid = :etid", array(':type' => 'transaction', ':etid' => $txnid))->fetchField(); } return $txns[$txnid]; } /** * Return a list of implemented transaction types. * * @return * Associative array with available transaction types where key is the machine * readable name and value is human readable one. */ function ec_store_transaction_types() { $types = & drupal_static(__FUNCTION__ . '_types'); if (!isset($types)) { $types = module_invoke_all('ec_transaction_types'); } return $types; } /** * Get Region info */ function ec_store_get_region_info($country = NULL, $fields = NULL) { $included = & drupal_static(__FUNCTION__ . '_included'); $regions = & drupal_static('ec_store_get_region_info_regions'); if ($fields) { _ec_store_map_region_fields($fields, TRUE); } $default = array( // Measures 'weight' => 'KG', 'length' => 'M', 'area' => 'M2', 'volume' => 'M3', 'state_name' => t('State/Province'), 'use_state_names' => FALSE, 'zip' => TRUE, 'zip_name' => t('Zip/Postcode'), 'payment_symbol' => '$', 'payment_symbol_position' => 1, // Left 'payment_thousands' => ',', 'payment_decimal' => '.', 'payment_decimal_places' => 2, ); if (!$included) { module_load_include('inc', 'ec_store', 'ec_store.region'); $included = TRUE; } if (1) { $include_list = ec_store_region_build_include_list(); if ($country) { $country = drupal_strtolower($country); if (isset($include_list[$country])) { @include_once($include_list[$country]); $function = 'ec_store_ec_region_' . $country . '_info'; if (function_exists($function)) { $info = call_user_func($function); } } $info = isset($info) && is_array($info) ? $info : array(); return $fields ? _ec_store_map_region_fields($info + $default) : $info + $default; } else { $regions = array(); foreach (ec_store_region_country_list() as $country => $name) { unset($info); $country = drupal_strtolower($country); if (isset($include_list[$country])) { @include_once($include_list[$country]); $function = 'ec_store_ec_region_' . $country . '_info'; if (function_exists($function)) { $info = call_user_func($function); } } $info['name'] = $name; $regions[drupal_strtoupper($country)] = (isset($info) && is_array($info) ? $info : array()) + $default; } return $fields ? array_map('_ec_store_map_region_fields', $regions) : $regions; } } } function _ec_store_map_region_fields($a, $init = FALSE) { static $fields; if ($init) { $fields = array_flip($a); return; } return array_intersect_key($a, $fields); } /** * */ function ec_store_region_country_list() { $included = & drupal_static('ec_store_get_region_info_included'); if (!$included) { module_load_include('inc', 'ec_store', 'ec_store.region'); $included = TRUE; } return _ec_store_region_country_list(); } /** * Implements hook_ctools_plugin_directory(). */ function ec_store_ctools_plugin_directory($module, $plugin) { if ($module == 'ctools' && $plugin == 'export_ui') { return 'plugins/' . $plugin; } elseif ($module == 'ec_store' && $plugin == 'ec_fields') { return 'plugins/' . $plugin; } } function ec_store_get_field_plugins($id = NULL) { ctools_include('plugins'); return ctools_get_plugins('ec_store', 'ec_fields', $id); } function ec_store_get_all_fields($enabled = TRUE) { ctools_include('export'); $fields = ctools_export_crud_load_all('ec_fields'); if ($enabled) { $fields = array_filter($fields, '_ec_store_filter_enabled_fields'); } return $fields; } function _ec_store_filter_enabled_fields($a) { return !isset($a->disabled) || !$a->disabled; }