Issues (1182)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/wc-update-functions.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

Code
1
<?php
2
/**
3
 * WooCommerce Updates
4
 *
5
 * Functions for updating data, used by the background updater.
6
 *
7
 * @author   WooThemes
8
 * @category Core
9
 * @package  WooCommerce/Functions
10
 * @version  2.6.0
11
 */
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
function wc_update_200_file_paths() {
18
	global $wpdb;
19
20
	// Upgrade old style files paths to support multiple file paths
21
	$existing_file_paths = $wpdb->get_results( "SELECT * FROM {$wpdb->postmeta} WHERE meta_key = '_file_path' AND meta_value != '';" );
22
23
	if ( $existing_file_paths ) {
24
25
		foreach( $existing_file_paths as $existing_file_path ) {
26
27
			$old_file_path = trim( $existing_file_path->meta_value );
28
29
			if ( ! empty( $old_file_path ) ) {
30
				$file_paths = serialize( array( md5( $old_file_path ) => $old_file_path ) );
31
32
				$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_key = '_file_paths', meta_value = %s WHERE meta_id = %d", $file_paths, $existing_file_path->meta_id ) );
33
34
				$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}woocommerce_downloadable_product_permissions SET download_id = %s WHERE product_id = %d", md5( $old_file_path ), $existing_file_path->post_id ) );
35
36
			}
37
		}
38
	}
