1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Verify nonce of an AJAX request |
4
|
|
|
* |
5
|
|
|
* @since 3.8.9 |
6
|
|
|
* @access private |
7
|
|
|
* |
8
|
|
|
* @uses WP_Error WordPress Error Class |
9
|
|
|
* @uses wp_verify_nonce() Verify that correct nonce was used with time limit. |
10
|
|
|
* |
11
|
|
|
* @param string $ajax_action Name of AJAX action |
12
|
|
|
* @return WP_Error|boolean True if nonce is valid. WP_Error if otherwise. |
13
|
|
|
*/ |
14
|
|
|
function _wpsc_ajax_verify_nonce( $ajax_action ) { |
15
|
|
|
// nonce can be passed with name wpsc_nonce or _wpnonce |
16
|
|
|
$nonce = ''; |
17
|
|
|
|
18
|
|
|
if ( isset( $_REQUEST['nonce'] ) ) |
19
|
|
|
$nonce = $_REQUEST['nonce']; |
20
|
|
|
elseif ( isset( $_REQUEST['_wpnonce'] ) ) |
21
|
|
|
$nonce = $_REQUEST['_wpnonce']; |
22
|
|
|
else |
23
|
|
|
return _wpsc_error_invalid_nonce(); |
24
|
|
|
|
25
|
|
|
// validate nonce |
26
|
|
|
if ( ! wp_verify_nonce( $nonce, 'wpsc_ajax_' . $ajax_action ) ) |
27
|
|
|
return _wpsc_error_invalid_nonce(); |
28
|
|
|
|
29
|
|
|
return true; |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
function _wpsc_error_invalid_nonce() { |
33
|
|
|
return new WP_Error( 'wpsc_ajax_invalid_nonce', __( 'Your session has expired. Please refresh the page and try again.', 'wp-e-commerce' ) ); |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* Verify AJAX callback and call it if it exists. |
38
|
|
|
* |
39
|
|
|
* @since 3.8.9 |
40
|
|
|
* @access private |
41
|
|
|
* |
42
|
|
|
* @uses WP_Error WordPress Error object |
43
|
|
|
* |
44
|
|
|
* @param string $ajax_action Name of AJAX action |
45
|
|
|
* @return WP_Error|array Array of response args if callback is valid. WP_Error if otherwise. |
46
|
|
|
*/ |
47
|
|
|
function _wpsc_ajax_fire_callback( $ajax_action ) { |
48
|
|
|
// if callback exists, call it and output JSON response |
49
|
|
|
$callback = "_wpsc_ajax_{$ajax_action}"; |
50
|
|
|
|
51
|
|
|
if ( is_callable( $callback ) ) |
52
|
|
|
$result = call_user_func( $callback ); |
53
|
|
|
else |
54
|
|
|
$result = new WP_Error( 'wpsc_invalid_ajax_callback', __( 'Invalid AJAX callback.', 'wp-e-commerce' ) ); |
55
|
|
|
|
56
|
|
|
return $result; |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* AJAX handler for all WPEC ajax requests. |
61
|
|
|
* |
62
|
|
|
* This function automates nonce checking and outputs JSON response. |
63
|
|
|
* |
64
|
|
|
* @since 3.8.9 |
65
|
|
|
* @access private |
66
|
|
|
* |
67
|
|
|
* @uses _wpsc_ajax_fire_callback() Verify ajax callback if it exists |
68
|
|
|
* @uses _wpsc_ajax_verify_nonce() Verify nonce of an ajax request |
69
|
|
|
* @uses is_wp_error() Check whether variable is a WordPress Error. |
70
|
|
|
* |
71
|
|
|
* @return array $output json encoded response |
|
|
|
|
72
|
|
|
*/ |
73
|
|
|
function _wpsc_ajax_handler() { |
74
|
|
|
$ajax_action = str_replace( '-', '_', $_REQUEST['wpsc_action'] ); |
75
|
|
|
|
76
|
|
|
if ( is_callable( '_wpsc_ajax_verify_' . $ajax_action ) ) { |
77
|
|
|
$result = call_user_func( '_wpsc_ajax_verify_' . $ajax_action ); |
78
|
|
|
} else { |
79
|
|
|
$result = _wpsc_ajax_verify_nonce( $ajax_action ); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
if ( ! is_wp_error( $result ) ) { |
83
|
|
|
$result = _wpsc_ajax_fire_callback( $ajax_action ); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
$output = array( |
87
|
|
|
'is_successful' => false, |
88
|
|
|
); |
89
|
|
|
|
90
|
|
|
if ( is_wp_error( $result ) ) { |
91
|
|
|
$output['error'] = array( |
92
|
|
|
'code' => $result->get_error_code(), |
93
|
|
|
'messages' => $result->get_error_messages(), |
94
|
|
|
'data' => $result->get_error_data(), |
95
|
|
|
); |
96
|
|
|
} else { |
97
|
|
|
$output['is_successful'] = true; |
98
|
|
|
$output['obj'] = $result; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
echo json_encode( $output ); |
102
|
|
|
exit; |
103
|
|
|
} |
104
|
|
|
add_action( 'wp_ajax_wpsc_ajax', '_wpsc_ajax_handler' ); |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Checks if WPSC is doing ajax |
108
|
|
|
* |
109
|
|
|
* @param string $action req The action we're checking |
110
|
|
|
* @return bool True if doing ajax |
111
|
|
|
*/ |
112
|
|
|
function wpsc_is_doing_ajax( $action = '' ) { |
113
|
|
|
$ajax = defined( 'DOING_AJAX' ) && DOING_AJAX && ! empty( $_REQUEST['action'] ) && $_REQUEST['action'] == 'wpsc_ajax'; |
114
|
|
|
|
115
|
|
|
if ( $action ) { |
116
|
|
|
$ajax = $ajax && ! empty( $_REQUEST['wpsc_action'] ) && $action == str_replace( '-', '_', $_REQUEST['wpsc_action'] ); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
return $ajax; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Helper function that generates nonce for an AJAX action. Basically just a wrapper of |
124
|
|
|
* wp_create_nonce() but automatically add prefix. |
125
|
|
|
* |
126
|
|
|
* @since 3.8.9 |
127
|
|
|
* @access private |
128
|
|
|
* |
129
|
|
|
* @uses wp_create_nonce() Creates a random one time use token |
130
|
|
|
* |
131
|
|
|
* @param string $action AJAX action without prefix |
|
|
|
|
132
|
|
|
* @return string The generated nonce. |
133
|
|
|
*/ |
134
|
|
|
function _wpsc_create_ajax_nonce( $ajax_action ) { |
135
|
|
|
return wp_create_nonce( "wpsc_ajax_{$ajax_action}" ); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Add new variation set via AJAX. |
140
|
|
|
* |
141
|
|
|
* If the variation set name is the same as an existing variation set, |
142
|
|
|
* the children variant terms will be added inside that existing set. |
143
|
|
|
* |
144
|
|
|
* @since 3.8.8 |
145
|
|
|
* @access private |
146
|
|
|
* |
147
|
|
|
* @uses term_exists() Returns true if term exists |
148
|
|
|
* @uses get_term() Gets all term data by term_id |
149
|
|
|
* @uses wp_insert_term() Inserts a term to the WordPress database |
150
|
|
|
* @uses is_wp_error() Checks whether variable is a WordPress error |
151
|
|
|
* @uses WP_Error WordPress Error class |
152
|
|
|
* @uses clean_term_cache() Will remove all of the term ids from the cache. |
153
|
|
|
* @uses delete_option() Deletes option from the database |
154
|
|
|
* @uses wp_cache_set() Saves the data to the cache. |
155
|
|
|
* @uses _get_term_hierarchy() Retrieves children of taxonomy as Term IDs. |
156
|
|
|
* @uses wp_terms_checklist() Output an unordered list of checkbox <input> elements labelled |
157
|
|
|
* @uses WPSC_Walker_Variation_Checklist Walker variation checklist |
158
|
|
|
* |
159
|
|
|
* @return array Response args |
160
|
|
|
*/ |
161
|
|
|
function _wpsc_ajax_add_variation_set() { |
162
|
|
|
$new_variation_set = $_POST['variation_set']; |
163
|
|
|
$variants = preg_split( '/\s*,\s*/', $_POST['variants'] ); |
164
|
|
|
|
165
|
|
|
$return = array(); |
166
|
|
|
|
167
|
|
|
$parent_term_exists = term_exists( $new_variation_set, 'wpsc-variation' ); |
168
|
|
|
|
169
|
|
|
// only use an existing parent ID if the term is not a child term |
170
|
|
|
if ( $parent_term_exists ) { |
171
|
|
|
$parent_term = get_term( $parent_term_exists['term_id'], 'wpsc-variation' ); |
172
|
|
|
if ( $parent_term->parent == '0' ) |
173
|
|
|
$variation_set_id = $parent_term_exists['term_id']; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
if ( empty( $variation_set_id ) ) { |
177
|
|
|
$results = wp_insert_term( apply_filters( 'wpsc_new_variation_set', $new_variation_set ), 'wpsc-variation' ); |
178
|
|
|
if ( is_wp_error( $results ) ) |
179
|
|
|
return $results; |
180
|
|
|
$variation_set_id = $results['term_id']; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
if ( empty( $variation_set_id ) ) |
184
|
|
|
return new WP_Error( 'wpsc_invalid_variation_id', __( 'Cannot retrieve the variation set in order to proceed.', 'wp-e-commerce' ) ); |
185
|
|
|
|
186
|
|
|
foreach ( $variants as $variant ) { |
187
|
|
|
$results = wp_insert_term( apply_filters( 'wpsc_new_variant', $variant, $variation_set_id ), 'wpsc-variation', array( 'parent' => $variation_set_id ) ); |
188
|
|
|
|
189
|
|
|
if ( is_wp_error( $results ) ) |
190
|
|
|
return $results; |
191
|
|
|
|
192
|
|
|
$inserted_variants[] = $results['term_id']; |
|
|
|
|
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
require_once( 'includes/walker-variation-checklist.php' ); |
196
|
|
|
|
197
|
|
|
if ( ! version_compare( $GLOBALS['wp_version'], '3.8.3', '>' ) ) { |
198
|
|
|
|
199
|
|
|
/* --- DIRTY HACK START --- */ |
200
|
|
|
/* |
201
|
|
|
There's a bug with term cache in WordPress core. See http://core.trac.wordpress.org/ticket/14485. Fixed in 3.9. |
202
|
|
|
The next 3 lines will delete children term cache for wpsc-variation. |
203
|
|
|
Without this hack, the new child variations won't be displayed on "Variations" page and |
204
|
|
|
also won't be displayed in wp_terms_checklist() call below. |
205
|
|
|
*/ |
206
|
|
|
clean_term_cache( $variation_set_id, 'wpsc-variation' ); |
207
|
|
|
delete_option('wpsc-variation_children'); |
208
|
|
|
wp_cache_set( 'last_changed', 1, 'terms' ); |
209
|
|
|
_get_term_hierarchy('wpsc-variation'); |
210
|
|
|
/* --- DIRTY HACK END --- */ |
211
|
|
|
|
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
ob_start(); |
215
|
|
|
|
216
|
|
|
wp_terms_checklist( (int) $_POST['post_id'], array( |
217
|
|
|
'taxonomy' => 'wpsc-variation', |
218
|
|
|
'descendants_and_self' => $variation_set_id, |
219
|
|
|
'walker' => new WPSC_Walker_Variation_Checklist( $inserted_variants ), |
|
|
|
|
220
|
|
|
'checked_ontop' => false, |
221
|
|
|
) ); |
222
|
|
|
|
223
|
|
|
$content = ob_get_clean(); |
224
|
|
|
|
225
|
|
|
$return = array( |
226
|
|
|
'variation_set_id' => $variation_set_id, |
227
|
|
|
'inserted_variants' => $inserted_variants, |
228
|
|
|
'content' => $content, |
229
|
|
|
); |
230
|
|
|
|
231
|
|
|
return $return; |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* Display gateway settings form via AJAX |
236
|
|
|
* |
237
|
|
|
* @since 3.8.9 |
238
|
|
|
* @access private |
239
|
|
|
* |
240
|
|
|
* @uses WPSC_Settings_Tab_Gateway |
241
|
|
|
* @uses WPSC_Settings_Tab_Gateway::display_payment_gateway_settings_form() Displays payment gateway form |
242
|
|
|
* |
243
|
|
|
* @return array Response args |
|
|
|
|
244
|
|
|
*/ |
245
|
|
|
function _wpsc_ajax_payment_gateway_settings_form() { |
246
|
|
|
|
247
|
|
|
require_once( 'settings-page.php' ); |
248
|
|
|
require_once( 'includes/settings-tabs/gateway.php' ); |
249
|
|
|
|
250
|
|
|
$return = array(); |
251
|
|
|
ob_start(); |
252
|
|
|
$tab = new WPSC_Settings_Tab_Gateway(); |
253
|
|
|
$tab->display_payment_gateway_settings_form(); |
254
|
|
|
$return['content'] = ob_get_clean(); |
255
|
|
|
|
256
|
|
|
return $return; |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
/** |
260
|
|
|
* Display shipping module settings form via AJAX |
261
|
|
|
* |
262
|
|
|
* @since 3.8.9 |
263
|
|
|
* @access private |
264
|
|
|
* |
265
|
|
|
* @uses WPSC_Settings_Table_Shipping |
266
|
|
|
* @uses WPSC_Settings_Table_Shipping::display_shipping_module_settings_form() Displays shipping module form |
267
|
|
|
* |
268
|
|
|
* @return array $return Response args |
|
|
|
|
269
|
|
|
*/ |
270
|
|
|
function _wpsc_ajax_shipping_module_settings_form() { |
271
|
|
|
require_once( 'settings-page.php' ); |
272
|
|
|
require_once( 'includes/settings-tabs/shipping.php' ); |
273
|
|
|
|
274
|
|
|
$return = array(); |
275
|
|
|
ob_start(); |
276
|
|
|
$tab = new WPSC_Settings_Tab_Shipping(); |
277
|
|
|
$tab->display_shipping_module_settings_form(); |
278
|
|
|
$return['content'] = ob_get_clean(); |
279
|
|
|
|
280
|
|
|
return $return; |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
/** |
284
|
|
|
* Display settings tab via AJAX |
285
|
|
|
* |
286
|
|
|
* @since 3.8.9 |
287
|
|
|
* @access private |
288
|
|
|
* |
289
|
|
|
* @uses WPSC_Settings_Page |
290
|
|
|
* @uses WPSC_Settings_Page::display_current_tab() Shows current tab of settings page |
291
|
|
|
* |
292
|
|
|
* @return array $return Response args |
|
|
|
|
293
|
|
|
*/ |
294
|
|
|
function _wpsc_ajax_navigate_settings_tab() { |
295
|
|
|
require_once( 'settings-page.php' ); |
296
|
|
|
|
297
|
|
|
$return = array(); |
298
|
|
|
ob_start(); |
299
|
|
|
$settings_page = new WPSC_Settings_Page( $_POST['tab'] ); |
300
|
|
|
$settings_page->display_current_tab(); |
301
|
|
|
$return['content'] = ob_get_clean(); |
302
|
|
|
|
303
|
|
|
return $return; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* Display base region list in Store Settings -> General |
308
|
|
|
* |
309
|
|
|
* @since 3.8.9 |
310
|
|
|
* @access private |
311
|
|
|
* |
312
|
|
|
* @uses WPSC_Settings_Tab_General |
313
|
|
|
* @uses WPSC_Settings_Tab_General::display_region_drop_down() Shows region dropdown |
314
|
|
|
* |
315
|
|
|
* @return array $return Response args |
|
|
|
|
316
|
|
|
*/ |
317
|
|
|
function _wpsc_ajax_display_region_list() { |
318
|
|
|
require_once( 'settings-page.php' ); |
319
|
|
|
require_once( 'includes/settings-tabs/general.php' ); |
320
|
|
|
|
321
|
|
|
$return = array(); |
322
|
|
|
ob_start(); |
323
|
|
|
$tab = new WPSC_Settings_Tab_General(); |
324
|
|
|
$tab->display_region_drop_down(); |
325
|
|
|
$return['content'] = ob_get_clean(); |
326
|
|
|
|
327
|
|
|
return $return; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* Save tracking ID of a sales log. |
332
|
|
|
* |
333
|
|
|
* @since 3.8.9 |
334
|
|
|
* @access private |
335
|
|
|
* |
336
|
|
|
* @uses WP_Error WordPress Error class |
337
|
|
|
* |
338
|
|
|
* @return array|WP_Error $return Response args if successful, WP_Error if otherwise. |
|
|
|
|
339
|
|
|
*/ |
340
|
|
|
function _wpsc_ajax_purchase_log_save_tracking_id() { |
341
|
|
|
global $wpdb; |
342
|
|
|
|
343
|
|
|
$result = $wpdb->update( |
344
|
|
|
WPSC_TABLE_PURCHASE_LOGS, |
345
|
|
|
array( |
346
|
|
|
'track_id' => $_POST['value'] |
347
|
|
|
), |
348
|
|
|
array( |
349
|
|
|
'id' => $_POST['log_id'] |
350
|
|
|
), |
351
|
|
|
'%s', |
352
|
|
|
'%d' |
353
|
|
|
); |
354
|
|
|
|
355
|
|
|
if ( ! $result ) |
356
|
|
|
return new WP_Error( 'wpsc_cannot_save_tracking_id', __( "Couldn't save tracking ID of the transaction. Please try again.", 'wp-e-commerce' ) ); |
357
|
|
|
|
358
|
|
|
$return = array( |
359
|
|
|
'rows_affected' => $result, |
360
|
|
|
'id' => $_POST['log_id'], |
361
|
|
|
'track_id' => $_POST['value'], |
362
|
|
|
); |
363
|
|
|
|
364
|
|
|
return $return; |
365
|
|
|
} |
366
|
|
|
|
367
|
|
|
/** |
368
|
|
|
* Send sales log tracking email via AJAX |
369
|
|
|
* |
370
|
|
|
* @since 3.8.9 |
371
|
|
|
* @access private |
372
|
|
|
* |
373
|
|
|
* @uses $wpdb WordPress database object for queries |
374
|
|
|
* @uses get_option() Gets option from DB given key |
375
|
|
|
* @uses add_filter() Calls 'wp_mail_from' which can replace the from email address |
376
|
|
|
* @uses add_filter() Calls 'wp_mail_from_name' allows replacement of the from name on WordPress emails |
377
|
|
|
* @uses wp_mail() All the emailses in WordPress are sent through this function |
378
|
|
|
* @uses WP_Error WordPress Error class |
379
|
|
|
* |
380
|
|
|
* @return array|WP_Error $return Response args if successful, WP_Error if otherwise |
|
|
|
|
381
|
|
|
*/ |
382
|
|
|
function _wpsc_ajax_purchase_log_send_tracking_email() { |
383
|
|
|
global $wpdb; |
384
|
|
|
|
385
|
|
|
$id = absint( $_POST['log_id'] ); |
386
|
|
|
$sql = $wpdb->prepare( "SELECT `track_id` FROM " . WPSC_TABLE_PURCHASE_LOGS . " WHERE `id`=%d LIMIT 1", $id ); |
387
|
|
|
$trackingid = $wpdb->get_var( $sql ); |
388
|
|
|
|
389
|
|
|
$message = get_option( 'wpsc_trackingid_message' ); |
390
|
|
|
$message = str_replace( '%trackid%', $trackingid, $message ); |
391
|
|
|
$message = str_replace( '%shop_name%', get_option( 'blogname' ), $message ); |
392
|
|
|
|
393
|
|
|
$email = wpsc_get_buyers_email( $id ); |
394
|
|
|
|
395
|
|
|
$subject = get_option( 'wpsc_trackingid_subject' ); |
396
|
|
|
$subject = str_replace( '%shop_name%', get_option( 'blogname' ), $subject ); |
397
|
|
|
|
398
|
|
|
add_filter( 'wp_mail_from', 'wpsc_replace_reply_address', 0 ); |
399
|
|
|
add_filter( 'wp_mail_from_name', 'wpsc_replace_reply_name', 0 ); |
400
|
|
|
|
401
|
|
|
$result = wp_mail( $email, $subject, $message); |
402
|
|
|
|
403
|
|
|
if ( ! $result ) { |
404
|
|
|
return new WP_Error( 'wpsc_cannot_send_tracking_email', __( "Couldn't send tracking email. Please try again.", 'wp-e-commerce' ) ); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
$return = array( |
408
|
|
|
'id' => $id, |
409
|
|
|
'tracking_id' => $trackingid, |
410
|
|
|
'subject' => $subject, |
411
|
|
|
'message' => $message, |
412
|
|
|
'email' => $email |
413
|
|
|
); |
414
|
|
|
|
415
|
|
|
return $return; |
416
|
|
|
} |
417
|
|
|
|
418
|
|
|
/** |
419
|
|
|
* Do purchase log action link via AJAX |
420
|
|
|
* |
421
|
|
|
* @since 3.9.0 |
422
|
|
|
* @access private |
423
|
|
|
* |
424
|
|
|
* @return array|WP_Error $return Response args if successful, WP_Error if otherwise |
425
|
|
|
*/ |
426
|
|
|
function _wpsc_ajax_purchase_log_action_link() { |
427
|
|
|
|
428
|
|
|
if ( isset( $_POST['log_id'] ) && isset( $_POST['purchase_log_action_link'] ) && isset( $_POST['purchase_log_action_nonce'] ) ) { |
429
|
|
|
|
430
|
|
|
$log_id = absint( $_POST['log_id'] ); |
431
|
|
|
$purchase_log_action_link = sanitize_key( $_POST['purchase_log_action_link'] ); |
432
|
|
|
|
433
|
|
|
// Verify action nonce |
434
|
|
|
if ( wp_verify_nonce( $_POST['purchase_log_action_nonce'], 'wpsc_purchase_log_action_ajax_' . $purchase_log_action_link ) ) { |
435
|
|
|
|
436
|
|
|
// Expected to receive success = true by default, or false on error. |
437
|
|
|
$return = apply_filters( 'wpsc_purchase_log_action_ajax-' . $purchase_log_action_link, array( 'success' => null ), $log_id ); |
438
|
|
|
|
439
|
|
|
} else { |
440
|
|
|
$return = _wpsc_error_invalid_nonce(); |
441
|
|
|
} |
442
|
|
|
|
443
|
|
|
if ( ! is_wp_error( $return ) ) { |
444
|
|
|
$return['log_id'] = $log_id; |
445
|
|
|
$return['purchase_log_action_link'] = $purchase_log_action_link; |
446
|
|
|
$return['success'] = isset( $return['success'] ) ? (bool) $return['success'] : null; |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
return $return; |
450
|
|
|
|
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
return new WP_Error( 'wpsc_ajax_invalid_purchase_log_action', __( 'Purchase log action failed.', 'wp-e-commerce' ) ); |
454
|
|
|
|
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
/** |
458
|
|
|
* Remove purchase log item. |
459
|
|
|
* |
460
|
|
|
* @since 4.0 |
461
|
|
|
* @access private |
462
|
|
|
* |
463
|
|
|
* @return array|WP_Error $return Response args if successful, WP_Error if otherwise |
464
|
|
|
*/ |
465
|
|
|
function _wpsc_ajax_remove_log_item() { |
466
|
|
|
|
467
|
|
|
if ( isset( $_POST['item_id'], $_POST['log_id'] ) ) { |
468
|
|
|
|
469
|
|
|
$item_id = absint( $_POST['item_id'] ); |
470
|
|
|
$log_id = absint( $_POST['log_id'] ); |
471
|
|
|
$log = new WPSC_Purchase_Log( $log_id ); |
472
|
|
|
|
473
|
|
|
if ( $log->remove_cart_item( $item_id ) ) { |
474
|
|
|
return _wpsc_init_log_items( $log ); |
475
|
|
|
} |
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
return new WP_Error( 'wpsc_ajax_invalid_remove_log_item', __( 'Removing log item failed.', 'wp-e-commerce' ) ); |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
/** |
482
|
|
|
* Update purchase log item quantity. |
483
|
|
|
* |
484
|
|
|
* @since 4.0 |
485
|
|
|
* @access private |
486
|
|
|
* |
487
|
|
|
* @return array|WP_Error $return Response args if successful, WP_Error if otherwise |
488
|
|
|
*/ |
489
|
|
|
function _wpsc_ajax_update_log_item_qty() { |
490
|
|
|
|
491
|
|
|
if ( isset( $_POST['item_id'], $_POST['log_id'], $_POST['qty'] ) ) { |
492
|
|
|
|
493
|
|
|
if ( empty( $_POST['qty'] ) ) { |
494
|
|
|
return _wpsc_ajax_remove_log_item(); |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
$item_id = absint( $_POST['item_id'] ); |
498
|
|
|
$log_id = absint( $_POST['log_id'] ); |
499
|
|
|
$log = new WPSC_Purchase_Log( $log_id ); |
500
|
|
|
$result = $log->update_cart_item( $item_id, array( 'quantity' => absint( $_POST['qty'] ) ) ); |
501
|
|
|
|
502
|
|
|
if ( 0 === $result ) { |
503
|
|
|
return true; |
504
|
|
|
} elseif ( false !== $result ) { |
505
|
|
|
return _wpsc_init_log_items( $log ); |
506
|
|
|
} |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
return new WP_Error( 'wpsc_ajax_invalid_update_log_item_qty', __( 'Updating log item quantity failed.', 'wp-e-commerce' ) ); |
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
/** |
513
|
|
|
* Add purchase log item. |
514
|
|
|
* |
515
|
|
|
* @since 4.0 |
516
|
|
|
* @access private |
517
|
|
|
* |
518
|
|
|
* @return array|WP_Error $return Response args if successful, WP_Error if otherwise |
519
|
|
|
*/ |
520
|
|
|
function _wpsc_ajax_add_log_item() { |
521
|
|
|
global $wpsc_cart; |
522
|
|
|
|
523
|
|
|
if ( |
524
|
|
|
isset( $_POST['product_ids'], $_POST['log_id'] ) |
525
|
|
|
&& is_array( $_POST['product_ids'] ) |
526
|
|
|
&& ! empty( $_POST['product_ids'] ) |
527
|
|
|
) { |
528
|
|
|
|
529
|
|
|
$existing = isset( $_POST['existing'] ) && is_array( $_POST['existing'] ) |
530
|
|
|
? array_map( 'absint', $_POST['existing'] ) |
531
|
|
|
: false; |
532
|
|
|
|
533
|
|
|
$item_ids = array(); |
534
|
|
|
|
535
|
|
|
foreach ( $_POST['product_ids'] as $product_id ) { |
536
|
|
|
$product_id = absint( $product_id ); |
537
|
|
|
$log_id = absint( $_POST['log_id'] ); |
538
|
|
|
$log = new WPSC_Purchase_Log( $log_id ); |
539
|
|
|
|
540
|
|
|
// Is product is already in item list? |
541
|
|
|
if ( $existing && in_array( $product_id, $existing, true ) ) { |
542
|
|
|
$item = $log->get_cart_item_from_product_id( $product_id ); |
543
|
|
|
if ( $item ) { |
544
|
|
|
// Update item quantity... |
545
|
|
|
$log->update_cart_item( $item->id, array( 'quantity' => ++$item->quantity ) ); |
546
|
|
|
// And move on. |
547
|
|
|
continue; |
548
|
|
|
} |
549
|
|
|
} |
550
|
|
|
|
551
|
|
|
$item = new wpsc_cart_item( $product_id, array(), $wpsc_cart ); |
552
|
|
|
$item_id = $item->save_to_db( $log_id ); |
553
|
|
|
$item_ids[] = absint( $item_id ); |
554
|
|
|
} |
555
|
|
|
|
556
|
|
|
return _wpsc_init_log_items( $log, $item_ids ); |
|
|
|
|
557
|
|
|
} |
558
|
|
|
|
559
|
|
|
return new WP_Error( 'wpsc_ajax_invalid_add_log_item', __( 'Adding log item failed.', 'wp-e-commerce' ) ); |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
function _wpsc_init_log_items( WPSC_Purchase_Log $log, $item_ids = array() ) { |
563
|
|
|
$log->init_items(); |
564
|
|
|
|
565
|
|
|
require_once( WPSC_FILE_PATH . '/wpsc-admin/display-sales-logs.php' ); |
566
|
|
|
|
567
|
|
|
$html = ''; |
568
|
|
|
$htmls[] = array(); |
|
|
|
|
569
|
|
|
|
570
|
|
|
while ( wpsc_have_purchaselog_details() ) { |
571
|
|
|
wpsc_the_purchaselog_item(); |
572
|
|
|
|
573
|
|
|
ob_start(); |
574
|
|
|
WPSC_Purchase_Log_Page::purchase_log_cart_item( $log->can_edit() ); |
575
|
|
|
$cart_item = ob_get_clean(); |
576
|
|
|
|
577
|
|
|
$htmls[ wpsc_purchaselog_details_id() ] = $cart_item; |
578
|
|
|
if ( ! empty( $item_ids ) && in_array( absint( wpsc_purchaselog_details_id() ), $item_ids, true ) ) { |
579
|
|
|
$html .= $cart_item; |
580
|
|
|
} |
581
|
|
|
} |
582
|
|
|
|
583
|
|
|
return array( |
584
|
|
|
'quantities' => wp_list_pluck( $log->get_items(), 'quantity', 'id' ), |
585
|
|
|
'html' => $html, |
586
|
|
|
'htmls' => $htmls, |
587
|
|
|
'discount_data' => wpsc_purchlog_has_discount_data() ? esc_html__( 'Coupon Code', 'wp-e-commerce' ) . ': ' . wpsc_display_purchlog_discount_data() : '', |
588
|
|
|
'discount' => wpsc_display_purchlog_discount(), |
589
|
|
|
'total_taxes' => wpsc_display_purchlog_taxes(), |
590
|
|
|
'total_shipping' => wpsc_display_purchlog_shipping(), |
591
|
|
|
'final_total' => wpsc_display_purchlog_totalprice(), |
592
|
|
|
); |
593
|
|
|
} |
594
|
|
|
|
595
|
|
|
/** |
596
|
|
|
* Search for products. |
597
|
|
|
* |
598
|
|
|
* @since 4.0 |
599
|
|
|
* @access private |
600
|
|
|
* |
601
|
|
|
* @return array|WP_Error $return Response args if successful, WP_Error if otherwise |
602
|
|
|
*/ |
603
|
|
|
function _wpsc_ajax_search_products() { |
604
|
|
|
$pt_object = get_post_type_object( 'wpsc-product' ); |
605
|
|
|
|
606
|
|
|
$s = wp_unslash( $_POST['search'] ); |
607
|
|
|
$args = array( |
608
|
|
|
'post_type' => 'wpsc-product', |
609
|
|
|
'post_status' => array( 'publish', 'inherit' ), |
610
|
|
|
'posts_per_page' => 50, |
611
|
|
|
); |
612
|
|
|
if ( '' !== $s ) { |
613
|
|
|
$args['s'] = $s; |
614
|
|
|
} |
615
|
|
|
|
616
|
|
|
$posts = get_posts( $args ); |
617
|
|
|
|
618
|
|
|
if ( ! $posts ) { |
619
|
|
|
return new WP_Error( 'wpsc_ajax_invalid_search_products', __( 'No items found.', 'wp-e-commerce' ) ); |
620
|
|
|
} |
621
|
|
|
|
622
|
|
|
$alt = ''; |
623
|
|
|
foreach ( $posts as $post ) { |
624
|
|
|
$post->title = trim( $post->post_title ) ? $post->post_title : __( '(no title)' ); |
625
|
|
|
$alt = ( 'alternate' === $alt ) ? '' : 'alternate'; |
626
|
|
|
|
627
|
|
|
$post->status = $post->post_status; |
628
|
|
|
|
629
|
|
|
switch ( $post->post_status ) { |
630
|
|
|
case 'publish' : |
631
|
|
|
case 'private' : |
632
|
|
|
$post->status = __( 'Published' ); |
633
|
|
|
break; |
634
|
|
|
case 'future' : |
635
|
|
|
$post->status = __( 'Scheduled' ); |
636
|
|
|
break; |
637
|
|
|
case 'pending' : |
638
|
|
|
$post->status = __( 'Pending Review' ); |
639
|
|
|
break; |
640
|
|
|
case 'draft' : |
641
|
|
|
$post->status = __( 'Draft' ); |
642
|
|
|
break; |
643
|
|
|
default : |
644
|
|
|
$post->status = $post->post_status; |
645
|
|
|
break; |
646
|
|
|
} |
647
|
|
|
|
648
|
|
|
if ( '0000-00-00 00:00:00' === $post->post_date ) { |
649
|
|
|
$post->time = ''; |
650
|
|
|
} else { |
651
|
|
|
/* translators: date format in table columns, see https://secure.php.net/date */ |
652
|
|
|
$post->time = mysql2date( __( 'Y/m/d' ), $post->post_date ); |
653
|
|
|
} |
654
|
|
|
|
655
|
|
|
$post->class = $alt; |
656
|
|
|
} |
657
|
|
|
|
658
|
|
|
return $posts; |
659
|
|
|
} |
660
|
|
|
|
661
|
|
|
/** |
662
|
|
|
* Handle AJAX clear downloads lock purchase log action |
663
|
|
|
* |
664
|
|
|
* The _wpsc_ajax_purchase_log_action_link() function which triggers this function is nonce |
665
|
|
|
* and capability checked in _wpsc_ajax_handler(). |
666
|
|
|
* |
667
|
|
|
* @since 3.9.0 |
668
|
|
|
* @access private |
669
|
|
|
* |
670
|
|
|
* @param array $response AJAX response. |
671
|
|
|
* @param int $log_id Purchase log ID. |
672
|
|
|
*/ |
673
|
|
|
function wpsc_purchase_log_action_ajax_downloads_lock( $response, $log_id ) { |
674
|
|
|
|
675
|
|
|
$response['success'] = wpsc_purchlog_clear_download_items( $log_id ); |
676
|
|
|
|
677
|
|
|
return $response; |
678
|
|
|
|
679
|
|
|
} |
680
|
|
|
add_action( 'wpsc_purchase_log_action_ajax-downloads_lock', 'wpsc_purchase_log_action_ajax_downloads_lock', 10, 2 ); |
681
|
|
|
|
682
|
|
|
|
683
|
|
|
/** |
684
|
|
|
* Handle AJAX email receipt purchase log action |
685
|
|
|
* |
686
|
|
|
* The _wpsc_ajax_purchase_log_action_link() function which triggers this function is nonce |
687
|
|
|
* and capability checked in _wpsc_ajax_handler(). |
688
|
|
|
* |
689
|
|
|
* @since 3.9.0 |
690
|
|
|
* @access private |
691
|
|
|
* |
692
|
|
|
* @param array $response AJAX response. |
693
|
|
|
* @param int $log_id Purchase log ID. |
694
|
|
|
*/ |
695
|
|
|
function wpsc_purchase_log_action_ajax_email_receipt( $response, $log_id ) { |
696
|
|
|
|
697
|
|
|
$response['success'] = wpsc_purchlog_resend_email( $log_id ); |
698
|
|
|
|
699
|
|
|
return $response; |
700
|
|
|
|
701
|
|
|
} |
702
|
|
|
add_action( 'wpsc_purchase_log_action_ajax-email_receipt', 'wpsc_purchase_log_action_ajax_email_receipt', 10, 2 ); |
703
|
|
|
|
704
|
|
|
/** |
705
|
|
|
* Delete an attached downloadable file via AJAX. |
706
|
|
|
* |
707
|
|
|
* @since 3.8.9 |
708
|
|
|
* @access private |
709
|
|
|
* |
710
|
|
|
* @uses _wpsc_delete_file() Deletes files associated with a product |
711
|
|
|
* @uses WP_Error WordPress error class |
712
|
|
|
* |
713
|
|
|
* @return array|WP_Error $return Response args if successful, WP_Error if otherwise |
|
|
|
|
714
|
|
|
*/ |
715
|
|
|
function _wpsc_ajax_delete_file() { |
716
|
|
|
$product_id = absint( $_REQUEST['product_id'] ); |
717
|
|
|
$file_name = basename( $_REQUEST['file_name'] ); |
718
|
|
|
|
719
|
|
|
$result = _wpsc_delete_file( $product_id, $file_name ); |
720
|
|
|
|
721
|
|
|
if ( ! $result ) |
722
|
|
|
return new WP_Error( 'wpsc_cannot_delete_file', __( "Couldn't delete the file. Please try again.", 'wp-e-commerce' ) ); |
723
|
|
|
|
724
|
|
|
$return = array( |
725
|
|
|
'product_id' => $product_id, |
726
|
|
|
'file_name' => $file_name, |
727
|
|
|
); |
728
|
|
|
|
729
|
|
|
return $return; |
730
|
|
|
} |
731
|
|
|
|
732
|
|
|
/** |
733
|
|
|
* Delete a product meta via AJAX |
734
|
|
|
* |
735
|
|
|
* @since 3.8.9 |
736
|
|
|
* @access private |
737
|
|
|
* |
738
|
|
|
* @uses delete_meta() Deletes metadata by meta id |
739
|
|
|
* @uses WP_Error WordPress error class |
740
|
|
|
* |
741
|
|
|
* @return array|WP_Error $return Response args if successful, WP_Error if otherwise |
|
|
|
|
742
|
|
|
*/ |
743
|
|
|
function _wpsc_ajax_remove_product_meta() { |
744
|
|
|
$meta_id = (int) $_POST['meta_id']; |
745
|
|
|
if ( ! delete_meta( $meta_id ) ) |
746
|
|
|
return new WP_Error( 'wpsc_cannot_delete_product_meta', __( "Couldn't delete product meta. Please try again.", 'wp-e-commerce' ) ); |
747
|
|
|
|
748
|
|
|
return array( 'meta_id' => $meta_id ); |
749
|
|
|
} |
750
|
|
|
|
751
|
|
|
/** |
752
|
|
|
* Modify a purchase log's status. |
753
|
|
|
* |
754
|
|
|
* @since 3.8.9 |
755
|
|
|
* @access private |
756
|
|
|
* |
757
|
|
|
* @uses wpsc_purchlog_edit_status() Edits purchase log status |
758
|
|
|
* @uses WP_Error WordPress Error class |
759
|
|
|
* @uses WPSC_Purchase_Log_List_Table |
760
|
|
|
* @uses WPSC_Purchase_Log_List_Table::prepare_items() |
761
|
|
|
* @uses WPSC_Purchase_Log_List_Table::views() |
762
|
|
|
* @uses WPSC_Purchase_Log_List_Table::display_tablenav() @todo docs |
763
|
|
|
* |
764
|
|
|
* @return array|WP_Error $return Response args if successful, WP_Error if otherwise. |
|
|
|
|
765
|
|
|
*/ |
766
|
|
|
function _wpsc_ajax_change_purchase_log_status() { |
767
|
|
|
$result = wpsc_purchlog_edit_status( $_POST['id'], $_POST['new_status'] ); |
768
|
|
|
if ( ! $result ) |
769
|
|
|
return new WP_Error( 'wpsc_cannot_edit_purchase_log_status', __( "Couldn't modify purchase log's status. Please try again.", 'wp-e-commerce' ) ); |
770
|
|
|
|
771
|
|
|
$args = array(); |
772
|
|
|
|
773
|
|
|
$args['screen'] = 'dashboard_page_wpsc-sales-logs'; |
774
|
|
|
|
775
|
|
|
require_once( WPSC_FILE_PATH . '/wpsc-admin/includes/purchase-log-list-table-class.php' ); |
776
|
|
|
$purchaselog_table = new WPSC_Purchase_Log_List_Table( $args ); |
777
|
|
|
$purchaselog_table->prepare_items(); |
778
|
|
|
|
779
|
|
|
ob_start(); |
780
|
|
|
$purchaselog_table->views(); |
781
|
|
|
$views = ob_get_clean(); |
782
|
|
|
|
783
|
|
|
ob_start(); |
784
|
|
|
$purchaselog_table->display_tablenav( 'top' ); |
785
|
|
|
$tablenav_top = ob_get_clean(); |
786
|
|
|
|
787
|
|
|
ob_start(); |
788
|
|
|
$purchaselog_table->display_tablenav( 'bottom' ); |
789
|
|
|
$tablenav_bottom = ob_get_clean(); |
790
|
|
|
|
791
|
|
|
$return = array( |
792
|
|
|
'id' => $_POST['id'], |
793
|
|
|
'new_status' => $_POST['new_status'], |
794
|
|
|
'views' => $views, |
795
|
|
|
'tablenav_top' => $tablenav_top, |
796
|
|
|
'tablenav_bottom' => $tablenav_bottom, |
797
|
|
|
); |
798
|
|
|
|
799
|
|
|
return $return; |
800
|
|
|
} |
801
|
|
|
|
802
|
|
|
/** |
803
|
|
|
* Save product ordering after drag-and-drop sorting |
804
|
|
|
* |
805
|
|
|
* @since 3.8.9 |
806
|
|
|
* @access private |
807
|
|
|
* |
808
|
|
|
* @uses $wpdb WordPress database object for use in queries |
809
|
|
|
* @uses wp_update_post() Updates post based on passed $args. Needs a post_id |
810
|
|
|
* @uses WP_Error WordPress Error class |
811
|
|
|
* |
812
|
|
|
* @return array|WP_Error Response args if successful, WP_Error if otherwise |
|
|
|
|
813
|
|
|
*/ |
814
|
|
|
function _wpsc_ajax_save_product_order() { |
815
|
|
|
|
816
|
|
|
$products = array( ); |
|
|
|
|
817
|
|
|
foreach ( $_POST['post'] as $product ) { |
818
|
|
|
$products[] = (int) str_replace( 'post-', '', $product ); |
819
|
|
|
} |
820
|
|
|
|
821
|
|
|
$failed = array(); |
822
|
|
|
foreach ( $products as $order => $product_id ) { |
823
|
|
|
$result = wp_update_post( array( |
824
|
|
|
'ID' => $product_id, |
825
|
|
|
'menu_order' => $order, |
826
|
|
|
) ); |
827
|
|
|
|
828
|
|
|
if ( ! $result ) |
829
|
|
|
$failed[] = $product_id; |
830
|
|
|
} |
831
|
|
|
|
832
|
|
|
// Validate data before exposing to action |
833
|
|
|
$category = isset( $_POST['category_id'] ) ? get_term_by( 'slug', $_POST['category_id'], 'wpsc_product_category' ) : false; |
834
|
|
|
do_action( 'wpsc_save_product_order', $products, $category ); |
835
|
|
|
|
836
|
|
|
if ( ! empty( $failed ) ) { |
837
|
|
|
$error_data = array( |
838
|
|
|
'failed_ids' => $failed, |
839
|
|
|
); |
840
|
|
|
|
841
|
|
|
return new WP_Error( 'wpsc_cannot_save_product_sort_order', __( "Couldn't save the products' sort order. Please try again.", 'wp-e-commerce' ), $error_data ); |
842
|
|
|
} |
843
|
|
|
|
844
|
|
|
return array( |
845
|
|
|
'ids' => $products, |
846
|
|
|
); |
847
|
|
|
} |
848
|
|
|
|
849
|
|
|
/** |
850
|
|
|
* Save Category Product Order |
851
|
|
|
* |
852
|
|
|
* Note that this uses the 'term_order' field in the 'term_relationships' table to store |
853
|
|
|
* the order. Although this column presently seems to be unused by WordPress, the intention |
854
|
|
|
* is it should be used to store the order of terms associates to a post, not the order |
855
|
|
|
* of posts as we are doing. This shouldn't be an issue for WPEC unless WordPress adds a UI |
856
|
|
|
* for this. More info at http://core.trac.wordpress.org/ticket/9547 |
857
|
|
|
* |
858
|
|
|
* @since 3.9 |
859
|
|
|
* @access private |
860
|
|
|
* |
861
|
|
|
* @uses $wpdb WordPress database object used for queries |
862
|
|
|
*/ |
863
|
|
|
function _wpsc_save_category_product_order( $products, $category ) { |
864
|
|
|
global $wpdb; |
865
|
|
|
|
866
|
|
|
// Only save category product order if in category |
867
|
|
|
if ( ! $category ) |
868
|
|
|
return; |
869
|
|
|
|
870
|
|
|
// Save product order in term_relationships table |
871
|
|
|
foreach ( $products as $order => $product_id ) { |
872
|
|
|
$wpdb->update( $wpdb->term_relationships, |
873
|
|
|
array( 'term_order' => $order ), |
874
|
|
|
array( 'object_id' => $product_id, 'term_taxonomy_id' => $category->term_taxonomy_id ), |
875
|
|
|
array( '%d' ), |
876
|
|
|
array( '%d', '%d' ) |
877
|
|
|
); |
878
|
|
|
} |
879
|
|
|
} |
880
|
|
|
add_action( 'wpsc_save_product_order', '_wpsc_save_category_product_order', 10, 2 ); |
881
|
|
|
|
882
|
|
|
/** |
883
|
|
|
* Update Checkout fields order |
884
|
|
|
* |
885
|
|
|
* @since 3.8.9 |
886
|
|
|
* @access private |
887
|
|
|
* |
888
|
|
|
* @uses $wpdb WordPress database object used for queries |
889
|
|
|
* @uses WP_Error WordPress error class |
890
|
|
|
* |
891
|
|
|
* @return array|WP_Error Response args or WP_Error |
|
|
|
|
892
|
|
|
*/ |
893
|
|
|
function _wpsc_ajax_update_checkout_fields_order() { |
894
|
|
|
global $wpdb; |
895
|
|
|
|
896
|
|
|
$checkout_fields = $_REQUEST['sort_order']; |
897
|
|
|
$order = 1; |
898
|
|
|
$failed = array(); |
899
|
|
|
$modified = array(); |
900
|
|
|
foreach ( $checkout_fields as &$checkout_field ) { |
901
|
|
|
// ignore new fields |
902
|
|
|
if ( strpos( $checkout_field, 'new-field' ) === 0 ) |
903
|
|
|
continue; |
904
|
|
|
$checkout_field = absint( preg_replace('/[^0-9]+/', '', $checkout_field ) ); |
905
|
|
|
$result = $wpdb->update( |
906
|
|
|
WPSC_TABLE_CHECKOUT_FORMS, |
907
|
|
|
array( |
908
|
|
|
'checkout_order' => $order |
909
|
|
|
), |
910
|
|
|
array( |
911
|
|
|
'id' => $checkout_field |
912
|
|
|
), |
913
|
|
|
'%d', |
914
|
|
|
'%d' |
915
|
|
|
); |
916
|
|
|
$order ++; |
917
|
|
|
if ( $result === false ) |
918
|
|
|
$failed[] = $checkout_field; |
919
|
|
|
elseif ( $result > 0 ) |
920
|
|
|
$modified[] = $checkout_field; |
921
|
|
|
} |
922
|
|
|
|
923
|
|
|
if ( ! empty( $failed ) ) |
924
|
|
|
return new WP_Error( 'wpsc_cannot_save_checkout_field_sort_order', __( "Couldn't save checkout field sort order. Please try again.", 'wp-e-commerce' ), array( 'failed_ids' => $failed ) ); |
925
|
|
|
|
926
|
|
|
return array( |
927
|
|
|
'modified' => $modified, |
928
|
|
|
); |
929
|
|
|
} |
930
|
|
|
|
931
|
|
|
/** |
932
|
|
|
* Save a downloadable file to a product |
933
|
|
|
* |
934
|
|
|
* @since 3.8.9 |
935
|
|
|
* @access private |
936
|
|
|
* |
937
|
|
|
* @uses $wpdb WordPress database object for use in queries |
938
|
|
|
* @uses _wpsc_create_ajax_nonce() Creates nonce for an ajax action |
939
|
|
|
* @uses wpsc_get_mimetype() Returns mimetype of file |
940
|
|
|
* @uses wp_insert_post() Inserts post to WordPress database |
941
|
|
|
* @uses wp_nonce_url() Retrieve URL with nonce added to URL query. |
942
|
|
|
* @uses wpsc_convert_bytes() Formats bytes |
943
|
|
|
* @uses wpsc_get_extension() Gets extension of file |
944
|
|
|
* @uses esc_attr() Escapes HTML attributes |
945
|
|
|
* @uses _x() Retrieve translated string with gettext context |
946
|
|
|
* |
947
|
|
|
* @return array|WP_Error Response args if successful, WP_Error if otherwise. |
948
|
|
|
*/ |
949
|
|
|
function _wpsc_ajax_upload_product_file() { |
950
|
|
|
global $wpdb; |
951
|
|
|
$product_id = absint( $_POST["product_id"] ); |
952
|
|
|
$output = ''; |
953
|
|
|
$delete_nonce = _wpsc_create_ajax_nonce( 'delete_file' ); |
954
|
|
|
|
955
|
|
|
foreach ( $_POST["select_product_file"] as $selected_file ) { |
956
|
|
|
// if we already use this file, there is no point doing anything more. |
957
|
|
|
$sql = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_type = 'wpsc-product-file' AND post_title = %s", $selected_file ); // TODO it's safer to select by post ID, in that case we will use get_posts() |
958
|
|
|
$file_post_data = $wpdb->get_row( $sql, ARRAY_A ); |
959
|
|
|
$selected_file_path = WPSC_FILE_DIR . basename( $selected_file ); |
960
|
|
|
$file_url = WPSC_FILE_URL . basename( $selected_file ); |
961
|
|
|
$file_size = filesize( $selected_file_path ); |
962
|
|
|
if ( empty( $file_post_data ) ) { |
963
|
|
|
$type = wpsc_get_mimetype( $selected_file_path ); |
964
|
|
|
$attachment = array( |
965
|
|
|
'post_mime_type' => $type, |
966
|
|
|
'post_parent' => $product_id, |
967
|
|
|
'post_title' => $selected_file, |
968
|
|
|
'post_content' => '', |
969
|
|
|
'post_type' => "wpsc-product-file", |
970
|
|
|
'post_status' => 'inherit' |
971
|
|
|
); |
972
|
|
|
$id = wp_insert_post( $attachment ); |
973
|
|
|
} else { |
974
|
|
|
// already attached |
975
|
|
|
if ( $file_post_data['post_parent'] == $product_id ) |
976
|
|
|
continue; |
977
|
|
|
$type = $file_post_data["post_mime_type"]; |
978
|
|
|
$url = $file_post_data["guid"]; |
979
|
|
|
$title = $file_post_data["post_title"]; |
980
|
|
|
$content = $file_post_data["post_content"]; |
981
|
|
|
// Construct the attachment |
982
|
|
|
$attachment = array( |
983
|
|
|
'post_mime_type' => $type, |
984
|
|
|
'guid' => $url, |
985
|
|
|
'post_parent' => absint( $product_id ), |
986
|
|
|
'post_title' => $title, |
987
|
|
|
'post_content' => $content, |
988
|
|
|
'post_type' => "wpsc-product-file", |
989
|
|
|
'post_status' => 'inherit' |
990
|
|
|
); |
991
|
|
|
// Save the data |
992
|
|
|
$id = wp_insert_post( $attachment ); |
993
|
|
|
} |
994
|
|
|
|
995
|
|
|
$deletion_url = wp_nonce_url( "admin.php?wpsc_admin_action=delete_file&file_name={$attachment['post_title']}&product_id={$product_id}", 'delete_file_' . $attachment['post_title'] ); |
996
|
|
|
|
997
|
|
|
$output .= '<tr class="wpsc_product_download_row">'; |
998
|
|
|
$output .= '<td style="padding-right: 30px;">' . $attachment['post_title'] . '</td>'; |
999
|
|
|
$output .= '<td>' . wpsc_convert_byte( $file_size ) . '</td>'; |
1000
|
|
|
$output .= '<td>.' . wpsc_get_extension( $attachment['post_title'] ) . '</td>'; |
1001
|
|
|
$output .= "<td><a data-file-name='" . esc_attr( $attachment['post_title'] ) . "' data-product-id='" . esc_attr( $product_id ) . "' data-nonce='" . esc_attr( $delete_nonce ) . "' class='file_delete_button' href='{$deletion_url}' >" . _x( 'Delete', 'Digital Download UI row', 'wp-e-commerce' ) . "</a></td>"; |
1002
|
|
|
$output .= '<td><a href=' .$file_url .'>' . _x( 'Download', 'Digital Download UI row', 'wp-e-commerce' ) . '</a></td>'; |
1003
|
|
|
$output .= '</tr>'; |
1004
|
|
|
} |
1005
|
|
|
|
1006
|
|
|
return array( |
1007
|
|
|
'content' => $output, |
1008
|
|
|
); |
1009
|
|
|
} |
1010
|
|
|
|
1011
|
|
|
/** |
1012
|
|
|
* Generate variations |
1013
|
|
|
* |
1014
|
|
|
* @since 3.8.9 |
1015
|
|
|
* @access private |
1016
|
|
|
* |
1017
|
|
|
* @uses wpsc_update_variations() Updates product variations given |
1018
|
|
|
* @uses wpsc_admin_product_listing() DEPRECATED |
1019
|
|
|
* |
1020
|
|
|
* @return array|WP_Error Response args if successful, WP_Error if otherwise |
1021
|
|
|
*/ |
1022
|
|
|
function _wpsc_ajax_update_variations() { |
1023
|
|
|
$product_id = absint( $_REQUEST["product_id"] ); |
1024
|
|
|
wpsc_update_variations(); |
1025
|
|
|
|
1026
|
|
|
ob_start(); |
1027
|
|
|
wpsc_admin_product_listing( $product_id ); |
1028
|
|
|
$content = ob_get_clean(); |
1029
|
|
|
|
1030
|
|
|
return array( 'content' => $content ); |
1031
|
|
|
} |
1032
|
|
|
|
1033
|
|
|
/** |
1034
|
|
|
* Display the shortcode generator. |
1035
|
|
|
* |
1036
|
|
|
* @since 3.8.9 |
1037
|
|
|
* @access private |
1038
|
|
|
*/ |
1039
|
|
|
function _wpsc_action_tinymce_window() { |
1040
|
|
|
require_once( WPSC_CORE_JS_PATH . '/tinymce3/window.php' ); |
1041
|
|
|
exit; |
1042
|
|
|
} |
1043
|
|
|
add_action( 'wp_ajax_wpsc_tinymce_window', '_wpsc_action_tinymce_window' ); |
1044
|
|
|
|
1045
|
|
|
/** |
1046
|
|
|
* Add tax rate |
1047
|
|
|
* @since 3.8.9 |
1048
|
|
|
* @access private |
1049
|
|
|
* |
1050
|
|
|
* @uses wpec_taxes_controller Contains all the logic to communicate with the taxes system |
1051
|
|
|
* @uses wpec_taxes_controller::wpec_taxes::wpec_taxes_get_regions() Gets tax regions based on input country code |
1052
|
|
|
* @uses wpec_taxes_controller::wpec_taxes_build_select_options() Returns HTML formatted options from input array |
1053
|
|
|
* @uses wpec_taxes_controller::wpec_taxes_build_form() Builds the tax rate form |
1054
|
|
|
* @uses wpec_taxes_controller::wpec_taxes::wpec_taxes_get_band_from_index() Retrieves tax band for given name |
1055
|
|
|
* |
1056
|
|
|
* @return array|WP_Error Response args if successful, WP_Error if otherwise |
1057
|
|
|
*/ |
1058
|
|
|
function _wpsc_ajax_add_tax_rate() { |
1059
|
|
|
//include taxes controller |
1060
|
|
|
$wpec_taxes_controller = new wpec_taxes_controller; |
1061
|
|
|
|
1062
|
|
|
switch ( $_REQUEST['wpec_taxes_action'] ) { |
1063
|
|
|
case 'wpec_taxes_get_regions': |
1064
|
|
|
$regions = $wpec_taxes_controller->wpec_taxes->wpec_taxes_get_regions( $_REQUEST['country_code'] ); |
|
|
|
|
1065
|
|
|
$key = $_REQUEST['current_key']; |
1066
|
|
|
$type = $_REQUEST['taxes_type']; |
1067
|
|
|
$default_option = array( 'region_code' => 'all-markets', 'name' => 'All Markets' ); |
1068
|
|
|
$select_settings = array( |
1069
|
|
|
'id' => "{$type}-region-{$key}", |
1070
|
|
|
'name' => "wpsc_options[wpec_taxes_{$type}][{$key}][region_code]", |
1071
|
|
|
'class' => 'wpsc-taxes-region-drop-down' |
1072
|
|
|
); |
1073
|
|
|
$returnable = $wpec_taxes_controller->wpec_taxes_build_select_options( $regions, 'region_code', 'name', $default_option, $select_settings ); |
1074
|
|
|
break; |
1075
|
|
|
}// switch |
1076
|
|
|
|
1077
|
|
|
return array( |
1078
|
|
|
'content' => $returnable, |
|
|
|
|
1079
|
|
|
); |
1080
|
|
|
} |
1081
|
|
|
|
1082
|
|
|
/** |
1083
|
|
|
* Displays the WPSC product variations table |
1084
|
|
|
* |
1085
|
|
|
* @uses check_admin_referrer() Makes sure user was referred from another admin page |
1086
|
|
|
* @uses WPSC_Product_Variations_Page The WPSC Product variations class |
1087
|
|
|
* @uses WPSC_Product_Variations_Page::display() Displays the product variations page |
1088
|
|
|
*/ |
1089
|
|
|
function wpsc_product_variations_table() { |
1090
|
|
|
check_admin_referer( 'wpsc_product_variations_table' ); |
1091
|
|
|
set_current_screen( 'wpsc-product' ); |
1092
|
|
|
require_once( WPSC_FILE_PATH . '/wpsc-admin/includes/product-variations-page.class.php' ); |
1093
|
|
|
$page = new WPSC_Product_Variations_Page(); |
1094
|
|
|
$page->display(); |
1095
|
|
|
|
1096
|
|
|
exit; |
1097
|
|
|
} |
1098
|
|
|
add_action( 'wp_ajax_wpsc_product_variations_table', 'wpsc_product_variations_table' ); |
1099
|
|
|
|
1100
|
|
|
/** |
1101
|
|
|
* @access private |
1102
|
|
|
* |
1103
|
|
|
* @uses current_user_can() Checks user capabilities given string |
1104
|
|
|
* @uses delete_post_thumbnail() Deletes post thumbnail given thumbnail id |
1105
|
|
|
* @uses set_post_thumbnail() Sets post thumbnail given post_id and thumbnail_id |
1106
|
|
|
* @uses wpsc_the_product_thumbnail() Returns URL to the product thumbnail |
1107
|
|
|
* |
1108
|
|
|
* @return array $response Includes the thumbnail URL and success bool value |
|
|
|
|
1109
|
|
|
*/ |
1110
|
|
|
function _wpsc_ajax_set_variation_product_thumbnail() { |
1111
|
|
|
$response = array( |
1112
|
|
|
'success' => false |
1113
|
|
|
); |
1114
|
|
|
|
1115
|
|
|
$post_ID = intval( $_POST['post_id'] ); |
1116
|
|
|
if ( current_user_can( 'edit_post', $post_ID ) ) { |
1117
|
|
|
$thumbnail_id = intval( $_POST['thumbnail_id'] ); |
1118
|
|
|
|
1119
|
|
|
if ( $thumbnail_id == '-1' ) |
1120
|
|
|
delete_post_thumbnail( $post_ID ); |
1121
|
|
|
|
1122
|
|
|
set_post_thumbnail( $post_ID, $thumbnail_id ); |
1123
|
|
|
|
1124
|
|
|
$thumbnail = wpsc_the_product_thumbnail( 50, 50, $post_ID, '' ); |
1125
|
|
|
if ( ! $thumbnail ) |
1126
|
|
|
$thumbnail = WPSC_CORE_IMAGES_URL . '/no-image-uploaded.gif'; |
1127
|
|
|
$response['src'] = $thumbnail; |
1128
|
|
|
$response['success'] = true; |
1129
|
|
|
} |
1130
|
|
|
|
1131
|
|
|
echo json_encode( $response ); |
1132
|
|
|
exit; |
1133
|
|
|
} |
1134
|
|
|
add_action( 'wp_ajax_wpsc_set_variation_product_thumbnail', '_wpsc_ajax_set_variation_product_thumbnail' ); |
1135
|
|
|
|
1136
|
|
|
/** |
1137
|
|
|
* Delete WPSC product image from gallery |
1138
|
|
|
* |
1139
|
|
|
* @uses check_ajax_referer() Verifies the AJAX request to prevent processing external requests |
1140
|
|
|
* @uses get_post_meta() Returns meta from the specified post |
1141
|
|
|
* @uses update_post_meta() Updates meta from the specified post |
1142
|
|
|
*/ |
1143
|
|
|
function product_gallery_image_delete_action() { |
1144
|
|
|
|
1145
|
|
|
$product_gallery = array(); |
1146
|
|
|
$gallery_image_id = $gallery_post_id = ''; |
1147
|
|
|
|
1148
|
|
|
$gallery_image_id = absint($_POST['product_gallery_image_id']); |
1149
|
|
|
$gallery_post_id = absint($_POST['product_gallery_post_id']); |
1150
|
|
|
|
1151
|
|
|
check_ajax_referer( 'wpsc_gallery_nonce', 'wpsc_gallery_nonce_check' ); |
1152
|
|
|
|
1153
|
|
|
$product_gallery = get_post_meta( $gallery_post_id, '_wpsc_product_gallery', true ); |
1154
|
|
|
|
1155
|
|
|
foreach ( $product_gallery as $index => $image_id ) { |
1156
|
|
|
if ( $image_id == $gallery_image_id ) { |
1157
|
|
|
unset( $product_gallery[$index] ); |
1158
|
|
|
} |
1159
|
|
|
} |
1160
|
|
|
|
1161
|
|
|
update_post_meta( $gallery_post_id, '_wpsc_product_gallery', $product_gallery ); |
1162
|
|
|
} |
1163
|
|
|
add_action( 'wp_ajax_product_gallery_image_delete', 'product_gallery_image_delete_action' ); |
1164
|
|
|
|
This check compares the return type specified in the
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.If the return type contains the type array, this check recommends the use of a more specific type like
String[]
orarray<String>
.