0) { $this->uid = $uid; if ($account = user_load($uid)) { $this->primary_email = $account->mail; } } $this->order_status = uc_order_state_default($state); $this->currency = variable_get('uc_currency_code', 'USD'); $this->billing_country = variable_get('uc_store_country', 840); $this->delivery_country = variable_get('uc_store_country', 840); $this->created = REQUEST_TIME; $this->modified = REQUEST_TIME; } } /** * Implements hook_help(). */ function uc_order_help($path, $arg) { switch ($path) { case 'admin/store/settings/orders/products/fields': return '
' . t('Attach fields to order product entities. These entities represent the product line items that appear in orders. Fields attached here are not visible in the current version of Ubercart, but they are available in Views. A ') . l(t('Computed Field'), 'http://drupal.org/project/computed_field') . t(' is useful for attaching custom data to each product as it is ordered.') . '
'; } } /** * Implements hook_menu(). */ function uc_order_menu() { global $user; $items = array(); $items['admin/store/customers'] = array( 'title' => 'Customers', 'description' => 'View and search customer information.', 'page callback' => 'uc_order_customers', 'access arguments' => array('view customers'), 'weight' => -6, 'position' => 'left', 'file' => 'uc_order.admin.inc', ); // admin/store/customers/view is provided by Views. // admin/store/customers/orders/% is provided by Views. $items['admin/store/settings/orders'] = array( 'title' => 'Orders', 'description' => 'Configure the display and workflow for orders.', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_order_settings_form'), 'access arguments' => array('administer store'), 'file' => 'uc_order.admin.inc', ); $items['admin/store/settings/orders/settings'] = array( 'title' => 'Settings', 'description' => 'Edit the basic order settings.', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); $items['admin/store/settings/orders/workflow'] = array( 'title' => 'Workflow', 'description' => 'Modify and configure order states and statuses.', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_order_workflow_form'), 'access arguments' => array('administer order workflow'), 'type' => MENU_LOCAL_TASK, 'weight' => -8, 'file' => 'uc_order.admin.inc', ); $items['admin/store/settings/orders/workflow/create'] = array( 'title' => 'Create custom order status', 'description' => 'Create a custom order status for your store.', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_order_status_create_form'), 'access arguments' => array('administer order workflow'), 'type' => MENU_LOCAL_ACTION, 'file' => 'uc_order.admin.inc', ); $items['admin/store/orders'] = array( 'title' => 'Orders', 'description' => 'View and process orders.', 'page callback' => 'uc_order_orders', 'access arguments' => array('view all orders'), 'weight' => -10, 'position' => 'left', 'file' => 'uc_order.admin.inc', ); // admin/store/orders/view is provided by Views. $items['admin/store/orders/create'] = array( 'title' => 'Create order', 'description' => 'Create an empty new order.', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_order_create_form'), 'access arguments' => array('create orders'), 'weight' => -5, 'file' => 'uc_order.admin.inc', ); $items['admin/store/orders/create/%user'] = array( 'title' => 'Create order for this customer', 'description' => 'Create an empty new order.', 'page callback' => 'uc_order_create_for_user', 'page arguments' => array(4), 'access arguments' => array('create orders'), 'file' => 'uc_order.admin.inc', ); // admin/store/orders/search is provided by Views. $items['admin/store/orders/address_book'] = array( 'title' => 'Select address', 'page callback' => 'uc_order_address_book', 'access arguments' => array('edit orders'), 'type' => MENU_CALLBACK, 'file' => 'uc_order.admin.inc', ); $items['admin/store/orders/customer'] = array( 'title' => 'Select customer', 'page callback' => 'uc_order_select_customer', 'page arguments' => array(NULL), 'access arguments' => array('edit orders'), 'type' => MENU_CALLBACK, 'file' => 'uc_order.admin.inc', ); // user/%/orders is provided by Views. $items['user/%user/orders/%uc_order'] = array( 'title callback' => 'uc_order_page_title', 'title arguments' => array(3), 'description' => 'View order.', 'page callback' => 'uc_order_view', 'page arguments' => array(3, 'customer'), 'access callback' => 'uc_order_can_view_order', 'access arguments' => array(1, 3), ); $items['user/%user/orders/%uc_order/invoice'] = array( 'title' => 'View invoice', 'description' => 'View order invoice.', 'page callback' => 'uc_order_view_invoice', 'page arguments' => array(3), 'access callback' => 'uc_order_can_view_order', 'access arguments' => array(1, 3, TRUE), ); $items['user/%user/orders/%uc_order/print'] = array( 'title' => 'Print invoice', 'description' => 'Print order invoice.', 'page callback' => 'uc_order_view_invoice', 'page arguments' => array(3, TRUE), 'access callback' => 'uc_order_can_view_order', 'access arguments' => array(1, 3, TRUE), ); $items['admin/store/orders/%uc_order'] = array( 'title callback' => 'uc_order_page_title', 'title arguments' => array(3), 'description' => 'View order', 'page callback' => 'uc_order_view', 'page arguments' => array(3, 'view'), 'access arguments' => array('view all orders'), 'file' => 'uc_order.admin.inc', ); $items['admin/store/orders/%uc_order/view'] = array( 'title' => 'View', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); $items['admin/store/orders/%uc_order/edit'] = array( 'title' => 'Edit', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_order_edit_form', 3), 'access arguments' => array('edit orders'), 'type' => MENU_LOCAL_TASK, 'weight' => 1, 'file' => 'uc_order.admin.inc', ); $items['admin/store/orders/%uc_order/add_line_item/%'] = array( 'title' => 'Add a line item', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_order_add_line_item_form', 3, 5), 'access arguments' => array('edit orders'), 'type' => MENU_CALLBACK, 'file' => 'uc_order.admin.inc', ); $items['admin/store/orders/%uc_order/invoice'] = array( 'title' => 'Invoice', 'page callback' => 'uc_order_view_invoice', 'page arguments' => array(3), 'access arguments' => array('view all orders'), 'type' => MENU_LOCAL_TASK, 'weight' => 3, ); $items['admin/store/orders/%uc_order/invoice/view'] = array( 'title' => 'View invoice', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); $items['admin/store/orders/%uc_order/invoice/print'] = array( 'title' => 'Printable invoice', 'page arguments' => array(3, TRUE), 'access arguments' => array('view all orders'), 'type' => MENU_LOCAL_TASK, 'weight' => -5, ); $items['admin/store/orders/%uc_order/invoice/mail'] = array( 'title' => 'Mail invoice', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_order_mail_invoice_form', 3), 'access arguments' => array('view all orders'), 'type' => MENU_LOCAL_TASK, 'weight' => 0, 'file' => 'uc_order.admin.inc', ); $items['admin/store/orders/%uc_order/log'] = array( 'title' => 'Log', 'page callback' => 'uc_order_log', 'page arguments' => array(3), 'access arguments' => array('view all orders'), 'type' => MENU_LOCAL_TASK, 'weight' => 10, 'file' => 'uc_order.admin.inc', ); $items['admin/store/orders/%uc_order/delete'] = array( 'title' => 'Delete an order', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_order_delete_confirm_form', 3), 'access callback' => 'uc_order_can_delete', 'access arguments' => array(3), 'file' => 'uc_order.admin.inc', ); return $items; } /** * Implements hook_menu_alter(). */ function uc_order_menu_alter(&$items) { // Adjust the Field UI tabs on admin/store/settings/orders. $items['admin/store/settings/orders/products/fields']['title'] = 'Ordered product fields'; $items['admin/store/settings/orders/products/fields']['weight'] = 3; // Disable field display settings for ordered products, // as we don't use this anywhere (yet). $items['admin/store/settings/orders/products/display']['access callback'] = FALSE; } /** * Implements hook_menu_local_tasks_alter(). */ function uc_order_menu_local_tasks_alter(&$data, $router_item, $root_path) { if ($root_path == 'admin/store/customers/orders/%') { $uid = $router_item['page_arguments'][0]; $item = menu_get_item('admin/store/orders/create/' . $uid); if ($item['access']) { $data['actions']['output'][] = array( '#theme' => 'menu_local_action', '#link' => $item, ); } } } /** * Title callback for admin/store/orders/%uc_order. */ function uc_order_page_title($order) { return t('Order @order_id', array('@order_id' => $order->order_id)); } /** * Implements hook_admin_paths(). */ function uc_order_admin_paths() { return array( // Don't show invoices with the admin theme, overlay, etc. 'admin/store/orders/*/invoice*' => FALSE, ); } /** * Implements hook_init(). */ function uc_order_init() { // Load uc_order.js on all order and customer admin pages. if (arg(0) == 'admin' && arg(1) == 'store' && (arg(2) == 'orders' || arg(2) == 'customers')) { drupal_add_js(array( 'ucURL' => array( 'adminOrders' => url('admin/store/orders/'), ), ), 'setting'); drupal_add_js(drupal_get_path('module', 'uc_order') . '/uc_order.js'); } } /** * Implements hook_theme(). */ function uc_order_theme($existing, $type, $theme, $path) { $theme_hooks = array( 'uc_order' => array( 'template' => 'uc-order', 'path' => $path . '/templates', 'variables' => array( 'order' => NULL, 'op' => 'view', 'template' => 'customer', 'thank_you_message' => FALSE, 'help_text' => FALSE, 'email_text' => FALSE, 'store_footer' => FALSE, 'business_header' => FALSE, 'shipping_method' => FALSE, ), ), 'uc_order_invoice_page' => array( 'variables' => array('content' => NULL), 'template' => 'uc_order-invoice-page', ), 'uc_order_state_table' => array( 'render element' => 'form', 'file' => 'uc_order.admin.inc', ), 'uc_order_status_table' => array( 'render element' => 'form', 'file' => 'uc_order.admin.inc', ), 'uc_order_edit_form' => array( 'render element' => 'form', 'file' => 'uc_order.admin.inc', ), 'uc_order_pane_line_items' => array( 'render element' => 'form', 'file' => 'uc_order.order_pane.inc', ), ); $theme_hooks += array( 'uc_order__customer' => array( 'template' => 'uc-order--customer', 'path' => $path . '/templates', 'variables' => $theme_hooks['uc_order']['variables'], ), 'uc_order__admin' => array( 'template' => 'uc-order--admin', 'path' => $path . '/templates', 'variables' => $theme_hooks['uc_order']['variables'], ), ); return $theme_hooks; } /** * Implements hook_permission(). */ function uc_order_permission() { return array( 'administer order workflow' => array( 'title' => t('Administer order workflow'), ), 'view customers' => array( 'title' => t('View customers'), ), 'view own orders' => array( 'title' => t('View own orders'), ), 'view own invoices' => array( 'title' => t('View own invoices'), ), 'view all orders' => array( 'title' => t('View all orders'), ), 'create orders' => array( 'title' => t('Create orders'), ), 'edit orders' => array( 'title' => t('Edit orders'), ), 'delete orders' => array( 'title' => t('Delete orders'), ), 'unconditionally delete orders' => array( 'title' => t('Unconditionally delete orders'), ), ); } /** * Access callback for user/%user/orders*. */ function uc_order_can_view_order($account, $order, $view_invoice = FALSE) { global $user; // Users with 'view all orders' are straightforward. $access = user_access('view all orders'); // If the user is the current user and is not anonymous, // also allow the "own" permissions. if ($user->uid && $user->uid == $account->uid) { if ($view_invoice) { $access = $access || user_access('view own invoices'); } else { $access = $access || user_access('view own orders'); } } // The order must also be owned by the user specified in the URL. $access = $access && $account->uid == $order->uid; return $access; } /** * Implements hook_query_TAG_alter(). */ function uc_order_query_uc_order_access_alter(QueryAlterableInterface $query) { global $user; // Read metadata from query, if provided. if (!$account = $query->getMetaData('account')) { $account = $user; } // If account can view all orders, we don't need to alter the query. if (user_access('view all orders', $account)) { return; } if (user_access('view own orders', $account)) { // Only allow the user to see their own orders. foreach ($query->getTables() as $table) { if ($table['table'] === 'uc_orders') { $query->condition($table['alias'] . '.uid', $account->uid); } } } else { // Deny access to everything. $query->where('1 = 0'); } } /** * Implements hook_entity_info(). */ function uc_order_entity_info() { return array( 'uc_order' => array( 'label' => t('Order'), 'controller class' => 'UcOrderController', 'base table' => 'uc_orders', 'fieldable' => TRUE, 'entity keys' => array( 'id' => 'order_id', ), 'bundles' => array( 'uc_order' => array( 'label' => t('Order'), 'admin' => array( 'path' => 'admin/store/settings/orders', 'access arguments' => array('administer store'), ), ), ), 'view modes' => array( 'view' => array( 'label' => t('Admin view'), ), 'customer' => array( 'label' => t('Customer view'), ), ), 'uri callback' => 'uc_order_uri', // Entity API callbacks. 'access callback' => 'uc_order_order_entity_access', 'creation callback' => 'uc_order_create', 'save callback' => 'uc_order_save', 'deletion callback' => 'uc_order_delete', ), 'uc_order_product' => array( 'label' => t('Order product'), 'base table' => 'uc_order_products', 'controller class' => 'UcOrderProductController', 'metadata controller class' => 'UcOrderProductMetadataController', 'fieldable' => TRUE, 'module' => 'uc_order', 'entity keys' => array( 'id' => 'order_product_id', ), 'bundles' => array( 'uc_order_product' => array( 'label' => t('Order product'), 'admin' => array( 'path' => 'admin/store/settings/orders/products', 'access arguments' => array('administer store'), ), ), ), 'view modes' => array( 'full' => array( 'label' => t('Normal view'), ), 'cart' => array( 'label' => t('Cart view'), ), ), // Entity API callbacks. 'access callback' => 'uc_order_order_product_access', ), ); } /** * Implements hook_field_extra_fields(). */ function uc_order_field_extra_fields() { $panes = module_invoke_all('uc_order_pane'); $extra = array(); foreach ($panes as $id => $pane) { $extra_field = array( 'label' => $pane['title'], 'description' => $pane['desc'], 'weight' => $pane['weight'], ); if (in_array('edit', $pane['show'])) { $extra['uc_order']['uc_order']['form'][$id] = $extra_field; } if (in_array('view', $pane['show']) || in_array('customer', $pane['show'])) { $extra['uc_order']['uc_order']['display'][$id] = $extra_field; } } return $extra; } /** * Implements hook_user_view(). */ function uc_order_user_view($account, $view_mode) { global $user; if ($user->uid && (($user->uid == $account->uid && user_access('view own orders')) || user_access('view all orders'))) { $account->content['summary']['orders'] = array( '#type' => 'user_profile_item', '#title' => t('Orders'), '#markup' => l(t('Click here to view your order history.'), 'user/' . $account->uid . '/orders'), ); } } /** * Implements hook_mail(). */ function uc_order_mail($key, &$message, $params) { $langcode = isset($message['language']) ? $message['language']->language : NULL; // Build the appropriate message parameters based on the e-mail key. switch ($key) { // Setup an e-mailed invoice. case 'invoice': $message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed'; $message['subject'] = t('Your Order Invoice', array(), array('langcode' => $langcode)); $message['from'] = uc_store_email_from(); $message['body'][] = theme('uc_order', array('order' => $params['order'], 'op' => 'admin-mail', 'template' => variable_get('uc_cust_order_invoice_template', 'customer'))); break; // Setup a custom e-mail defined by an action on a predicate. case 'action-mail': // Assemble an email message from the conditional actions settings. $message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed'; $message['from'] = $params['from']; // Perform token replacement on the subject and body. $subject = token_replace($params['subject'], $params['replacements'], $langcode ? array('language' => $message['language']) : array()); $body = token_replace($params['message'], $params['replacements'], $langcode ? array('language' => $message['language']) : array()); // Strip newline characters from e-mail subjects. // @todo: Maybe drupal_mail_send() should do this? $message['subject'] = str_replace(array("\r\n", "\r", "\n"), ' ', $subject); // Apply an input format to the message body if specified. if (isset($params['format'])) { $message['body'] = explode("\n", check_markup($body, $params['format'], $langcode)); } else { $message['body'] = explode("\n", $body); } break; } } /** * Implements hook_views_api(). */ function uc_order_views_api() { return array( 'api' => '2.0', 'path' => drupal_get_path('module', 'uc_order') . '/views', ); } /** * Implements hook_form_FORM_ID_alter() for views_exposed_form(). */ function uc_order_form_views_exposed_form_alter(&$form, &$form_state) { if (substr($form['#id'], 0, 29) == 'views-exposed-form-uc-orders-') { $form['#submit'][] = 'uc_order_form_views_exposed_form_submit'; if ($form['#id'] == 'views-exposed-form-uc-orders-search' && !module_exists('date_views')) { drupal_set_message(t('Download the Date module and enable Date Views to allow searching orders by date.', array('@url' => 'http://drupal.org/project/date')), 'warning'); } } } /** * Redirects if an order ID was entered in the exposed field. */ function uc_order_form_views_exposed_form_submit($form, &$form_state) { if (!empty($form_state['values']['order_id']) && uc_order_exists($form_state['values']['order_id'])) { $form_state['redirect'] = 'admin/store/orders/' . $form_state['values']['order_id']; $form_state['no_redirect'] = FALSE; } } /** * Implements hook_form_FORM_ID_alter() for uc_store_settings_form(). */ function uc_order_form_uc_store_settings_form_alter(&$form, &$form_state) { $form['display']['uc_order_capitalize_addresses'] = array( '#type' => 'checkbox', '#title' => t('Capitalize address on order screens'), '#default_value' => variable_get('uc_order_capitalize_addresses', TRUE), ); } /** * Implements hook_uc_order_pane(). */ function uc_order_uc_order_pane() { $panes['print_button'] = array( 'callback' => 'uc_order_pane_print_button', 'title' => t('Print button'), 'display title' => '', 'desc' => t("Button to open a printable invoice."), 'class' => 'abs-left', 'weight' => -10, 'show' => array('customer'), ); $panes['ship_to'] = array( 'callback' => 'uc_order_pane_ship_to', 'title' => t('Ship to'), 'desc' => t("Manage the order's shipping address and contact information."), 'class' => 'pos-left', 'weight' => 1, 'show' => array('view', 'edit', 'customer'), ); $panes['bill_to'] = array( 'callback' => 'uc_order_pane_bill_to', 'title' => t('Bill to'), 'desc' => t("Manage the order's billing address and contact information."), 'class' => 'pos-left', 'weight' => 2, 'show' => array('view', 'edit', 'customer'), ); $panes['customer'] = array( 'callback' => 'uc_order_pane_customer', 'title' => t('Customer info'), 'desc' => t("Manage the information for the customer's user account."), 'class' => 'pos-left', 'weight' => 3, 'show' => array('view', 'edit'), ); $panes['products'] = array( 'callback' => 'uc_order_pane_products', 'title' => t('Products'), 'desc' => t('Manage the products an order contains.'), 'class' => 'abs-left', 'weight' => 5, 'show' => array('view', 'edit', 'customer'), ); $panes['line_items'] = array( 'callback' => 'uc_order_pane_line_items', 'title' => t('Line items'), 'display title' => '', 'desc' => t("View and modify an order's line items."), 'class' => 'abs-left', 'weight' => 6, 'show' => array('view', 'edit', 'customer'), ); $panes['order_comments'] = array( 'callback' => 'uc_order_pane_order_comments', 'title' => t('Order comments'), 'desc' => t('View the order comments, used for communicating with customers.'), 'class' => 'abs-left', 'weight' => 8, 'show' => array('view', 'customer'), ); $panes['admin_comments'] = array( 'callback' => 'uc_order_pane_admin_comments', 'title' => t('Admin comments'), 'desc' => t('View the admin comments, used for administrative notes and instructions.'), 'class' => 'abs-left', 'weight' => 9, 'show' => array('view', 'edit'), ); $panes['update'] = array( 'callback' => 'uc_order_pane_update', 'title' => t('Update order'), 'desc' => t("Update an order's status or add comments to an order."), 'class' => 'abs-left', 'weight' => 10, 'show' => array('view'), ); return $panes; } /** * Implements hook_uc_order_state(). */ function uc_order_uc_order_state() { $states['canceled'] = array( 'title' => t('Canceled'), 'weight' => -20, 'scope' => 'specific', ); $states['in_checkout'] = array( 'title' => t('In checkout'), 'weight' => -10, 'scope' => 'specific', ); $states['post_checkout'] = array( 'title' => t('Post checkout'), 'weight' => 0, 'scope' => 'general', ); $states['completed'] = array( 'title' => t('Completed'), 'weight' => 20, 'scope' => 'general', ); return $states; } /** * Implements hook_uc_line_item(). */ function uc_order_uc_line_item() { $items['subtotal'] = array( 'title' => t('Subtotal'), 'weight' => 0, 'stored' => FALSE, 'calculated' => FALSE, 'callback' => 'uc_line_item_subtotal', ); $items['generic'] = array( 'title' => t('Empty line'), 'weight' => 2, 'stored' => TRUE, 'add_list' => TRUE, 'calculated' => TRUE, 'callback' => 'uc_line_item_generic', ); $items['total'] = array( 'title' => t('Total'), 'weight' => 15, 'stored' => FALSE, 'calculated' => FALSE, 'display_only' => TRUE, 'callback' => 'uc_line_item_total', ); return $items; } /** * Implements hook_uc_message(). */ function uc_order_uc_message() { $messages['order_update_email'] = t("[order:first-name] [order:last-name],\n\nYour order number [order:link] at [store:name] has been updated.\n\nOrder status: [order:order-status]\n\nOrder comment:\n[order:last-comment]\n\nBrowse to the following page to login to your account and view your order details:\n[site:login-link]\n\n\nThanks again,\n\n[store:name]\n[site:slogan]"); return $messages; } /** * Implements hook_uc_invoice_templates(). */ function uc_order_uc_invoice_templates() { return array('admin', 'customer'); } /** * Entity API "uri callback" for uc_order entity. * * @param $order * The order to return the URI for. */ function uc_order_uri($order) { return array( 'path' => 'admin/store/orders/' . $order->order_id, ); } /** * Entity API "access callback" for uc_order entity. * * Checks order access for various operations. * * @param $op * The operation being performed. One of 'view', 'update', 'create' or * 'delete'. * @param $order * (optional) An order to check access for. * @param $account * (optional) The account to check, or current user if not given. */ function uc_order_order_entity_access($op, $order = NULL, $account = NULL) { global $user; if (!isset($account)) { $account = $user; } if ($op == 'delete') { if (!empty($order)) { return uc_order_can_delete($order, $account); } else { return FALSE; } } if ($op == 'update') { return user_access('edit orders', $account); } if ($op == 'create') { return user_access('create orders', $account); } if ($op == 'view') { if (user_access('view all orders', $account)) { return TRUE; } return (!empty($order) && $order->uid == $account->uid && user_access('view own orders', $account)); } } /** * Generates and saves a new order. * * @param $uid * The user ID to assign the order to. * @param $state * The initial state of the order. */ function uc_order_new($uid = 0, $state = 'in_checkout') { $order = new UcOrder($uid, $state); module_invoke_all('entity_presave', $order, 'uc_order'); drupal_write_record('uc_orders', $order); uc_order_module_invoke('new', $order, NULL); module_invoke_all('entity_insert', $order, 'uc_order'); return $order; } /** * Entity API "creation callback" for uc_order entity. * * @param $values * A set of default values for the order. */ function uc_order_create($values, $entity_type) { $order = new UcOrder(); foreach ($values as $key => $value) { $order->$key = $value; } module_invoke_all('entity_presave', $order, 'uc_order'); drupal_write_record('uc_orders', $order); uc_order_module_invoke('new', $order, NULL); module_invoke_all('entity_insert', $order, 'uc_order'); return $order; } /** * Entity API "save callback" for uc_order entity. * * Saves an order to the database. */ function uc_order_save($order) { $transaction = db_transaction(); try { if (is_null($order->order_id) || intval($order->order_id) == 0) { return FALSE; } field_attach_presave('uc_order', $order); $order->order_total = uc_order_get_total($order); $order->product_count = uc_order_get_product_count($order); if (is_null($order->delivery_country) || $order->delivery_country == 0) { $order->delivery_country = variable_get('uc_store_country', 840); } if (is_null($order->billing_country) || $order->billing_country == 0) { $order->billing_country = variable_get('uc_store_country', 840); } $order->host = ip_address(); $order->modified = REQUEST_TIME; uc_order_module_invoke('presave', $order, NULL); module_invoke_all('entity_presave', $order, 'uc_order'); drupal_write_record('uc_orders', $order, 'order_id'); if (is_array($order->products)) { foreach ($order->products as $product) { drupal_alter('uc_order_product', $product, $order); uc_order_product_save($order->order_id, $product); } } field_attach_update('uc_order', $order); uc_order_module_invoke('save', $order, NULL); module_invoke_all('entity_update', $order, 'uc_order'); $order->order_total = uc_order_get_total($order); } catch (Exception $e) { $transaction->rollback('uc_order'); watchdog_exception('uc_order', $e); throw $e; } } /** * Entity API "deletion callback" for uc_order entity. * * Deletes an order and tells other modules to do the same. * * @param $order_id * The ID of the order you wish to delete. */ function uc_order_delete($order_id) { global $user; $order = uc_order_load($order_id); // Perform the operations if we're deleting a valid order. if ($order !== FALSE) { rules_invoke_event('uc_order_delete', $order); uc_order_module_invoke('delete', $order, NULL); module_invoke_all('entity_delete', $order, 'uc_order'); // Delete data from the appropriate Ubercart order tables. db_delete('uc_orders') ->condition('order_id', $order_id) ->execute(); $efq = new EntityFieldQuery(); $result = $efq->entityCondition('entity_type', 'uc_order_product') ->propertyCondition('order_id', $order->order_id) ->execute(); if (!empty($result['uc_order_product'])) { $product_ids = array_keys($result['uc_order_product']); uc_order_product_delete_multiple($product_ids); } db_delete('uc_order_comments') ->condition('order_id', $order_id) ->execute(); db_delete('uc_order_admin_comments') ->condition('order_id', $order_id) ->execute(); db_delete('uc_order_log') ->condition('order_id', $order_id) ->execute(); // Delete line items for the order. uc_order_delete_line_item($order_id, TRUE); // Delete attached field values. field_attach_delete('uc_order', $order); // Log the action in the database. watchdog('uc_order', 'Order @order_id deleted by user @uid.', array('@order_id' => $order_id, '@uid' => $user->uid)); } } /** * Entity API "access callback" for uc_order_product entity. * * Checks order product access for various operations. * * @param $op * The operation being performed. One of 'view', 'update', 'create' or * 'delete'. * @param $order * Optionally an order to check access for. * @param $account * The user to check for. Leave it to NULL to check for the current user. */ function uc_order_order_product_access($op, $product = NULL, $account = NULL) { if (isset($product) && $product->order_id) { $order = uc_order_load($product->order_id); return uc_order_order_entity_access($op, $order, $account); } return FALSE; } /** * Save a product to an order. */ function uc_order_product_save($order_id, $product) { $product->order_id = $order_id; return entity_save('uc_order_product', $product); } /** * API wrapper for uc_order_product_save(). * * @todo: Change the signature for uc_order_product_save() to this one. */ function uc_order_product_entity_save($product) { return uc_order_product_save($product->order_id, $product); } /** * Remove a single product line from an order. * * @param int $order_product_id * Ordered product ID of product to remove. */ function uc_order_product_delete($order_product_id) { return uc_order_product_delete_multiple(array($order_product_id)); } /** * Remove multiple product lines from an order. * * @param array $order_product_ids * List of ordered product IDs of products to remove. */ function uc_order_product_delete_multiple($order_product_ids) { return entity_delete_multiple('uc_order_product', $order_product_ids); } /** * Load a single ordered product entity. * * @param int $opid * The ID of the ordered product entity. * @param bool $reset * Whether to reset the internal cache for ordered product IDs. Defaults to * FALSE. * * @return object * The ordered product entity matching $opid. */ function uc_order_product_load($opid, $reset = FALSE) { $products = uc_order_product_load_multiple(array($opid), $reset); return reset($products); } /** * Load multiple ordered product entities. * * @param array $opids * Array of ordered product IDs of products to load. Default is the empty * array, which loads all ordered products. * @param bool $reset * Whether to reset the internal cache for ordered product IDs. Defaults to * FALSE. * * @return array * An array of ordered product entities matching $opids, indexed by * ID. */ function uc_order_product_load_multiple($opids = array(), $reset = FALSE) { return entity_load('uc_order_product', $opids, array(), $reset); } /** * Generate an array for rendering the multiple order products. * * Order products being viewed are generally expected to be fully-loaded entity * objects, thus have their name or id key set. However, it is possible to * view a single entity without any id, e.g. for generating a preview during * creation. * * @param array $order_products * The array of order product to render. * @param $view_mode * A view mode as used by this entity type, e.g. 'full', 'teaser'... * @param $langcode * (optional) A language code to use for rendering. Defaults to the global * content language of the current request. * @param $page * (optional) If set will control if the entity is rendered: if TRUE * the entity will be rendered without its title, so that it can be embedded * in another context. If FALSE the entity will be displayed with its title * in a mode suitable for lists. * If unset, the page mode will be enabled if the current path is the URI * of the entity, as returned by entity_uri(). * * @return * The renderable array, keyed by the entity type and by entity identifiers, * for which the entity name is used if existing - see entity_id(). If there * is no information on how to view an entity, FALSE is returned. */ function uc_order_product_view_multiple($order_products, $view_mode = 'full', $langcode = NULL, $page = NULL) { return entity_view('uc_order_product', $order_products, $view_mode, $langcode, $page); } /** * Merge fields from their associated nodes into a set of order products. * * @param $products * An array of order_products. * @param $published * TRUE to load only published nodes, FALSE to load all nodes. * * @return * TRUE if the merge was successful for all products in the set. FALSE * otherwise (i.e. if the associated product node no longer exists). */ function uc_order_product_revive($products, $published = TRUE) { // Allow invocation for a single product. if (!is_array($products)) { $products = array($products); } // Load the nodes associated with each order product. $nids = array(); foreach ($products as $product) { $nids[] = $product->nid; } $nodes = node_load_multiple($nids); // Merge in fields from any nodes that still exist (but don't override order // product fields that are already set). $return = TRUE; foreach ($products as &$product) { if (!empty($nodes[$product->nid]) && (!$published || $nodes[$product->nid]->status == NODE_PUBLISHED)) { foreach ($nodes[$product->nid] as $key => $value) { if (!isset($product->$key)) { $product->$key = $value; } } // Order products are always variants. $product->variant = TRUE; } else { $return = FALSE; } } return $return; } /** * Displays the order view screen, constructed via hook_uc_order_pane(). */ function uc_order_view($order, $view_mode = 'full') { $order->content['#view_mode'] = $view_mode; // Build fields content. // In case of a multiple view, node_view_multiple() already ran the // 'prepare_view' step. An internal flag prevents the operation from running // twice. field_attach_prepare_view('uc_order', array($order->order_id => $order), $view_mode); entity_prepare_view('uc_order', array($order->order_id => $order)); $order->content += field_attach_view('uc_order', $order, $view_mode); $panes = _uc_order_pane_list($view_mode); foreach ($panes as $pane) { if (in_array($view_mode, $pane['show'])) { $func = $pane['callback']; if (function_exists($func) && ($contents = $func($view_mode, $order)) != NULL) { $title = isset($pane['display title']) ? $pane['display title'] : $pane['title']; if ($title) { $title = array( '#markup' => $pane['title'] . ':', '#prefix' => '