39
}
40
41
function wc_update_200_permalinks() {
42
	// Setup default permalinks if shop page is defined
43
	$permalinks 	= get_option( 'woocommerce_permalinks' );
44
	$shop_page_id 	= wc_get_page_id( 'shop' );
45
46
	if ( empty( $permalinks ) && $shop_page_id > 0 ) {
47
48
		$base_slug 		= $shop_page_id > 0 && get_post( $shop_page_id ) ? get_page_uri( $shop_page_id ) : 'shop';
49
50
		$category_base 	= get_option('woocommerce_prepend_shop_page_to_urls') == "yes" ? trailingslashit( $base_slug ) : '';
51
		$category_slug 	= get_option('woocommerce_product_category_slug') ? get_option('woocommerce_product_category_slug') : _x( 'product-category', 'slug', 'woocommerce' );
52
		$tag_slug 		= get_option('woocommerce_product_tag_slug') ? get_option('woocommerce_product_tag_slug') : _x( 'product-tag', 'slug', 'woocommerce' );
53
54
		if ( 'yes' == get_option('woocommerce_prepend_shop_page_to_products') ) {
55
			$product_base = trailingslashit( $base_slug );
56
		} else {
57
			if ( ( $product_slug = get_option('woocommerce_product_slug') ) !== false && ! empty( $product_slug ) ) {
58
				$product_base = trailingslashit( $product_slug );
59
			} else {
60
				$product_base = trailingslashit( _x('product', 'slug', 'woocommerce') );
61
			}
62
		}
63
64
		if ( get_option('woocommerce_prepend_category_to_products') == 'yes' )
65
			$product_base .= trailingslashit('%product_cat%');
66
67
		$permalinks = array(
68
			'product_base' 		=> untrailingslashit( $product_base ),
69
			'category_base' 	=> untrailingslashit( $category_base . $category_slug ),
70
			'attribute_base' 	=> untrailingslashit( $category_base ),
71
			'tag_base' 			=> untrailingslashit( $category_base . $tag_slug )
72
		);
73
74
		update_option( 'woocommerce_permalinks', $permalinks );
75
	}
76
}
77
78
function wc_update_200_subcat_display() {
79
	// Update subcat display settings
80 View Code Duplication
	if ( get_option( 'woocommerce_shop_show_subcategories' ) == 'yes' ) {
81
		if ( get_option( 'woocommerce_hide_products_when_showing_subcategories' ) == 'yes' ) {
82
			update_option( 'woocommerce_shop_page_display', 'subcategories' );
83
		} else {
84
			update_option( 'woocommerce_shop_page_display', 'both' );
85
		}
86
	}
87
88 View Code Duplication
	if ( get_option( 'woocommerce_show_subcategories' ) == 'yes' ) {
89
		if ( get_option( 'woocommerce_hide_products_when_showing_subcategories' ) == 'yes' ) {
90
			update_option( 'woocommerce_category_archive_display', 'subcategories' );
91
		} else {
92
			update_option( 'woocommerce_category_archive_display', 'both' );
93
		}
94
	}
95
}
96
97
function wc_update_200_taxrates() {
98
	global $wpdb;
99
100
	// Update tax rates
101
	$loop = 0;
102
	$tax_rates = get_option( 'woocommerce_tax_rates' );
103
104
	if ( $tax_rates )
105
		foreach ( $tax_rates as $tax_rate ) {
106
107
			foreach ( $tax_rate['countries'] as $country => $states ) {
108
109
				$states = array_reverse( $states );
110
111
				foreach ( $states as $state ) {
112
113
					if ( $state == '*' )
114
						$state = '';
115
116
					$wpdb->insert(
117
						$wpdb->prefix . "woocommerce_tax_rates",
118
						array(
119
							'tax_rate_country'  => $country,
120
							'tax_rate_state'    => $state,
121
							'tax_rate'          => $tax_rate['rate'],
122
							'tax_rate_name'     => $tax_rate['label'],
123
							'tax_rate_priority' => 1,
124
							'tax_rate_compound' => $tax_rate['compound'] == 'yes' ? 1 : 0,
125
							'tax_rate_shipping' => $tax_rate['shipping'] == 'yes' ? 1 : 0,
126
							'tax_rate_order'    => $loop,
127
							'tax_rate_class'    => $tax_rate['class']
128
						)
129
					);
130
131
					$loop++;
132
				}
133
			}
134
		}
135
136
	$local_tax_rates = get_option( 'woocommerce_local_tax_rates' );
137
138
	if ( $local_tax_rates )
139
		foreach ( $local_tax_rates as $tax_rate ) {
140
141
			$location_type = $tax_rate['location_type'] == 'postcode' ? 'postcode' : 'city';
142
143
			if ( $tax_rate['state'] == '*' )
144
				$tax_rate['state'] = '';
145
146
			$wpdb->insert(
147
				$wpdb->prefix . "woocommerce_tax_rates",
148
				array(
149
					'tax_rate_country'  => $tax_rate['country'],
150
					'tax_rate_state'    => $tax_rate['state'],
151
					'tax_rate'          => $tax_rate['rate'],
152
					'tax_rate_name'     => $tax_rate['label'],
153
					'tax_rate_priority' => 2,
154
					'tax_rate_compound' => $tax_rate['compound'] == 'yes' ? 1 : 0,
155
					'tax_rate_shipping' => $tax_rate['shipping'] == 'yes' ? 1 : 0,
156
					'tax_rate_order'    => $loop,
157
					'tax_rate_class'    => $tax_rate['class']
158
				)
159
			);
160
161
			$tax_rate_id = $wpdb->insert_id;
162
163
			if ( $tax_rate['locations'] ) {
164
				foreach ( $tax_rate['locations'] as $location ) {
165
166
					$wpdb->insert(
167
						$wpdb->prefix . "woocommerce_tax_rate_locations",
168
						array(
169
							'location_code' => $location,
170
							'tax_rate_id'   => $tax_rate_id,
171
							'location_type' => $location_type,
172
						)
173
					);
174
175
				}
176
			}
177
178
			$loop++;
179
		}
180
181
	update_option( 'woocommerce_tax_rates_backup', $tax_rates );
182
	update_option( 'woocommerce_local_tax_rates_backup', $local_tax_rates );
183
	delete_option( 'woocommerce_tax_rates' );
184
	delete_option( 'woocommerce_local_tax_rates' );
185
}
186
187
function wc_update_200_line_items() {
188
	global $wpdb;
189
190
	// Now its time for the massive update to line items - move them to the new DB tables
191
	// Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_items' WHERE meta_key = '_order_items_old'
192
	$order_item_rows = $wpdb->get_results( "
193
		SELECT * FROM {$wpdb->postmeta}
194
		WHERE meta_key = '_order_items'
195
	" );
196
197
	foreach ( $order_item_rows as $order_item_row ) {
198
199
		$order_items = (array) maybe_unserialize( $order_item_row->meta_value );
200
201
		foreach ( $order_items as $order_item ) {
202
203
			if ( ! isset( $order_item['line_total'] ) && isset( $order_item['taxrate'] ) && isset( $order_item['cost'] ) ) {
204
				$order_item['line_tax'] 			= number_format( ( $order_item['cost'] * $order_item['qty'] ) * ( $order_item['taxrate'] / 100 ), 2, '.', '' );
205
				$order_item['line_total'] 			= $order_item['cost'] * $order_item['qty'];
206
				$order_item['line_subtotal_tax'] 	= $order_item['line_tax'];
207
				$order_item['line_subtotal'] 		= $order_item['line_total'];
208
			}
209
210
			$order_item['line_tax'] 			= isset( $order_item['line_tax'] ) ? $order_item['line_tax'] : 0;
211
			$order_item['line_total']			= isset( $order_item['line_total'] ) ? $order_item['line_total'] : 0;
212
			$order_item['line_subtotal_tax'] 	= isset( $order_item['line_subtotal_tax'] ) ? $order_item['line_subtotal_tax'] : 0;
213
			$order_item['line_subtotal'] 		= isset( $order_item['line_subtotal'] ) ? $order_item['line_subtotal'] : 0;
214
215
			$item_id = wc_add_order_item( $order_item_row->post_id, array(
216
		 		'order_item_name' 		=> $order_item['name'],
217
		 		'order_item_type' 		=> 'line_item'
218
		 	) );
219
220
		 	// Add line item meta
221
		 	if ( $item_id ) {
222
			 	wc_add_order_item_meta( $item_id, '_qty', absint( $order_item['qty'] ) );
223
			 	wc_add_order_item_meta( $item_id, '_tax_class', $order_item['tax_class'] );
224
			 	wc_add_order_item_meta( $item_id, '_product_id', $order_item['id'] );
225
			 	wc_add_order_item_meta( $item_id, '_variation_id', $order_item['variation_id'] );
226
			 	wc_add_order_item_meta( $item_id, '_line_subtotal', wc_format_decimal( $order_item['line_subtotal'] ) );
227
			 	wc_add_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( $order_item['line_subtotal_tax'] ) );
228
			 	wc_add_order_item_meta( $item_id, '_line_total', wc_format_decimal( $order_item['line_total'] ) );
229
			 	wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $order_item['line_tax'] ) );
230
231
			 	$meta_rows = array();
232
233
				// Insert meta
234
				if ( ! empty( $order_item['item_meta'] ) ) {
235
					foreach ( $order_item['item_meta'] as $key => $meta ) {
236
						// Backwards compatibility
237
						if ( is_array( $meta ) && isset( $meta['meta_name'] ) ) {
238
							$meta_rows[] = '(' . $item_id . ',"' . esc_sql( $meta['meta_name'] ) . '","' . esc_sql( $meta['meta_value'] ) . '")';
239
						} else {
240
							$meta_rows[] = '(' . $item_id . ',"' . esc_sql( $key ) . '","' . esc_sql( $meta ) . '")';
241
						}
242
					}
243
				}
244
245
				// Insert meta rows at once
246
				if ( sizeof( $meta_rows ) > 0 ) {
247
					$wpdb->query( $wpdb->prepare( "
248
						INSERT INTO {$wpdb->prefix}woocommerce_order_itemmeta ( order_item_id, meta_key, meta_value )
249
						VALUES " . implode( ',', $meta_rows ) . ";
250
					", $order_item_row->post_id ) );
251
				}
252
253
				// Delete from DB (rename)
254
				$wpdb->query( $wpdb->prepare( "
255
					UPDATE {$wpdb->postmeta}
256
					SET meta_key = '_order_items_old'
257
					WHERE meta_key = '_order_items'
258
					AND post_id = %d
259
				", $order_item_row->post_id ) );
260
		 	}
261
262
			unset( $meta_rows, $item_id, $order_item );
263
		}
264
	}
265
266
	// Do the same kind of update for order_taxes - move to lines
267
	// Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_taxes' WHERE meta_key = '_order_taxes_old'
268
	$order_tax_rows = $wpdb->get_results( "
269
		SELECT * FROM {$wpdb->postmeta}
270
		WHERE meta_key = '_order_taxes'
271
	" );
272
273
	foreach ( $order_tax_rows as $order_tax_row ) {
274
275
		$order_taxes = (array) maybe_unserialize( $order_tax_row->meta_value );
276
277
		if ( $order_taxes ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $order_taxes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
278
			foreach( $order_taxes as $order_tax ) {
279
280
				if ( ! isset( $order_tax['label'] ) || ! isset( $order_tax['cart_tax'] ) || ! isset( $order_tax['shipping_tax'] ) )
281
					continue;
282
283
				$item_id = wc_add_order_item( $order_tax_row->post_id, array(
284
			 		'order_item_name' 		=> $order_tax['label'],
285
			 		'order_item_type' 		=> 'tax'
286
			 	) );
287
288
			 	// Add line item meta
289
			 	if ( $item_id ) {
290
				 	wc_add_order_item_meta( $item_id, 'compound', absint( isset( $order_tax['compound'] ) ? $order_tax['compound'] : 0 ) );
291
				 	wc_add_order_item_meta( $item_id, 'tax_amount', wc_clean( $order_tax['cart_tax'] ) );
292
				 	wc_add_order_item_meta( $item_id, 'shipping_tax_amount', wc_clean( $order_tax['shipping_tax'] ) );
293
				}
294
295
				// Delete from DB (rename)
296
				$wpdb->query( $wpdb->prepare( "
297
					UPDATE {$wpdb->postmeta}
298
					SET meta_key = '_order_taxes_old'
299
					WHERE meta_key = '_order_taxes'
300
					AND post_id = %d
301
				", $order_tax_row->post_id ) );
302
303
				unset( $tax_amount );
304
			}
305
		}
306
	}
307
}
308
309
function wc_update_200_images() {
310
	// Grab the pre 2.0 Image options and use to populate the new image options settings,
311
	// cleaning up afterwards like nice people do
312
	foreach ( array( 'catalog', 'single', 'thumbnail' ) as $value ) {
313
314
		$old_settings = array_filter( array(
315
			'width' => get_option( 'woocommerce_' . $value . '_image_width' ),
316
			'height' => get_option( 'woocommerce_' . $value . '_image_height' ),
317
			'crop' => get_option( 'woocommerce_' . $value . '_image_crop' )
318
		) );
319
320
		if ( ! empty(  $old_settings  ) && update_option( 'shop_' . $value . '_image_size', $old_settings ) ){
321
322
			delete_option( 'woocommerce_' . $value . '_image_width' );
323
			delete_option( 'woocommerce_' . $value . '_image_height' );
324
			delete_option( 'woocommerce_' . $value . '_image_crop' );
325
326
		}
327
	}
328
}
329
330
function wc_update_200_db_version() {
331
	WC_Install::update_db_version( '2.0.0' );
332
}
333
334
function wc_update_209_brazillian_state() {
335
	global $wpdb;
336
337
	// Update brazillian state codes
338
	$wpdb->update(
339
		$wpdb->postmeta,
340
		array(
341
			'meta_value' => 'BA'
342
		),
343
		array(
344
			'meta_key'   => '_billing_state',
345
			'meta_value' => 'BH'
346
		)
347
	);
348
	$wpdb->update(
349
		$wpdb->postmeta,
350
		array(
351
			'meta_value' => 'BA'
352
		),
353
		array(
354
			'meta_key'   => '_shipping_state',
355
			'meta_value' => 'BH'
356
		)
357
	);
358
	$wpdb->update(
359
		$wpdb->usermeta,
360
		array(
361
			'meta_value' => 'BA'
362
		),
363
		array(
364
			'meta_key'   => 'billing_state',
365
			'meta_value' => 'BH'
366
		)
367
	);
368
	$wpdb->update(
369
		$wpdb->usermeta,
370
		array(
371
			'meta_value' => 'BA'
372
		),
373
		array(
374
			'meta_key'   => 'shipping_state',
375
			'meta_value' => 'BH'
376
		)
377
	);
378
}
379
380
function wc_update_209_db_version() {
381
	WC_Install::update_db_version( '2.0.9' );
382
}
383
384
function wc_update_210_remove_pages() {
385
	// Pages no longer used
386
	wp_trash_post( get_option('woocommerce_pay_page_id') );
387
	wp_trash_post( get_option('woocommerce_thanks_page_id') );
388
	wp_trash_post( get_option('woocommerce_view_order_page_id') );
389
	wp_trash_post( get_option('woocommerce_change_password_page_id') );
390
	wp_trash_post( get_option('woocommerce_edit_address_page_id') );
391
	wp_trash_post( get_option('woocommerce_lost_password_page_id') );
392
}
393
394
function wc_update_210_file_paths() {
395
	global $wpdb;
396
397
	// Upgrade file paths to support multiple file paths + names etc
398
	$existing_file_paths = $wpdb->get_results( "SELECT * FROM {$wpdb->postmeta} WHERE meta_key = '_file_paths' AND meta_value != '';" );
399
400
	if ( $existing_file_paths ) {
401
402
		foreach( $existing_file_paths as $existing_file_path ) {
403
404
			$needs_update = false;
405
			$new_value    = array();
406
			$value        = maybe_unserialize( trim( $existing_file_path->meta_value ) );
407
408
			if ( $value ) {
409
				foreach ( $value as $key => $file ) {
410
					if ( ! is_array( $file ) ) {
411
						$needs_update      = true;
412
						$new_value[ $key ] = array(
413
							'file' => $file,
414
							'name' => wc_get_filename_from_url( $file )
415
						);
416
					} else {
417
						$new_value[ $key ] = $file;
418
					}
419
				}
420
				if ( $needs_update ) {
421
					$new_value = serialize( $new_value );
422
423
					$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_key = %s, meta_value = %s WHERE meta_id = %d", '_downloadable_files', $new_value, $existing_file_path->meta_id ) );
424
				}
425
			}
426
		}
427
	}
428
}
429
430
function wc_update_210_db_version() {
431
	WC_Install::update_db_version( '2.1.0' );
432
}
433
434
function wc_update_220_shipping() {
435
	$woocommerce_ship_to_destination = 'shipping';
436
437
	if ( get_option( 'woocommerce_ship_to_billing_address_only' ) === 'yes' ) {
438
		$woocommerce_ship_to_destination = 'billing_only';
439
	} elseif ( get_option( 'woocommerce_ship_to_billing' ) === 'yes' ) {
440
		$woocommerce_ship_to_destination = 'billing';
441
	}
442
443
	add_option( 'woocommerce_ship_to_destination', $woocommerce_ship_to_destination, '', 'no' );
444
}
445
446
function wc_update_220_order_status() {
447
	global $wpdb;
448
	$wpdb->query( "
449
		UPDATE {$wpdb->posts} as posts
450
		LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_ID
451
		LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
452
		LEFT JOIN {$wpdb->terms} AS term USING( term_id )
453
		SET posts.post_status = 'wc-pending'
454
		WHERE posts.post_type = 'shop_order'
455
		AND posts.post_status = 'publish'
456
		AND tax.taxonomy = 'shop_order_status'
457
		AND	term.slug LIKE 'pending%';
458
		"
459
	);
460
	$wpdb->query( "
461
		UPDATE {$wpdb->posts} as posts
462
		LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_ID
463
		LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
464
		LEFT JOIN {$wpdb->terms} AS term USING( term_id )
465
		SET posts.post_status = 'wc-processing'
466
		WHERE posts.post_type = 'shop_order'
467
		AND posts.post_status = 'publish'
468
		AND tax.taxonomy = 'shop_order_status'
469
		AND	term.slug LIKE 'processing%';
470
		"
471
	);
472
	$wpdb->query( "
473
		UPDATE {$wpdb->posts} as posts
474
		LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_ID
475
		LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
476
		LEFT JOIN {$wpdb->terms} AS term USING( term_id )
477
		SET posts.post_status = 'wc-on-hold'
478
		WHERE posts.post_type = 'shop_order'
479
		AND posts.post_status = 'publish'
480
		AND tax.taxonomy = 'shop_order_status'
481
		AND	term.slug LIKE 'on-hold%';
482
		"
483
	);
484
	$wpdb->query( "
485
		UPDATE {$wpdb->posts} as posts
486
		LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_ID
487
		LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
488
		LEFT JOIN {$wpdb->terms} AS term USING( term_id )
489
		SET posts.post_status = 'wc-completed'
490
		WHERE posts.post_type = 'shop_order'
491
		AND posts.post_status = 'publish'
492
		AND tax.taxonomy = 'shop_order_status'
493
		AND	term.slug LIKE 'completed%';
494
		"
495
	);
496
	$wpdb->query( "
497
		UPDATE {$wpdb->posts} as posts
498
		LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_ID
499
		LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
500
		LEFT JOIN {$wpdb->terms} AS term USING( term_id )
501
		SET posts.post_status = 'wc-cancelled'
502
		WHERE posts.post_type = 'shop_order'
503
		AND posts.post_status = 'publish'
504
		AND tax.taxonomy = 'shop_order_status'
505
		AND	term.slug LIKE 'cancelled%';
506
		"
507
	);
508
	$wpdb->query( "
509
		UPDATE {$wpdb->posts} as posts
510
		LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_ID
511
		LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
512
		LEFT JOIN {$wpdb->terms} AS term USING( term_id )
513
		SET posts.post_status = 'wc-refunded'
514
		WHERE posts.post_type = 'shop_order'
515
		AND posts.post_status = 'publish'
516
		AND tax.taxonomy = 'shop_order_status'
517
		AND	term.slug LIKE 'refunded%';
518
		"
519
	);
520
	$wpdb->query( "
521
		UPDATE {$wpdb->posts} as posts
522
		LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_ID
523
		LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
524
		LEFT JOIN {$wpdb->terms} AS term USING( term_id )
525
		SET posts.post_status = 'wc-failed'
526
		WHERE posts.post_type = 'shop_order'
527
		AND posts.post_status = 'publish'
528
		AND tax.taxonomy = 'shop_order_status'
529
		AND	term.slug LIKE 'failed%';
530
		"
531
	);
532
}
533
534 View Code Duplication
function wc_update_220_variations() {
535
	global $wpdb;
536
	// Update variations which manage stock
537
	$update_variations = $wpdb->get_results( "
538
		SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent FROM {$wpdb->posts} as posts
539
		LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock'
540
		LEFT OUTER JOIN {$wpdb->postmeta} as postmeta2 ON posts.ID = postmeta2.post_id AND postmeta2.meta_key = '_manage_stock'
541
		WHERE posts.post_type = 'product_variation'
542
		AND postmeta.meta_value IS NOT NULL
543
		AND postmeta.meta_value != ''
544
		AND postmeta2.meta_value IS NULL
545
	" );
546
547
	foreach ( $update_variations as $variation ) {
548
		$parent_backorders = get_post_meta( $variation->variation_parent, '_backorders', true );
549
		add_post_meta( $variation->variation_id, '_manage_stock', 'yes', true );
550
		add_post_meta( $variation->variation_id, '_backorders', $parent_backorders ? $parent_backorders : 'no', true );
551
	}
552
}
553
554
function wc_update_220_attributes() {
555
	global $wpdb;
556
	// Update taxonomy names with correct sanitized names
557
	$attribute_taxonomies = $wpdb->get_results( "SELECT * FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies" );
558
559
	foreach ( $attribute_taxonomies as $attribute_taxonomy ) {
560
		$sanitized_attribute_name = wc_sanitize_taxonomy_name( $attribute_taxonomy->attribute_name );
561
		if ( $sanitized_attribute_name !== $attribute_taxonomy->attribute_name ) {
562
			if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT 1=1 FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_name = %s;", $sanitized_attribute_name ) ) ) {
563
				// Update attribute
564
				$wpdb->update(
565
					"{$wpdb->prefix}woocommerce_attribute_taxonomies",
566
					array(
567
						'attribute_name' => $sanitized_attribute_name
568
					),
569
					array(
570
						'attribute_id' => $attribute_taxonomy->attribute_id
571
					)
572
				);
573
574
				// Update terms
575
				$wpdb->update(
576
					$wpdb->term_taxonomy,
577
					array( 'taxonomy' => wc_attribute_taxonomy_name( $sanitized_attribute_name ) ),
578
					array( 'taxonomy' => 'pa_' . $attribute_taxonomy->attribute_name )
579
				);
580
			}
581
		}
582
	}
583
}
584
585
function wc_update_220_db_version() {
586
	WC_Install::update_db_version( '2.2.0' );
587
}
588
589
function wc_update_230_options() {
590
	// _money_spent and _order_count may be out of sync - clear them
591
	delete_metadata( 'user', 0, '_money_spent', '', true );
592
	delete_metadata( 'user', 0, '_order_count', '', true );
593
594
	// To prevent taxes being hidden when using a default 'no address' in a store with tax inc prices, set the woocommerce_default_customer_address to use the store base address by default
595
	if ( '' === get_option( 'woocommerce_default_customer_address', false ) && wc_prices_include_tax() ) {
596
		update_option( 'woocommerce_default_customer_address', 'base' );
597
	}
598
}
599
600
function wc_update_230_db_version() {
601
	WC_Install::update_db_version( '2.3.0' );
602
}
603
604
function wc_update_240_options() {
605
	/**
606
	 * Coupon discount calculations.
607
	 * Maintain the old coupon logic for upgrades.
608
	 */
609
	update_option( 'woocommerce_calc_discounts_sequentially', 'yes' );
610
}
611
612
function wc_update_240_shipping_methods() {
613
	global $wpdb;
614
	/**
615
	 * Flat Rate Shipping.
616
	 * Update legacy options to new math based options.
617
	 */
618
	$shipping_methods = array(
619
		'woocommerce_flat_rates'                        => new WC_Shipping_Legacy_Flat_Rate(),
620
		'woocommerce_international_delivery_flat_rates' => new WC_Shipping_Legacy_International_Delivery()
621
	);
622
	foreach ( $shipping_methods as $flat_rate_option_key => $shipping_method ) {
623
		// Stop this running more than once if routine is repeated
624
		if ( version_compare( $shipping_method->get_option( 'version', 0 ), '2.4.0', '<' ) ) {
625
			$has_classes                      = sizeof( WC()->shipping->get_shipping_classes() ) > 0;
626
			$cost_key                         = $has_classes ? 'no_class_cost' : 'cost';
627
			$min_fee                          = $shipping_method->get_option( 'minimum_fee' );
628
			$math_cost_strings                = array( 'cost' => array(), 'no_class_cost' => array() );
629
			$math_cost_strings[ $cost_key ][] = $shipping_method->get_option( 'cost' );
630
631
			if ( $fee = $shipping_method->get_option( 'fee' ) ) {
632
				$math_cost_strings[ $cost_key ][] = strstr( $fee, '%' ) ? '[fee percent="' . str_replace( '%', '', $fee ) . '" min="' . esc_attr( $min_fee ) . '"]' : $fee;
633
			}
634
635
			foreach ( WC()->shipping->get_shipping_classes() as $shipping_class ) {
636
				$rate_key                       = 'class_cost_' . $shipping_class->slug;
637
				$math_cost_strings[ $rate_key ] = $math_cost_strings[ 'no_class_cost' ];
638
			}
639
640
			if ( $flat_rates = array_filter( (array) get_option( $flat_rate_option_key, array() ) ) ) {
641
				foreach ( $flat_rates as $shipping_class => $rate ) {
642
					$rate_key = 'class_cost_' . $shipping_class;
643
					if ( $rate['cost'] || $rate['fee'] ) {
644
						$math_cost_strings[ $rate_key ][] = $rate['cost'];
645
						$math_cost_strings[ $rate_key ][] = strstr( $rate['fee'], '%' ) ? '[fee percent="' . str_replace( '%', '', $rate['fee'] ) . '" min="' . esc_attr( $min_fee ) . '"]' : $rate['fee'];
646
					}
647
				}
648
			}
649
650
			if ( 'item' === $shipping_method->type ) {
651
				foreach ( $math_cost_strings as $key => $math_cost_string ) {
652
					$math_cost_strings[ $key ] = array_filter( array_map( 'trim', $math_cost_strings[ $key ] ) );
653
					if ( ! empty( $math_cost_strings[ $key ] ) ) {
654
						$last_key                                = max( 0, sizeof( $math_cost_strings[ $key ] ) - 1 );
655
						$math_cost_strings[ $key ][0]            = '( ' . $math_cost_strings[ $key ][0];
656
						$math_cost_strings[ $key ][ $last_key ] .= ' ) * [qty]';
657
					}
658
				}
659
			}
660
661
			$math_cost_strings[ 'cost' ][] = $shipping_method->get_option( 'cost_per_order' );
662
663
			// Save settings
664
			foreach ( $math_cost_strings as $option_id => $math_cost_string ) {
665
				$shipping_method->settings[ $option_id ] = implode( ' + ', array_filter( $math_cost_string ) );
666
			}
667
668
			$shipping_method->settings['version'] = '2.4.0';
669
			$shipping_method->settings['type']    = 'item' === $shipping_method->settings['type'] ? 'class' : $shipping_method->settings['type'];
670
671
			update_option( $shipping_method->plugin_id . $shipping_method->id . '_settings', $shipping_method->settings );
672
		}
673
	}
674
}
675
676
function wc_update_240_api_keys() {
677
	global $wpdb;
678
	/**
679
	 * Update the old user API keys to the new Apps keys.
680
	 */
681
	$api_users = $wpdb->get_results( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'woocommerce_api_consumer_key'" );
682
	$apps_keys = array();
683
684
	// Get user data
685
	foreach ( $api_users as $_user ) {
686
		$user = get_userdata( $_user->user_id );
687
		$apps_keys[] = array(
688
			'user_id'         => $user->ID,
689
			'permissions'     => $user->woocommerce_api_key_permissions,
690
			'consumer_key'    => wc_api_hash( $user->woocommerce_api_consumer_key ),
691
			'consumer_secret' => $user->woocommerce_api_consumer_secret,
692
			'truncated_key'   => substr( $user->woocommerce_api_consumer_secret, -7 )
693
		);
694
	}
695
696
	if ( ! empty( $apps_keys ) ) {
697
		// Create new apps
698
		foreach ( $apps_keys as $app ) {
699
			$wpdb->insert(
700
				$wpdb->prefix . 'woocommerce_api_keys',
701
				$app,
702
				array(
703
					'%d',
704
					'%s',
705
					'%s',
706
					'%s',
707
					'%s'
708
				)
709
			);
710
		}
711
712
		// Delete old user keys from usermeta
713
		foreach ( $api_users as $_user ) {
714
			$user_id = intval( $_user->user_id );
715
			delete_user_meta( $user_id, 'woocommerce_api_consumer_key' );
716
			delete_user_meta( $user_id, 'woocommerce_api_consumer_secret' );
717
			delete_user_meta( $user_id, 'woocommerce_api_key_permissions' );
718
		}
719
	}
720
}
721
722
function wc_update_240_webhooks() {
723
	global $wpdb;
724
	/**
725
	 * Webhooks.
726
	 * Make sure order.update webhooks get the woocommerce_order_edit_status hook.
727
	 */
728
	$order_update_webhooks = get_posts( array(
729
		'posts_per_page' => -1,
730
		'post_type'      => 'shop_webhook',
731
		'meta_key'       => '_topic',
732
		'meta_value'     => 'order.updated'
733
	) );
734
	foreach ( $order_update_webhooks as $order_update_webhook ) {
735
		$webhook = new WC_Webhook( $order_update_webhook->ID );
736
		$webhook->set_topic( 'order.updated' );
737
	}
738
}
739
740
function wc_update_240_refunds() {
741
	global $wpdb;
742
	/**
743
	 * Refunds for full refunded orders.
744
	 * Update fully refunded orders to ensure they have a refund line item so reports add up.
745
	 */
746
	$refunded_orders = get_posts( array(
747
		'posts_per_page' => -1,
748
		'post_type'      => 'shop_order',
749
		'post_status'    => array( 'wc-refunded' )
750
	) );
751
752
	// Ensure emails are disabled during this update routine
753
	remove_all_actions( 'woocommerce_order_status_refunded_notification' );
754
	remove_all_actions( 'woocommerce_order_partially_refunded_notification' );
755
	remove_action( 'woocommerce_order_status_refunded', array( 'WC_Emails', 'send_transactional_email' ) );
756
	remove_action( 'woocommerce_order_partially_refunded', array( 'WC_Emails', 'send_transactional_email' ) );
757
758
	foreach ( $refunded_orders as $refunded_order ) {
759
		$order_total    = get_post_meta( $refunded_order->ID, '_order_total', true );
760
		$refunded_total = $wpdb->get_var( $wpdb->prepare( "
761
			SELECT SUM( postmeta.meta_value )
762
			FROM $wpdb->postmeta AS postmeta
763
			INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
764
			WHERE postmeta.meta_key = '_refund_amount'
765
			AND postmeta.post_id = posts.ID
766
		", $refunded_order->ID ) );
767
768
		if ( $order_total > $refunded_total ) {
769
			wc_create_refund( array(
770
				'amount'     => $order_total - $refunded_total,
771
				'reason'     => __( 'Order Fully Refunded', 'woocommerce' ),
772
				'order_id'   => $refunded_order->ID,
773
				'line_items' => array(),
774
				'date'       => $refunded_order->post_modified
775
			) );
776
		}
777
	}
778
779
	wc_delete_shop_order_transients();
780
}
781
782
function wc_update_240_db_version() {
783
	WC_Install::update_db_version( '2.4.0' );
784
}
785
786 View Code Duplication
function wc_update_241_variations() {
787
	global $wpdb;
788
789
	// Select variations that don't have any _stock_status implemented on WooCommerce 2.2
790
	$update_variations = $wpdb->get_results( "
791
		SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent
792
		FROM {$wpdb->posts} as posts
793
		LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock_status'
794
		WHERE posts.post_type = 'product_variation'
795
		AND postmeta.meta_value IS NULL
796
	" );
797
798
	foreach ( $update_variations as $variation ) {
799
		// Get the parent _stock_status
800
		$parent_stock_status = get_post_meta( $variation->variation_parent, '_stock_status', true );
801
802
		// Set the _stock_status
803
		add_post_meta( $variation->variation_id, '_stock_status', $parent_stock_status ? $parent_stock_status : 'instock', true );
804
805
		// Delete old product children array
806
		delete_transient( 'wc_product_children_' . $variation->variation_parent );
807
	}
808
809
	// Invalidate old transients such as wc_var_price
810
	WC_Cache_Helper::get_transient_version( 'product', true );
811
}
812
813
function wc_update_241_db_version() {
814
	WC_Install::update_db_version( '2.4.1' );
815
}
816
817
function wc_update_250_currency() {
818
	global $wpdb;
819
	// Fix currency settings for LAK currency.
820
	$current_currency = get_option( 'woocommerce_currency' );
821
822
	if ( 'KIP' === $current_currency ) {
823
		update_option( 'woocommerce_currency', 'LAK' );
824
	}
825
826
	// Update LAK currency code.
827
	$wpdb->update(
828
		$wpdb->postmeta,
829
		array(
830
			'meta_value' => 'LAK'
831
		),
832
		array(
833
			'meta_key'   => '_order_currency',
834
			'meta_value' => 'KIP'
835
		)
836
	);
837
}
838
839
function wc_update_250_db_version() {
840
	WC_Install::update_db_version( '2.5.0' );
841
}
842
843
function wc_update_260_options() {
844
	/**
845
	 * woocommerce_calc_shipping option has been removed in 2.6
846
	 */
847
	if ( 'no' === get_option( 'woocommerce_calc_shipping' ) ) {
848
		update_option( 'woocommerce_ship_to_countries', 'disabled' );
849
	}
850
851
	WC_Admin_Notices::add_notice( 'legacy_shipping' );
852
}
853
854
function wc_update_260_termmeta() {
855
	global $wpdb;
856
	/**
857
	 * Migrate term meta to WordPress tables
858
	 */
859 View Code Duplication
	if ( get_option( 'db_version' ) >= 34370 && $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}woocommerce_termmeta';" ) ) {
860
		if ( $wpdb->query( "INSERT INTO {$wpdb->termmeta} ( term_id, meta_key, meta_value ) SELECT woocommerce_term_id, meta_key, meta_value FROM {$wpdb->prefix}woocommerce_termmeta;" ) ) {
861
			$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_termmeta" );
862
		}
863
	}
864
}
865
866
function wc_update_260_zones() {
867
	global $wpdb;
868
	/**
869
	 * Old (table rate) shipping zones to new core shipping zones migration.
870
	 * zone_enabled and zone_type are no longer used, but it's safe to leave them be.
871
	 */
872 View Code Duplication
	if ( $wpdb->get_var( "SHOW COLUMNS FROM `{$wpdb->prefix}woocommerce_shipping_zones` LIKE 'zone_enabled';" ) ) {
873
		$wpdb->query( "ALTER TABLE {$wpdb->prefix}woocommerce_shipping_zones CHANGE `zone_type` `zone_type` VARCHAR(40) NOT NULL DEFAULT '';" );
874
		$wpdb->query( "ALTER TABLE {$wpdb->prefix}woocommerce_shipping_zones CHANGE `zone_enabled` `zone_enabled` INT(1) NOT NULL DEFAULT 1;" );
875
	}
876
}
877
878
function wc_update_260_zone_methods() {
879
	global $wpdb;
880
881
	/**
882
	 * Shipping zones in WC 2.6.0 use a table named woocommerce_shipping_zone_methods.
883
	 * Migrate the old data out of woocommerce_shipping_zone_shipping_methods into the new table and port over any known options (used by table rates and flat rate boxes).
884
	 */
885
	if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}woocommerce_shipping_zone_shipping_methods';" ) ) {
886
		$old_methods = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods;" );
887
		if ( $old_methods ) {
888
			$max_new_id = $wpdb->get_var( "SELECT MAX(instance_id) FROM {$wpdb->prefix}woocommerce_shipping_zone_methods" );
889
			$max_old_id = $wpdb->get_var( "SELECT MAX(shipping_method_id) FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods" );
890
891
			// Avoid ID conflicts
892
			$wpdb->query( $wpdb->prepare( "ALTER TABLE {$wpdb->prefix}woocommerce_shipping_zone_methods AUTO_INCREMENT = %d;", max( $max_new_id, $max_old_id ) + 1 ) );
893
894
			// Store changes
895
			$changes = array();
896
897
			// Move data
898
			foreach ( $old_methods as $old_method ) {
899
				$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zone_methods', array(
900
					'zone_id'      => $old_method->zone_id,
901
					'method_id'    => $old_method->shipping_method_type,
902
					'method_order' => $old_method->shipping_method_order
903
				) );
904
905
				$new_instance_id = $wpdb->insert_id;
906
907
				// Move main settings
908
				$older_settings_key = 'woocommerce_' . $old_method->shipping_method_type . '-' . $old_method->shipping_method_id . '_settings';
909
				$old_settings_key   = 'woocommerce_' . $old_method->shipping_method_type . '_' . $old_method->shipping_method_id . '_settings';
910
				add_option( 'woocommerce_' . $old_method->shipping_method_type . '_' . $new_instance_id . '_settings', get_option( $old_settings_key, get_option( $older_settings_key ) ) );
911
912
				// Handling for table rate and flat rate box shipping.
913
				if ( 'table_rate' === $old_method->shipping_method_type ) {
914
					// Move priority settings
915
					add_option( 'woocommerce_table_rate_default_priority_' . $new_instance_id, get_option( 'woocommerce_table_rate_default_priority_' . $old_method->shipping_method_id ) );
916
					add_option( 'woocommerce_table_rate_priorities_' . $new_instance_id, get_option( 'woocommerce_table_rate_priorities_' . $old_method->shipping_method_id ) );
917
918
					// Move rates
919
					$wpdb->update(
920
						$wpdb->prefix . 'woocommerce_shipping_table_rates',
921
						array(
922
							'shipping_method_id' => $new_instance_id
923
						),
924
						array(
925
							'shipping_method_id' => $old_method->shipping_method_id
926
						)
927
					);
928
				} elseif ( 'flat_rate_boxes' === $old_method->shipping_method_type ) {
929
					$wpdb->update(
930
						$wpdb->prefix . 'woocommerce_shipping_flat_rate_boxes',
931
						array(
932
							'shipping_method_id' => $new_instance_id
933
						),
934
						array(
935
							'shipping_method_id' => $old_method->shipping_method_id
936
						)
937
					);
938
				}
939
940
				$changes[ $old_method->shipping_method_id ] = $new_instance_id;
941
			}
942
943
			// $changes contains keys (old method ids) and values (new instance ids) if extra processing is needed in plugins.
944
			// Store this to an option so extensions can pick it up later, then fire an action.
945
			update_option( 'woocommerce_updated_instance_ids', $changes );
946
			do_action( 'woocommerce_updated_instance_ids', $changes );
947
		}
948
	}
949
}
950
951
function wc_update_260_refunds() {
952
	global $wpdb;
953
	/**
954
	 * Refund item qty should be negative
955
	 */
956
	$wpdb->query( "
957
	UPDATE {$wpdb->prefix}woocommerce_order_itemmeta as item_meta
958
	LEFT JOIN {$wpdb->prefix}woocommerce_order_items as items ON item_meta.order_item_id = items.order_item_id
959
	LEFT JOIN {$wpdb->posts} as posts ON items.order_id = posts.ID
960
	SET item_meta.meta_value = item_meta.meta_value * -1
961
	WHERE item_meta.meta_value > 0 AND item_meta.meta_key = '_qty' AND posts.post_type = 'shop_order_refund'
962
	" );
963
}
964
965
function wc_update_260_db_version() {
966
	WC_Install::update_db_version( '2.6.0' );
967
}
968