1 |
85ad3d82
|
Assos Assos
|
<?php
|
2 |
|
|
|
3 |
|
|
/**
|
4 |
|
|
* @file
|
5 |
|
|
* The page and form callbacks for use in the checkout form.
|
6 |
|
|
*/
|
7 |
|
|
|
8 |
|
|
|
9 |
|
|
/**
|
10 |
|
|
* Redirects invalid checkout attempts or displays the checkout form if valid.
|
11 |
|
|
*/
|
12 |
|
|
function commerce_checkout_router($order, $checkout_page = NULL) {
|
13 |
|
|
$checkout_pages = commerce_checkout_pages();
|
14 |
|
|
|
15 |
|
|
// If no checkout page is specified, default to the first one.
|
16 |
|
|
if (empty($checkout_page)) {
|
17 |
|
|
$checkout_page = reset($checkout_pages);
|
18 |
|
|
}
|
19 |
|
|
|
20 |
|
|
// If the user does not have access to checkout the order, return a 404. We
|
21 |
|
|
// could return a 403, but then the user would know they've identified a
|
22 |
|
|
// potentially valid checkout URL.
|
23 |
|
|
if (!commerce_checkout_access($order)) {
|
24 |
|
|
return MENU_NOT_FOUND;
|
25 |
|
|
}
|
26 |
|
|
|
27 |
|
|
// If the user is attempting to access an inaccessible page for their order,
|
28 |
|
|
// redirect them to the proper page.
|
29 |
|
|
if (!commerce_checkout_page_access($checkout_page, $order)) {
|
30 |
|
|
$target_uri = commerce_checkout_order_uri($order);
|
31 |
|
|
|
32 |
|
|
// Only redirect if the target page is different from the page the user was
|
33 |
|
|
// trying to access. Otherwise give a 403 error.
|
34 |
|
|
if (!empty($target_uri) && $target_uri !== $_GET['q']) {
|
35 |
|
|
drupal_goto($target_uri);
|
36 |
|
|
}
|
37 |
|
|
else {
|
38 |
|
|
return MENU_ACCESS_DENIED;
|
39 |
|
|
}
|
40 |
|
|
}
|
41 |
|
|
|
42 |
b858700c
|
Assos Assos
|
// Ensure the order can proceed to checkout; if not, redirect away.
|
43 |
|
|
if (!commerce_checkout_order_can_checkout($order)) {
|
44 |
85ad3d82
|
Assos Assos
|
drupal_goto('<front>');
|
45 |
|
|
}
|
46 |
|
|
|
47 |
|
|
// Prior to displaying the checkout form, allow other modules to route the
|
48 |
|
|
// checkout form.
|
49 |
|
|
module_invoke_all('commerce_checkout_router', $order, $checkout_page);
|
50 |
|
|
|
51 |
|
|
// Update the page title if specified.
|
52 |
|
|
if (!empty($checkout_page['title'])) {
|
53 |
|
|
drupal_set_title($checkout_page['title']);
|
54 |
|
|
}
|
55 |
|
|
|
56 |
|
|
return drupal_get_form('commerce_checkout_form_' . $checkout_page['page_id'], $order, $checkout_page);
|
57 |
|
|
}
|
58 |
|
|
|
59 |
|
|
/**
|
60 |
|
|
* Builds the checkout form for the given order on the specified checkout page.
|
61 |
|
|
*
|
62 |
|
|
* @param $order
|
63 |
|
|
* The fully loaded order object being checked out.
|
64 |
|
|
* @param $checkout_page
|
65 |
|
|
* The checkout page object representing the current step in checkout.
|
66 |
|
|
*/
|
67 |
|
|
function commerce_checkout_form($form, &$form_state, $order, $checkout_page) {
|
68 |
|
|
global $user;
|
69 |
|
|
|
70 |
9d13637e
|
Assos Assos
|
// Ensure this include file is loaded when the form is rebuilt from the cache.
|
71 |
|
|
$form_state['build_info']['files']['form'] = drupal_get_path('module', 'commerce_checkout') . '/includes/commerce_checkout.pages.inc';
|
72 |
|
|
|
73 |
85ad3d82
|
Assos Assos
|
$form['#attached']['css'][] = drupal_get_path('module', 'commerce_checkout') .'/theme/commerce_checkout.base.css';
|
74 |
|
|
$form['#attached']['css'][] = drupal_get_path('module', 'commerce_checkout') .'/theme/commerce_checkout.theme.css';
|
75 |
|
|
$form['#attached']['js'][] = drupal_get_path('module', 'commerce_checkout') . '/commerce_checkout.js';
|
76 |
|
|
|
77 |
|
|
$form_state['order'] = $order;
|
78 |
|
|
$form_state['checkout_page'] = $checkout_page;
|
79 |
|
|
$form_state['account'] = clone($user);
|
80 |
|
|
|
81 |
|
|
// Add any help text that has been defined for this checkout page.
|
82 |
|
|
$help = filter_xss($checkout_page['help']);
|
83 |
|
|
|
84 |
|
|
if (!empty($help)) {
|
85 |
|
|
$form['help'] = array(
|
86 |
|
|
'#markup' => theme('commerce_checkout_help', array('help' => $help)),
|
87 |
|
|
);
|
88 |
|
|
}
|
89 |
|
|
|
90 |
|
|
// Restore form errors.
|
91 |
|
|
if (!empty($form_state['storage']['errors'])) {
|
92 |
|
|
$form_errors = &drupal_static('form_set_error', array());
|
93 |
|
|
$form_errors = $form_state['storage']['errors'];
|
94 |
|
|
}
|
95 |
|
|
|
96 |
dbb0c974
|
Assos Assos
|
$form['#after_build'][] = 'commerce_checkout_form_process_errors';
|
97 |
|
|
|
98 |
85ad3d82
|
Assos Assos
|
// Catch and clear already pushed messages.
|
99 |
|
|
$previous_messages = drupal_get_messages();
|
100 |
|
|
$show_errors_message = FALSE;
|
101 |
|
|
$visible_panes = 0;
|
102 |
|
|
|
103 |
|
|
// Add any enabled checkout panes for this page to the form.
|
104 |
|
|
foreach (commerce_checkout_panes(array('enabled' => TRUE, 'page' => $checkout_page['page_id'])) as $pane_id => $checkout_pane) {
|
105 |
|
|
if ($callback = commerce_checkout_pane_callback($checkout_pane, 'checkout_form')) {
|
106 |
|
|
// Generate the pane form.
|
107 |
|
|
$pane_form = $callback($form, $form_state, $checkout_pane, $order);
|
108 |
|
|
|
109 |
|
|
// Combine the messages that were created during this pane's validation or
|
110 |
|
|
// submit process with any that were created during the pane generation
|
111 |
|
|
// and merge them into the session's current messages array.
|
112 |
|
|
if (!empty($form_state['storage']['messages'][$pane_id])) {
|
113 |
|
|
$_SESSION['messages'] = array_merge_recursive($form_state['storage']['messages'][$pane_id], drupal_get_messages());
|
114 |
|
|
}
|
115 |
|
|
|
116 |
|
|
// If there are messages in the session right now for this pane, theme
|
117 |
|
|
// them into the form right above the pane itself.
|
118 |
|
|
if (!empty($_SESSION['messages'])) {
|
119 |
|
|
// If there are error messages and this is not the first pane on the
|
120 |
|
|
// form, then indicate we need to show an error message at the top of
|
121 |
|
|
// the page.
|
122 |
|
|
if ($visible_panes > 0 && !empty($_SESSION['messages']['error'])) {
|
123 |
|
|
$show_errors_message = TRUE;
|
124 |
|
|
}
|
125 |
|
|
|
126 |
|
|
// Rendering status messages clears the session of messages, so they
|
127 |
|
|
// will not be visible if the user is redirected. We can at least not
|
128 |
|
|
// render here when we detect the global variable added by Rules to
|
129 |
|
|
// handle redirects, though modules implementing redirects will still
|
130 |
|
|
// encounter the same problem of "lost" messages.
|
131 |
|
|
if (!isset($GLOBALS['_rules_action_drupal_goto_do'])){
|
132 |
|
|
$form_state['storage']['themed_messages'][$pane_id] = theme('status_messages');
|
133 |
|
|
|
134 |
|
|
$pane_form[$pane_id . '_messages'] = array(
|
135 |
|
|
'#markup' => $form_state['storage']['themed_messages'][$pane_id],
|
136 |
|
|
'#weight' => -50,
|
137 |
|
|
);
|
138 |
|
|
}
|
139 |
|
|
}
|
140 |
|
|
|
141 |
|
|
// Create a fieldset for the pane and add the form data defined in the
|
142 |
|
|
// pane's form callback.
|
143 |
|
|
if ($pane_form) {
|
144 |
|
|
$form[$pane_id] = $pane_form + array(
|
145 |
|
|
'#type' => $checkout_pane['fieldset'] ? 'fieldset' : 'container',
|
146 |
|
|
'#title' => check_plain($checkout_pane['title']),
|
147 |
|
|
'#collapsible' => $checkout_pane['collapsible'],
|
148 |
|
|
'#collapsed' => $checkout_pane['collapsed'],
|
149 |
|
|
'#attributes' => array('class' => array($pane_id)),
|
150 |
|
|
'#tree' => TRUE,
|
151 |
|
|
);
|
152 |
|
|
|
153 |
|
|
$visible_panes++;
|
154 |
|
|
}
|
155 |
|
|
}
|
156 |
|
|
}
|
157 |
|
|
|
158 |
|
|
// Restore general messages to the current session's messages array.
|
159 |
|
|
$_SESSION['messages'] = array_merge_recursive(array_filter($previous_messages), drupal_get_messages());
|
160 |
|
|
|
161 |
|
|
// If there are errors on the form, add a message to the top of the page.
|
162 |
|
|
if ($show_errors_message) {
|
163 |
|
|
$form['error_message'] = array(
|
164 |
|
|
'#markup' => theme('commerce_checkout_errors_message', array('label' => t('Errors on form'), 'message' => t('There are errors on the page. Please correct them and resubmit the form.'))),
|
165 |
|
|
'#weight' => -10,
|
166 |
|
|
);
|
167 |
|
|
}
|
168 |
|
|
|
169 |
|
|
// Only add buttons to the form if the checkout page hasn't disabled them.
|
170 |
|
|
if ($checkout_page['buttons']) {
|
171 |
|
|
$form['buttons'] = array(
|
172 |
|
|
'#type' => 'fieldset',
|
173 |
|
|
'#attributes' => array('class' => array('checkout-buttons')),
|
174 |
|
|
);
|
175 |
|
|
$form['buttons']['continue'] = array(
|
176 |
|
|
'#type' => 'submit',
|
177 |
|
|
'#value' => $checkout_page['submit_value'],
|
178 |
|
|
'#attributes' => array('class' => array('checkout-continue')),
|
179 |
|
|
'#suffix' => '<span class="checkout-processing element-invisible"></span>',
|
180 |
|
|
'#validate' => array('commerce_checkout_form_validate'),
|
181 |
|
|
'#submit' => array('commerce_checkout_form_submit'),
|
182 |
|
|
);
|
183 |
|
|
|
184 |
|
|
// Add the cancel or back button where appropriate. We define button level
|
185 |
|
|
// submit handlers because we're using hook_forms() to use this form builder
|
186 |
|
|
// function and to avoid issues if other modules implement button level submit
|
187 |
|
|
// handlers on these or custom checkout buttons.
|
188 |
|
|
$button_operator = '<span class="button-operator">' . t('or') . '</span>';
|
189 |
|
|
|
190 |
|
|
if (!$checkout_page['prev_page'] && !empty($checkout_page['back_value'])) {
|
191 |
|
|
// Add an empty "Back" button value to avoid submission errors.
|
192 |
|
|
$form['buttons']['back'] = array(
|
193 |
|
|
'#type' => 'value',
|
194 |
|
|
'#value' => '',
|
195 |
|
|
);
|
196 |
|
|
|
197 |
|
|
// Store the cancel redirect in the form so modules can modify it easily.
|
198 |
|
|
$form_state['cancel_redirect'] = '<front>';
|
199 |
|
|
|
200 |
|
|
$form['buttons']['cancel'] = array(
|
201 |
|
|
'#type' => 'submit',
|
202 |
|
|
'#value' => t('Cancel'),
|
203 |
|
|
'#attributes' => array('class' => array('checkout-cancel')),
|
204 |
|
|
'#submit' => array('commerce_checkout_form_cancel_submit'),
|
205 |
|
|
'#limit_validation_errors' => array(),
|
206 |
|
|
'#prefix' => $button_operator,
|
207 |
|
|
);
|
208 |
|
|
}
|
209 |
|
|
elseif ($checkout_page['prev_page'] && !empty($checkout_page['back_value'])) {
|
210 |
|
|
$form['buttons']['back'] = array(
|
211 |
|
|
'#type' => 'submit',
|
212 |
|
|
'#value' => $checkout_page['back_value'],
|
213 |
|
|
'#attributes' => array('class' => array('checkout-back')),
|
214 |
|
|
'#submit' => array('commerce_checkout_form_back_submit'),
|
215 |
|
|
'#limit_validation_errors' => array(),
|
216 |
|
|
'#prefix' => $button_operator,
|
217 |
|
|
);
|
218 |
|
|
}
|
219 |
|
|
}
|
220 |
|
|
|
221 |
|
|
// Remove form level validate and submit handlers.
|
222 |
|
|
$form['#validate'] = array();
|
223 |
|
|
$form['#submit'] = array();
|
224 |
|
|
|
225 |
|
|
return $form;
|
226 |
|
|
}
|
227 |
|
|
|
228 |
dbb0c974
|
Assos Assos
|
/**
|
229 |
|
|
* After build callback for the checkout form.
|
230 |
|
|
*/
|
231 |
|
|
function commerce_checkout_form_process_errors($form, $form_state) {
|
232 |
|
|
// Do this only on form rebuild (when the form will not be validated anymore):
|
233 |
|
|
if (!empty($form_state['storage']['errors']) && !empty($form_state['rebuild'])) {
|
234 |
|
|
foreach (array_keys($form_state['storage']['errors']) as $element_name) {
|
235 |
|
|
// Look for all elements which have $element_name as parents, and
|
236 |
|
|
// restore their #validated property (so _form_set_class() will set
|
237 |
|
|
// the error class even though the rebuilt form is not validated).
|
238 |
|
|
// We can't simply use drupal_array_get_nested_value(), since the #parents
|
239 |
|
|
// property may have been changed and not match the form structure.
|
240 |
|
|
_commerce_checkout_set_validated($form, $element_name);
|
241 |
|
|
}
|
242 |
|
|
}
|
243 |
|
|
|
244 |
|
|
return $form;
|
245 |
|
|
}
|
246 |
|
|
|
247 |
|
|
/**
|
248 |
|
|
* Set '#validated' on elements which have the specified parents.
|
249 |
|
|
*/
|
250 |
|
|
function _commerce_checkout_set_validated(&$element, $imploded_parents) {
|
251 |
|
|
// Recurse to child elements if the current element is a container.
|
252 |
|
|
foreach (element_children($element) as $key) {
|
253 |
|
|
_commerce_checkout_set_validated($element[$key], $imploded_parents);
|
254 |
|
|
}
|
255 |
|
|
|
256 |
|
|
// This will also set #validated on all elements where #needs_validation would
|
257 |
|
|
// be FALSE, but that doesn't hurt anything.
|
258 |
|
|
if (!empty($element['#parents']) && strpos($imploded_parents, implode('][', $element['#parents'])) === 0) {
|
259 |
|
|
$element['#validated'] = TRUE;
|
260 |
|
|
}
|
261 |
|
|
}
|
262 |
|
|
|
263 |
85ad3d82
|
Assos Assos
|
/**
|
264 |
|
|
* Validate handler for the continue button of the checkout form.
|
265 |
|
|
*
|
266 |
|
|
* This function calls the validation function of each pane, followed by
|
267 |
|
|
* the submit function if the validation succeeded. As long as one pane
|
268 |
|
|
* fails validation, we then ask for the form to be rebuilt. Once all the panes
|
269 |
|
|
* are happy, we move on to the next page.
|
270 |
|
|
*/
|
271 |
|
|
function commerce_checkout_form_validate($form, &$form_state) {
|
272 |
|
|
$checkout_page = $form_state['checkout_page'];
|
273 |
|
|
|
274 |
|
|
// Load a fresh copy of the order stored in the form.
|
275 |
|
|
$order = commerce_order_load($form_state['order']->order_id);
|
276 |
|
|
|
277 |
|
|
// Catch and clear already pushed messages.
|
278 |
|
|
$previous_messages = drupal_get_messages();
|
279 |
|
|
|
280 |
|
|
// Load any pre-existing validation errors for the elements.
|
281 |
|
|
$errors = array();
|
282 |
|
|
|
283 |
|
|
foreach ((array) form_get_errors() as $element_path => $error) {
|
284 |
|
|
list($pane_id, ) = explode('][', $element_path, 2);
|
285 |
|
|
$errors[$pane_id][$element_path] = $error;
|
286 |
|
|
}
|
287 |
|
|
|
288 |
|
|
// Loop through the enabled checkout panes for the current page.
|
289 |
|
|
$form_validate = TRUE;
|
290 |
|
|
foreach (commerce_checkout_panes(array('enabled' => TRUE, 'page' => $checkout_page['page_id'])) as $pane_id => $checkout_pane) {
|
291 |
|
|
$validate = TRUE;
|
292 |
|
|
|
293 |
|
|
// If any element in the pane failed validation, we mark the pane as
|
294 |
|
|
// unvalidated and replay the validation messages on top of it.
|
295 |
|
|
if (!empty($errors[$pane_id])) {
|
296 |
|
|
$validate = FALSE;
|
297 |
|
|
|
298 |
|
|
foreach ($errors[$pane_id] as $element_path => $message) {
|
299 |
|
|
if ($message) {
|
300 |
|
|
drupal_set_message($message, 'error');
|
301 |
|
|
}
|
302 |
|
|
}
|
303 |
|
|
|
304 |
|
|
if (isset($previous_messages['error'])) {
|
305 |
|
|
$previous_messages['error'] = array_values(array_diff($previous_messages['error'], $errors[$pane_id]));
|
306 |
|
|
}
|
307 |
|
|
}
|
308 |
|
|
|
309 |
|
|
// If the pane has defined a checkout form validate handler...
|
310 |
|
|
if ($callback = commerce_checkout_pane_callback($checkout_pane, 'checkout_form_validate')) {
|
311 |
|
|
// Give it a chance to process the submitted data.
|
312 |
|
|
$validate &= $callback($form, $form_state, $checkout_pane, $order);
|
313 |
|
|
}
|
314 |
|
|
|
315 |
|
|
// Catch and clear panes' messages.
|
316 |
|
|
$pane_messages = drupal_get_messages();
|
317 |
|
|
|
318 |
|
|
// Submit the pane if it validated.
|
319 |
|
|
if ($validate && $callback = commerce_checkout_pane_callback($checkout_pane, 'checkout_form_submit')) {
|
320 |
|
|
$callback($form, $form_state, $checkout_pane, $order);
|
321 |
|
|
}
|
322 |
|
|
|
323 |
|
|
// Generate status messages.
|
324 |
|
|
$form_state['storage']['messages'][$pane_id] = array_merge_recursive($pane_messages, drupal_get_messages());
|
325 |
|
|
|
326 |
|
|
// A failed pane makes the form fail.
|
327 |
|
|
$form_validate &= $validate;
|
328 |
|
|
}
|
329 |
|
|
|
330 |
|
|
// Restore messages and form errors.
|
331 |
|
|
$_SESSION['messages'] = array_merge_recursive(array_filter($previous_messages), drupal_get_messages());
|
332 |
|
|
$form_errors = &drupal_static('form_set_error', array());
|
333 |
|
|
$form_state['storage']['errors'] = $form_errors;
|
334 |
|
|
$form_errors = array();
|
335 |
|
|
|
336 |
|
|
// Save the updated order object and reset the order in the form cache to
|
337 |
|
|
// ensure rebuilt forms use the updated order.
|
338 |
|
|
commerce_order_save($order);
|
339 |
|
|
$form_state['build_info']['args'][0] = $order;
|
340 |
|
|
|
341 |
|
|
// If a pane failed validation or the form state has otherwise been altered to
|
342 |
|
|
// initiate a rebuild, return without moving to the next checkout page.
|
343 |
|
|
if (!$form_validate || $form_state['rebuild']) {
|
344 |
|
|
$form_state['rebuild'] = TRUE;
|
345 |
|
|
}
|
346 |
|
|
}
|
347 |
|
|
|
348 |
|
|
/**
|
349 |
|
|
* Submit handler for the continue button of the checkout form.
|
350 |
|
|
*/
|
351 |
|
|
function commerce_checkout_form_submit($form, &$form_state) {
|
352 |
|
|
$checkout_page = $form_state['checkout_page'];
|
353 |
|
|
|
354 |
|
|
// Load a fresh copy of the order stored in the form.
|
355 |
|
|
$order = commerce_order_load($form_state['order']->order_id);
|
356 |
|
|
|
357 |
|
|
// If we are going to redirect with checkout pane messages stored in the form
|
358 |
|
|
// state, they will not be displayed on a subsequent form build like normal.
|
359 |
|
|
// Move them out of the form state messages array and into the current
|
360 |
|
|
// session's general message array instead.
|
361 |
|
|
if (!empty($form_state['storage']['messages'])) {
|
362 |
|
|
foreach ($form_state['storage']['messages'] as $pane_id => $pane_messages) {
|
363 |
|
|
$_SESSION['messages'] = array_merge_recursive($_SESSION['messages'], $pane_messages);
|
364 |
|
|
}
|
365 |
|
|
}
|
366 |
|
|
|
367 |
|
|
// If the form was submitted via the continue button...
|
368 |
|
|
if (end($form_state['triggering_element']['#array_parents']) == 'continue') {
|
369 |
|
|
// If there is another checkout page...
|
370 |
|
|
if ($checkout_page['next_page']) {
|
371 |
|
|
// Update the order status to reflect the next checkout page.
|
372 |
|
|
$order = commerce_order_status_update($order, 'checkout_' . $checkout_page['next_page'], FALSE, NULL, t('Customer continued to the next checkout page via a submit button.'));
|
373 |
|
|
|
374 |
|
|
// If it happens to be the complete page, process completion now.
|
375 |
|
|
if ($checkout_page['next_page'] == 'complete') {
|
376 |
|
|
commerce_checkout_complete($order);
|
377 |
|
|
}
|
378 |
|
|
|
379 |
|
|
// Redirect to the next checkout page.
|
380 |
|
|
$form_state['redirect'] = 'checkout/' . $order->order_id . '/' . $checkout_page['next_page'];
|
381 |
|
|
}
|
382 |
|
|
}
|
383 |
|
|
}
|
384 |
|
|
|
385 |
|
|
/**
|
386 |
|
|
* Special submit handler for the back button to avoid processing orders.
|
387 |
|
|
*/
|
388 |
|
|
function commerce_checkout_form_back_submit($form, &$form_state) {
|
389 |
|
|
// If there is a previous page...
|
390 |
|
|
if ($previous_page = commerce_checkout_page_load($form_state['checkout_page']['prev_page'])) {
|
391 |
|
|
$order = commerce_order_load($form_state['order']->order_id);
|
392 |
|
|
|
393 |
|
|
// Move the form back to that page.
|
394 |
|
|
if ($previous_page['prev_page']) {
|
395 |
|
|
$form_state['redirect'] = 'checkout/' . $order->order_id . '/' . $previous_page['page_id'];
|
396 |
|
|
}
|
397 |
|
|
else {
|
398 |
|
|
$form_state['redirect'] = 'checkout/' . $order->order_id;
|
399 |
|
|
}
|
400 |
|
|
|
401 |
|
|
// Update the order status for the checkout step.
|
402 |
|
|
$form_state['order'] = commerce_order_status_update($order, 'checkout_' . $previous_page['page_id'], FALSE, NULL, t('Customer returned to the previous checkout page via a submit button.'));
|
403 |
|
|
}
|
404 |
|
|
}
|
405 |
|
|
|
406 |
|
|
/**
|
407 |
|
|
* Special submit handler for the cancel button to avoid processing orders.
|
408 |
|
|
*/
|
409 |
|
|
function commerce_checkout_form_cancel_submit($form, &$form_state) {
|
410 |
|
|
$order = commerce_order_load($form_state['order']->order_id);
|
411 |
|
|
|
412 |
|
|
// Set the order status back to the first checkout page's status.
|
413 |
|
|
$order_state = commerce_order_state_load('checkout');
|
414 |
|
|
$form_state['order'] = commerce_order_status_update($order, $order_state['default_status'], TRUE);
|
415 |
|
|
|
416 |
|
|
// Skip saving in the status update and manually save here to force a save
|
417 |
|
|
// even when the status doesn't actually change.
|
418 |
|
|
if (variable_get('commerce_order_auto_revision', TRUE)) {
|
419 |
|
|
$form_state['order']->revision = TRUE;
|
420 |
|
|
$form_state['order']->log = t('Customer manually canceled the checkout process.');
|
421 |
|
|
}
|
422 |
|
|
|
423 |
|
|
commerce_order_save($form_state['order']);
|
424 |
|
|
|
425 |
|
|
drupal_set_message(t('Checkout of your current order has been canceled and may be resumed when you are ready.'));
|
426 |
|
|
|
427 |
|
|
$form_state['redirect'] = $form_state['cancel_redirect'];
|
428 |
|
|
}
|
429 |
|
|
|
430 |
|
|
/**
|
431 |
|
|
* Themes the optional checkout review page data.
|
432 |
|
|
*/
|
433 |
|
|
function theme_commerce_checkout_review($variables) {
|
434 |
|
|
$form = $variables['form'];
|
435 |
|
|
|
436 |
|
|
// Turn the review data array into table rows.
|
437 |
|
|
$rows = array();
|
438 |
|
|
|
439 |
|
|
foreach ($form['#data'] as $pane_id => $data) {
|
440 |
|
|
// First add a row for the title.
|
441 |
|
|
$rows[] = array(
|
442 |
|
|
'data' => array(
|
443 |
|
|
array('data' => $data['title'], 'colspan' => 2),
|
444 |
|
|
),
|
445 |
|
|
'class' => array('pane-title', 'odd'),
|
446 |
|
|
);
|
447 |
|
|
|
448 |
|
|
// Next, add the data for this particular section.
|
449 |
|
|
if (is_array($data['data'])) {
|
450 |
|
|
// If it's an array, treat each key / value pair as a 2 column row.
|
451 |
|
|
foreach ($data['data'] as $key => $value) {
|
452 |
|
|
$rows[] = array(
|
453 |
|
|
'data' => array(
|
454 |
|
|
array('data' => $key .':', 'class' => array('pane-data-key')),
|
455 |
|
|
array('data' => $value, 'class' => array('pane-data-value')),
|
456 |
|
|
),
|
457 |
|
|
'class' => array('pane-data', 'even'),
|
458 |
|
|
);
|
459 |
|
|
}
|
460 |
|
|
}
|
461 |
|
|
else {
|
462 |
|
|
// Otherwise treat it as a block of text in its own row.
|
463 |
|
|
$rows[] = array(
|
464 |
|
|
'data' => array(
|
465 |
|
|
array('data' => $data['data'], 'colspan' => 2, 'class' => array('pane-data-full')),
|
466 |
|
|
),
|
467 |
|
|
'class' => array('pane-data', 'even'),
|
468 |
|
|
);
|
469 |
|
|
}
|
470 |
|
|
}
|
471 |
|
|
|
472 |
|
|
return theme('table', array('rows' => $rows, 'attributes' => array('class' => array('checkout-review'))));
|
473 |
|
|
} |