Completed
Pull Request — master (#2165)
by Justin
05:44
created

WPSC_Cart_Item::refresh_item()   F

Complexity

Conditions 23
Paths 6144

Size

Total Lines 116
Code Lines 79

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 79
nc 6144
nop 0
dl 0
loc 116
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * WP eCommerce Cart Item class
4
 *
5
 * This is the class for WP eCommerce Cart Items,
6
 * The Cart Items class handles the same, but for cart items themselves.
7
 *
8
 * @package wp-e-commerce
9
 * @since 3.8
10
 * @subpackage wpsc-cart-classes
11
*/
12
13
/**
14
 * The WPSC Cart Items class
15
 */
16
class WPSC_Cart_Item {
17
18
	// Variation Cache
19
	private static $variation_cache;
20
21
	// each cart item contains a reference to the cart that it is a member of
22
	public $cart;
23
24
	// provided values
25
	public $product_id;
26
	public $variation_values;
27
	public $product_variations;
28
	public $variation_data;
29
	public $quantity = 1;
30
	public $provided_price;
31
32
	//values from the database
33
	public $product_name;
34
	public $category_list = array();
35
	public $category_id_list = array();
36
	public $unit_price;
37
	public $total_price;
38
	public $taxable_price = 0;
39
	public $tax = 0;
40
	public $weight = 0;
41
	public $shipping = 0;
42
	public $sku = null;
43
	public $product_url;
44
	public $image_id;
45
	public $thumbnail_image;
46
	public $custom_tax_rate = null;
47
	public $meta = array();
48
	public $stock = 1;
49
	public $tax_rate = 0.00;
50
	public $has_limited_stock = false;
51
	public $uses_shipping = 1;
52
	public $file_id = null;
53
	public $is_downloadable = false;
54
55
	private $item_meta = array();
56
57
	public $is_donation = false;
58
	public $apply_tax = true;
59
	public $priceandstock_id;
60
61
	// user provided values
62
	public $custom_message = '';
63
	public $custom_file = null;
64
65
	/**
66
	 * compare cart item meta
67
	 * @access public
68
	 * @param other cart item against which this items meta will be compared
69
	 * @return returns true if the cart item meta for this item is the same as is in the cart item in the argument
70
	 */
71
	function item_meta_equal( $other_cart_item ) {
72
		$my_item_meta_key    = serialize( $this->item_meta );
73
		$other_item_meta_key = serialize( $other_cart_item->item_meta );
74
75
		return strcmp( $my_item_meta_key, $other_item_meta_key ) == 0;
76
	}
77
78
	/**
79
	 * Delete cart item meta value
80
	 *
81
	 * @access public
82
	 * @param meta key name
83
	 * @param meta key value
84
	 * @return previous meta value if it existed, nothing otherwise
85
	 */
86
	function delete_meta( $key ) {
87
88
		if ( isset( $this->item_meta[ $key ] ) ) {
89
			$value = $this->item_meta[ $key ];
90
			unset( $this->item_meta[ $key ] );
91
			return $value;
92
		}
93
94
		return;
95
	}
96
97
	/**
98
	 * Update or add cart item meta value
99
	 *
100
	 * @access public
101
	 * @param meta key name
102
	 * @param meta key value
103
	 * @return previous meta value if it existed, null otherwise
104
	 */
105
	function update_meta( $key, $value = null ) {
106
107
		if ( ! isset( $value ) ) {
108
			$result = $this->delete_meta( $key );
109
		} else {
110
			$result = isset( $this->meta[ $key ] ) ? $this->meta[ $key ] : null;
111
			$this->item_meta[ $key ] = $value;
112
		}
113
114
		return $result;
115
	}
116
117
	/**
118
	 * Get cart item meta value
119
	 *
120
	 * @access public
121
	 * @param meta key name, optional, empty returns all meta as an array
122
	 * @return previous meta value if it existed, null otherwise
123
	 */
124
	function get_meta( $key = '' ) {
125
126
		if ( empty( $key ) ) {
127
			$result = $this->item_meta;
128
		} else {
129
			$result = isset( $this->item_meta[ $key ] ) ? $this->item_meta[ $key ] : null;
130
		}
131
132
		return $result;
133
	}
134
135
	public static function refresh_variation_cache() {
136
		global $wpsc_cart;
137
138
		$variation_product_ids = array();
139
140
		foreach ( $wpsc_cart->get_items() as $cart_item ) {
141
			if ( ! empty( $cart_item->variation_values ) )
142
				$variation_product_ids[] = $cart_item->product_id;
143
		}
144
145
		if ( empty( $variation_product_ids ) )
146
			return;
147
148
		self::$variation_cache = wp_get_object_terms( $variation_product_ids, 'wpsc-variation', array( 'fields' => 'all_with_object_id' ) );
149
150
		foreach ( self::$variation_cache as $term ) {
151
			if ( ! array_key_exists( $term->object_id, self::$variation_cache ) )
152
				self::$variation_cache[$term->object_id] = array();
153
154
			self::$variation_cache[$term->object_id][$term->parent] = $term->name;
155
		}
156
157
		return self::$variation_cache;
158
	}
159
160
	/**
161
	 * wpsc_cart_item constructor, requires a product ID and the parameters for the product
162
	 * @access public
163
	 *
164
	 * @param integer the product ID
165
	 * @param array parameters
166
	 * @param object  the cart object
167
	 * @return boolean true on sucess, false on failure
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
168
	 */
169
	function __construct( $product_id, $parameters, $cart ) {
170
171
		// still need to add the ability to limit the number of an item in the cart at once.
172
		// each cart item contains a reference to the cart that it is a member of, this makes that reference
173
		// The cart is in the cart item, which is in the cart, which is in the cart item, which is in the cart, which is in the cart item...
174
		$this->cart = &$cart;
175
176
		$parameters = wp_parse_args( $parameters, array(
177
			'is_customisable' => false,
178
			'file_data'       => null
179
		) );
180
181
		foreach ( $parameters as $name => $value ) {
182
			$this->$name = $value;
183
		}
184
185
		$this->product_id = absint( $product_id );
186
187
		// to preserve backwards compatibility, make product_variations a reference to variations.
188
		$this->product_variations =& $this->variation_values;
189
190
		if ( $parameters['is_customisable'] == true && $parameters['file_data'] != null ) {
191
			$this->save_provided_file( $parameters['file_data'] );
192
		}
193
194
		$this->refresh_item();
195
196
		if ( ! has_action( 'wpsc_add_item', array( 'wpsc_cart_item', 'refresh_variation_cache' ) ) ) {
197
			add_action( 'wpsc_add_item', array( 'wpsc_cart_item', 'refresh_variation_cache' ) );
198
		}
199
200
	}
201
202
	/**
203
	 * update item method, currently can only update the quantity
204
	 * will require the parameters to update (no, you cannot change the product ID, delete the item and make a new one)
205
	 * @access public
206
	 *
207
	 * @param integer quantity
208
	 * #@param array parameters
209
	 * @return boolean true on sucess, false on failure
210
	 */
211
	function update_item($quantity) {
212
		$this->quantity = (int)$quantity;
213
		$this->refresh_item();
214
		$this->update_claimed_stock();
215
	}
216
217
	/**
218
	 * refresh_item method, refreshes the item, calculates the prices, gets the name
219
	 * @access public
220
	 *
221
	 * @return array array of monetary and other values
0 ignored issues
show
Documentation introduced by
Should the return type not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

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[] or array<String>.

Loading history...
222
	 */
223
	function refresh_item() {
224
		global $wpdb, $wpsc_shipping_modules, $wpsc_cart;
225
		$product_id = $this->product_id;
226
		$product = get_post( $this->product_id );
227
		$product_meta = get_metadata( 'post', $this->product_id );
228
		$this->sku = get_post_meta( $product_id, '_wpsc_sku', true );
229
		$price = get_post_meta( $product_id, '_wpsc_price', true );
230
		$special_price = get_post_meta( $product_id, '_wpsc_special_price', true );
231
		$product_meta = get_post_meta( $product_id, '_wpsc_product_metadata' );
232
		$this->stock = get_post_meta( $product_id, '_wpsc_stock', true );
233
		$this->is_donation = get_post_meta( $product_id, '_wpsc_is_donation', true );
234
235
		if ( isset( $special_price ) && $special_price > 0 && $special_price < $price )
236
			$price = $special_price;
237
		$priceandstock_id = 0;
238
		$this->weight = isset( $product_meta[0]['weight'] ) ? $product_meta[0]["weight"] : 0;
239
		// if we are using table rate price
240
		if ( isset( $product_meta[0]['table_rate_price'] ) ) {
241
			$levels = $product_meta[0]['table_rate_price'];
242
			if ( ! empty( $levels['quantity'] ) ) {
243
				foreach((array)$levels['quantity'] as $key => $qty) {
244
					if ($this->quantity >= $qty) {
245
						$unit_price = $levels['table_price'][$key];
246
						if ($unit_price != '')
247
							$price = $unit_price;
248
					}
249
				}
250
			}
251
		}
252
253
		$price = apply_filters( 'wpsc_price', $price, $product_id, $this );
254
255
		// create the string containing the product name.
256
		$this->product_name = $this->get_title( 'raw' );
257
		$this->priceandstock_id = $priceandstock_id;
258
		$this->meta = $product_meta;
259
260
		// change no_shipping to boolean and invert it
261
		if( isset( $product_meta[0]['no_shipping'] ) && $product_meta[0]['no_shipping'] == 1)
262
			$this->uses_shipping = 0 ;
263
		else
264
			$this->uses_shipping = 1;
265
266
		$quantity_limited = get_product_meta($product_id, 'stock', true);
267
		$this->has_limited_stock = (bool)$quantity_limited;
268
269
		if($this->is_donation == 1)
270
			$this->unit_price = (float) $this->provided_price;
271
		else
272
			$this->unit_price = (float) $price;
273
274
		$this->total_price = $this->unit_price * $this->quantity;
275
		if ( $product->post_parent )
276
			$category_data = get_the_product_category( $product->post_parent );
277
		else
278
			$category_data = get_the_product_category( $product_id );
279
280
		$this->category_list = array();
281
		$this->category_id_list = array();
282
283
		foreach( (array) $category_data as $category_row ) {
284
			$this->category_list[] = $category_row->slug;
285
			$this->category_id_list[] = $category_row->term_id;
286
		}
287
288
		//wpec_taxes - calculate product tax and add to total price
289
		$wpec_taxes_controller = new wpec_taxes_controller();
290
		if ( $wpec_taxes_controller->wpec_taxes_isincluded() && $wpec_taxes_controller->wpec_taxes_isenabled() ){
291
			$taxes = $wpec_taxes_controller->wpec_taxes_calculate_included_tax($this);
292
			$this->tax_rate = $taxes['rate'];
293
			$this->tax = $taxes['tax'];
294
		}
295
296
		if ( $product->post_parent ) {
297
			$this->product_url = get_permalink( $product->post_parent );
298
		} else {
299
			$this->product_url = get_permalink( $product_id );
300
		}
301
302
		if( ! is_array( $this->variation_values ) )
303
			$attach_parent = $product_id;
304
		else
305
			$attach_parent = $wpdb->get_var( $wpdb->prepare("SELECT post_parent FROM $wpdb->posts WHERE ID = %d", $product_id ) );
306
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
307
308
		$att_img_args = array(
309
				'post_type'   => 'attachment',
310
				'numberposts' => 1,
311
				'post_parent' => $attach_parent,
312
				'orderby'     => 'menu_order',
313
				'order'       => 'DESC'
314
		);
315
316
		$attached_image = get_posts( $att_img_args );
317
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
318
319
		if ( $attached_image != null )
320
			$this->thumbnail_image = array_shift( $attached_image );
321
322
		$product_files = (array) get_posts( array(
323
				'post_type'   => 'wpsc-product-file',
324
				'post_parent' => $this->product_id,
325
				'numberposts' => -1,
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set numberposts to -1 ever.
Loading history...
326
				'post_status' => 'inherit'
327
		) );
328
329
		$this->is_downloadable = count( $product_files ) > 0;
330
331
		if ( isset( $this->cart->selected_shipping_method ) && isset( $wpsc_shipping_modules[$this->cart->selected_shipping_method] ) && is_callable( array( $wpsc_shipping_modules[$this->cart->selected_shipping_method], "get_item_shipping" ) ) )
332
			$this->shipping = $wpsc_shipping_modules[$this->cart->selected_shipping_method]->get_item_shipping( $this );
333
334
		// update the claimed stock here
335
		$this->update_claimed_stock();
336
337
		do_action_ref_array( 'wpsc_refresh_item', array( &$this ) );
338
	}
339
340
	public function get_title( $mode = 'display' ) {
341
342
		if ( ! get_post_field( 'post_parent', $this->product_id ) ) {
343
			return get_post_field( 'post_title', $this->product_id );
344
		}
345
346
		if ( empty( self::$variation_cache ) ) {
347
			self::refresh_variation_cache();
348
		}
349
350
		$primary_product_id = get_post_field( 'post_parent', $this->product_id );
351
		$title              = get_post_field( 'post_title' , $primary_product_id );
352
353
		if ( isset( self::$variation_cache[ $this->product_id ] ) ) {
354
			ksort( self::$variation_cache[ $this->product_id ] );
355
			$vars   = implode( ', ', self::$variation_cache[ $this->product_id ] );
356
			$title .= ' (' . $vars . ')';
357
		}
358
359
		$title = apply_filters( 'wpsc_cart_product_title', $title, $this->product_id, $this );
360
361
		if ( $mode == 'display' ) {
362
			$title = apply_filters( 'the_title', $title, $this );
363
		}
364
365
		return $title;
366
	}
367
368
	/**
369
	 * Calculate shipping method
370
	 * if no parameter passed, takes the currently selected method
371
	 * @access public
372
	 *
373
	 * @param string shipping method
374
	 * @return boolean true on sucess, false on failure
375
	 */
376
377
	function calculate_shipping($method = null) {
378
		global $wpdb, $wpsc_cart, $wpsc_shipping_modules;
379
		$shipping = '';
380
		if($method === null)
381
			$method = $this->cart->selected_shipping_method;
382
383
		if( $method && isset( $wpsc_shipping_modules[$method] ) && method_exists( $wpsc_shipping_modules[$method], "get_item_shipping"  ))
384
			$shipping = $wpsc_shipping_modules[$method]->get_item_shipping($this);
385
386
		if($method == $this->cart->selected_shipping_method && !empty( $shipping ) )
387
			$this->shipping = $shipping;
388
389
		return $shipping;
390
	}
391
392
	/**
393
	 * user provided file method
394
	 * @access public
395
	 * @param string shipping method
396
	 * @return boolean true on sucess, false on failure
397
	 */
398
399
	function save_provided_file($file_data) {
400
		global $wpdb;
401
		$accepted_file_types['mime'][] = 'image/jpeg';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$accepted_file_types was never initialized. Although not strictly required by PHP, it is generally a good practice to add $accepted_file_types = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
402
		$accepted_file_types['mime'][] = 'image/gif';
403
		$accepted_file_types['mime'][] = 'image/png';
404
405
		$accepted_file_types['mime'][] = 'image/pjpeg';  // Added for IE compatibility
406
		$accepted_file_types['mime'][] = 'image/x-png';  // Added for IE compatibility
407
408
		$accepted_file_types['ext'][] = 'jpeg';
409
		$accepted_file_types['ext'][] = 'jpg';
410
		$accepted_file_types['ext'][] = 'gif';
411
		$accepted_file_types['ext'][] = 'png';
412
413
		$accepted_file_types = apply_filters( 'wpsc_customer_upload_accepted_file_types', $accepted_file_types, $this );
414
415
		$can_have_uploaded_image = get_product_meta($this->product_id,'product_metadata',true);
416
		$product = get_post($this->product_id);
417
		if(0 != $product->post_parent ){
418
			$product = get_post($product->post_parent);
419
			$can_have_uploaded_image = get_product_meta($product->ID,'product_metadata',true);
420
		}
421
		$can_have_uploaded_image = $can_have_uploaded_image['can_have_uploaded_image'];
422
		if ('on' == $can_have_uploaded_image || 1 == $can_have_uploaded_image) {
423
			$file_data['name'] = sanitize_file_name( $file_data['name'] );
424
			$name_parts = explode('.',basename($file_data['name']));
425
			$extension = array_pop($name_parts);
426
427
			if ( ( (
428
					array_search( strtolower( $file_data['type'] ), $accepted_file_types['mime'] ) !== false ) ||
429
					get_option( 'wpsc_check_mime_types' ) == 1 ) &&
430
					array_search( strtolower( $extension ), $accepted_file_types['ext'] ) !== false ) {
431
432
				if(is_file(WPSC_USER_UPLOADS_DIR.$file_data['name'])) {
433
					$name_parts = explode('.',basename($file_data['name']));
434
					$extension = array_pop($name_parts);
435
					$name_base = implode('.',$name_parts);
436
					$file_data['name'] = null;
437
					$num = 2;
438
					//  loop till we find a free file name, first time I get to do a do loop in yonks
439
					do {
440
						$test_name = "{$name_base}-{$num}.{$extension}";
441
						if(!file_exists(WPSC_USER_UPLOADS_DIR.$test_name))
442
							$file_data['name'] = $test_name;
443
						$num++;
444
					} while ($file_data['name'] == null);
445
				}
446
447
				$unique_id =  sha1(uniqid(rand(),true));
0 ignored issues
show
introduced by
Expected 1 space after "="; 2 found
Loading history...
448
				if(move_uploaded_file($file_data['tmp_name'], WPSC_USER_UPLOADS_DIR.$file_data['name']) )
449
					$this->custom_file = array(
450
							'file_name' => $file_data['name'],
451
							'mime_type' => $file_data['type'],
452
							'unique_id' => $unique_id
453
					);
454
455
			}
456
		}
457
	}
458
459
	/**
460
	 * update_claimed_stock method
461
	 * Updates the claimed stock table, to prevent people from having more than the existing stock in their carts
462
	 * @access public
463
	 *
464
	 * no parameters, nothing returned
465
	 */
466
	function update_claimed_stock() {
467
		global $wpdb;
468
469
		if($this->has_limited_stock == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
470
			$claimed_query = new WPSC_Claimed_Stock( array(
471
				'product_id' => $this->product_id,
472
				'cart_id'    => $this->cart->unique_id
473
			) );
474
			$claimed_query->update_claimed_stock( $this->quantity );
475
		}
476
	}
477
478
	/**
479
	 * save to database method
480
	 * @access public
481
	 *
482
	 * @param integer purchase log id
483
	 *
484
	 * @return int    The inserted cart item ID.
485
	 */
486
	function save_to_db($purchase_log_id) {
487
		global $wpdb, $wpsc_shipping_modules;
488
489
		$method = $this->cart->selected_shipping_method;
490
		$shipping = 0;
491
492
		if( ! empty( $method ) && method_exists( $wpsc_shipping_modules[$method], "get_item_shipping" ) )
493
			$shipping = $wpsc_shipping_modules[$this->cart->selected_shipping_method]->get_item_shipping( $this );
494
495
		if( $this->cart->has_total_shipping_discount() )
496
			$shipping = 0;
497
498
		$shipping = apply_filters( 'wpsc_item_shipping_amount_db', $shipping, $this );
499
500
		//initialize tax variables
501
		$tax = 0;
502
		$tax_rate = 0;
503
504
		//wpec_taxes - calculate product tax and add to total price
505
		$wpec_taxes_controller = new wpec_taxes_controller();
506
507
		if($wpec_taxes_controller->wpec_taxes_isincluded() && $wpec_taxes_controller->wpec_taxes_isenabled()){
508
			$taxes = $wpec_taxes_controller->wpec_taxes_calculate_included_tax($this);
509
			$tax_rate = $taxes['rate'];
510
			$tax = $taxes['tax'];
511
		}
512
513
		$wpdb->insert(
514
			WPSC_TABLE_CART_CONTENTS,
515
			array(
516
				'prodid'         => $this->product_id,
517
				'name'           => $this->get_title(),
518
				'purchaseid'     => $purchase_log_id,
519
				'price'          => $this->unit_price,
520
				'pnp'            => floatval( $shipping ),
521
				'tax_charged'    => floatval( $tax ),
522
				'gst'            => floatval( $tax_rate ),
523
				'quantity'       => $this->quantity,
524
				'donation'       => $this->is_donation,
525
				'no_shipping'    => 0,
526
				'custom_message' => $this->custom_message,
527
				'files'          => serialize( $this->custom_file ),
528
				'meta'           => null
529
			),
530
			array(
531
				'%d',
532
				'%s',
533
				'%d',
534
				'%f',
535
				'%f',
536
				'%f',
537
				'%f',
538
				'%s',
539
				'%d',
540
				'%d',
541
				'%s',
542
				'%s',
543
				'%s'
544
			)
545
		);
546
547
		$cart_item_id = $wpdb->get_var( "SELECT " . $wpdb->insert_id . " AS `id` FROM `".WPSC_TABLE_CART_CONTENTS."` LIMIT 1");
548
549
		wpsc_add_cart_item_meta( $cart_item_id, 'sku', $this->sku, true );
550
551
		if ( ! empty( $this->item_meta ) ) {
552
			foreach ( $this->item_meta as $item_meta_key => $item_meta_value ) {
553
				wpsc_add_cart_item_meta( $cart_item_id, $item_meta_key, $item_meta_value, true );
554
			}
555
		}
556
557
		if ( $this->is_downloadable == true ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
558
559
			$product_files = (array) get_posts( array(
560
					'post_type'   => 'wpsc-product-file',
561
					'post_parent' => $this->product_id,
562
					'numberposts' => -1,
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set numberposts to -1 ever.
Loading history...
563
					'post_status' => 'inherit'
564
			) );
565
566
			$downloads = get_option( 'max_downloads' );
567
568
			foreach ( $product_files as $file ) {
569
570
				// if the file is downloadable, check that the file is real
571
				$unique_id = sha1( uniqid( mt_rand(), true ) );
572
573
				$wpdb->insert(
574
						WPSC_TABLE_DOWNLOAD_STATUS,
575
						array(
576
								'product_id' => $this->product_id,
577
								'fileid'     => $file->ID,
578
								'purchid'    => $purchase_log_id,
579
								'cartid'     => $cart_item_id,
580
								'uniqueid'   => $unique_id,
581
								'downloads'  => $downloads,
582
								'active'     => 0,
583
								'datetime'   => date( 'Y-m-d H:i:s' )
584
						),
585
						array(
586
								'%d',
587
								'%d',
588
								'%d',
589
								'%d',
590
								'%s',
591
								'%s',
592
								'%d',
593
								'%s',
594
						)
595
				);
596
597
				$download_id = $wpdb->get_var( "SELECT " . $wpdb->insert_id . " AS `id` FROM `".WPSC_TABLE_DOWNLOAD_STATUS."` LIMIT 1");
598
				wpsc_update_meta( $download_id, '_is_legacy', 'false', 'wpsc_downloads' );
599
			}
0 ignored issues
show
introduced by
Blank line found after control structure
Loading history...
600
601
		}
602
603
		do_action( 'wpsc_save_cart_item', $cart_item_id, $this->product_id, $this );
604
605
		return $cart_item_id;
606
	}
607
608
}
609
610
611
/**
612
 * Comparison object that helps with ordering cart items
613
 *
614
 * @since  3.8.9
615
 * @access private
616
 */
617
class _WPSC_Comparison {
618
619
	private $orderby = '';
620
	private $order = 'ASC';
621
622
	/**
623
	 * Constructor
624
	 *
625
	 * @param string $orderby Field to order by
626
	 * @param string $order   Order direction, defaults to ASC for ascending.
627
	 */
628
	public function __construct( $orderby, $order = 'ASC' ) {
629
		$this->orderby = $orderby;
630
		$this->order = $order;
631
	}
632
633
	/**
634
	 * This compare method can be passed into usort when sorting an array of object
635
	 *
636
	 * @since  3.8.9
637
	 *
638
	 * @param  object|array $a
639
	 * @param  object|array $b
640
	 * @return int          See usort() documentation for the meaning of this return value.
641
	 */
642
	public function compare( $a, $b ) {
643
		// cast them all to object, just in case any of them is an array
644
		$a = (object) $a;
645
		$b = (object) $b;
646
647
		$key = $this->orderby;
648
649
		$val_a = isset( $a->$key ) ? $a->$key : 0;
650
		$val_b = isset( $b->$key ) ? $b->$key : 0;
651
652
		$diff = $val_a - $val_b;
653
654
		if ( $this->order != 'ASC' )
655
			$diff = $diff * -1;
656
657
		return $diff;
658
	}
659
}
660
661
/**
662
 * Refreshes discount for coupons when a new product is added to the cart.
663
 *
664
 * This is a fairly generally expected workflow, though there are some instances wherein
665
 * one might prefer to force the customer to "Update".  In those instances, this can be unhooked.
666
 *
667
 * @since  3.8.14
668
 * @return void
669
 */
670
function wpsc_cart_item_refresh_coupon() {
671
	$coupon = wpsc_get_customer_meta( 'coupon' );
672
673
	if ( ! empty( $coupon ) ) {
674
675
		wpsc_coupon_price( $coupon );
676
	}
677
}
678
679
add_action( 'wpsc_refresh_item', 'wpsc_cart_item_refresh_coupon' );
680
681
/**
682
 * Filters the gateway count to return zero if a free cart is present.
683
 *
684
 * @access private
685
 * @param  int     $count Number of active gateways.
686
 *
687
 * @since  3.9.0
688
 * @return int     $count
689
 */
690
function _wpsc_free_checkout_gateway_count( $count ) {
691
692
	if ( wpsc_is_free_cart() ) {
693
		$count = 0;
694
	}
695
696
	return $count;
697
}
698
699
add_filter( 'wpsc_gateway_count', '_wpsc_free_checkout_gateway_count', 15 );
700
701
/**
702
 * Filters the custom gateway field to return an empty string if a free cart is present.
703
 *
704
 * @access private
705
 * @param  string     $value Custom gateway field.
706
 *
707
 * @since  3.9.0
708
 * @return string     $value
709
 */
710
function _wpsc_free_checkout_hidden_field( $value ) {
711
712
	if ( wpsc_is_free_cart() ) {
713
		$value = '';
714
	}
715
716
	return $value;
717
}
718
719
add_filter( 'wpsc_gateway_hidden_field_value', '_wpsc_free_checkout_hidden_field' , 15 );
720