PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 5.0.0
WooCommerce v5.0.0
10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / includes / wc-update-functions.php
woocommerce / includes Last commit date
abstracts 5 years ago admin 5 years ago cli 5 years ago customizer 5 years ago data-stores 5 years ago emails 5 years ago export 5 years ago gateways 5 years ago import 5 years ago integrations 5 years ago interfaces 5 years ago legacy 5 years ago libraries 6 years ago log-handlers 5 years ago payment-tokens 5 years ago queue 5 years ago rest-api 5 years ago shipping 5 years ago shortcodes 5 years ago theme-support 5 years ago tracks 5 years ago traits 5 years ago walkers 5 years ago wccom-site 5 years ago widgets 5 years ago class-wc-ajax.php 5 years ago class-wc-api.php 5 years ago class-wc-auth.php 5 years ago class-wc-autoloader.php 5 years ago class-wc-background-emailer.php 5 years ago class-wc-background-updater.php 5 years ago class-wc-breadcrumb.php 5 years ago class-wc-cache-helper.php 5 years ago class-wc-cart-fees.php 5 years ago class-wc-cart-session.php 5 years ago class-wc-cart-totals.php 5 years ago class-wc-cart.php 5 years ago class-wc-checkout.php 5 years ago class-wc-cli.php 8 years ago class-wc-comments.php 5 years ago class-wc-countries.php 5 years ago class-wc-coupon.php 5 years ago class-wc-customer-download-log.php 5 years ago class-wc-customer-download.php 5 years ago class-wc-customer.php 5 years ago class-wc-data-exception.php 8 years ago class-wc-data-store.php 6 years ago class-wc-datetime.php 5 years ago class-wc-deprecated-action-hooks.php 8 years ago class-wc-deprecated-filter-hooks.php 7 years ago class-wc-discounts.php 5 years ago class-wc-download-handler.php 5 years ago class-wc-emails.php 5 years ago class-wc-embed.php 5 years ago class-wc-form-handler.php 5 years ago class-wc-frontend-scripts.php 5 years ago class-wc-geo-ip.php 5 years ago class-wc-geolite-integration.php 6 years ago class-wc-geolocation.php 5 years ago class-wc-https.php 5 years ago class-wc-install.php 5 years ago class-wc-integrations.php 5 years ago class-wc-log-levels.php 5 years ago class-wc-logger.php 5 years ago class-wc-meta-data.php 7 years ago class-wc-order-factory.php 5 years ago class-wc-order-item-coupon.php 5 years ago class-wc-order-item-fee.php 5 years ago class-wc-order-item-meta.php 5 years ago class-wc-order-item-product.php 5 years ago class-wc-order-item-shipping.php 5 years ago class-wc-order-item-tax.php 5 years ago class-wc-order-item.php 5 years ago class-wc-order-query.php 5 years ago class-wc-order-refund.php 5 years ago class-wc-order.php 5 years ago class-wc-payment-gateways.php 5 years ago class-wc-payment-tokens.php 5 years ago class-wc-post-data.php 5 years ago class-wc-post-types.php 5 years ago class-wc-privacy-background-process.php 5 years ago class-wc-privacy-erasers.php 6 years ago class-wc-privacy-exporters.php 6 years ago class-wc-privacy.php 5 years ago class-wc-product-attribute.php 5 years ago class-wc-product-download.php 5 years ago class-wc-product-external.php 5 years ago class-wc-product-factory.php 5 years ago class-wc-product-grouped.php 8 years ago class-wc-product-query.php 5 years ago class-wc-product-simple.php 5 years ago class-wc-product-variable.php 5 years ago class-wc-product-variation.php 5 years ago class-wc-query.php 5 years ago class-wc-rate-limiter.php 5 years ago class-wc-regenerate-images-request.php 5 years ago class-wc-regenerate-images.php 5 years ago class-wc-register-wp-admin-settings.php 5 years ago class-wc-rest-authentication.php 5 years ago class-wc-rest-exception.php 5 years ago class-wc-session-handler.php 5 years ago class-wc-shipping-rate.php 5 years ago class-wc-shipping-zone.php 5 years ago class-wc-shipping-zones.php 5 years ago class-wc-shipping.php 5 years ago class-wc-shortcodes.php 5 years ago class-wc-structured-data.php 5 years ago class-wc-tax.php 5 years ago class-wc-template-loader.php 5 years ago class-wc-tracker.php 5 years ago class-wc-validation.php 5 years ago class-wc-webhook.php 5 years ago class-woocommerce.php 5 years ago wc-account-functions.php 5 years ago wc-attribute-functions.php 5 years ago wc-cart-functions.php 5 years ago wc-conditional-functions.php 5 years ago wc-core-functions.php 5 years ago wc-coupon-functions.php 5 years ago wc-deprecated-functions.php 5 years ago wc-formatting-functions.php 5 years ago wc-notice-functions.php 5 years ago wc-order-functions.php 5 years ago wc-order-item-functions.php 5 years ago wc-page-functions.php 5 years ago wc-product-functions.php 5 years ago wc-rest-functions.php 5 years ago wc-stock-functions.php 5 years ago wc-template-functions.php 5 years ago wc-template-hooks.php 5 years ago wc-term-functions.php 5 years ago wc-update-functions.php 5 years ago wc-user-functions.php 5 years ago wc-webhook-functions.php 5 years ago wc-widget-functions.php 5 years ago
wc-update-functions.php
2286 lines
1 <?php
2 /**
3 * WooCommerce Updates
4 *
5 * Functions for updating data, used by the background updater.
6 *
7 * @package WooCommerce\Functions
8 * @version 3.3.0
9 */
10
11 defined( 'ABSPATH' ) || exit;
12
13 /**
14 * Update file paths for 2.0
15 *
16 * @return void
17 */
18 function wc_update_200_file_paths() {
19 global $wpdb;
20
21 // Upgrade old style files paths to support multiple file paths.
22 $existing_file_paths = $wpdb->get_results( "SELECT meta_value, meta_id, post_id FROM {$wpdb->postmeta} WHERE meta_key = '_file_path' AND meta_value != '';" );
23
24 if ( $existing_file_paths ) {
25
26 foreach ( $existing_file_paths as $existing_file_path ) {
27
28 $old_file_path = trim( $existing_file_path->meta_value );
29
30 if ( ! empty( $old_file_path ) ) {
31 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
32 $file_paths = serialize( array( md5( $old_file_path ) => $old_file_path ) );
33
34 $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 ) );
35
36 $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 ) );
37
38 }
39 }
40 }
41 }
42
43 /**
44 * Update permalinks for 2.0
45 *
46 * @return void
47 */
48 function wc_update_200_permalinks() {
49 // Setup default permalinks if shop page is defined.
50 $permalinks = get_option( 'woocommerce_permalinks' );
51 $shop_page_id = wc_get_page_id( 'shop' );
52
53 if ( empty( $permalinks ) && $shop_page_id > 0 ) {
54
55 $base_slug = $shop_page_id > 0 && get_post( $shop_page_id ) ? get_page_uri( $shop_page_id ) : 'shop';
56
57 $category_base = 'yes' === get_option( 'woocommerce_prepend_shop_page_to_urls' ) ? trailingslashit( $base_slug ) : '';
58 $category_slug = get_option( 'woocommerce_product_category_slug' ) ? get_option( 'woocommerce_product_category_slug' ) : _x( 'product-category', 'slug', 'woocommerce' );
59 $tag_slug = get_option( 'woocommerce_product_tag_slug' ) ? get_option( 'woocommerce_product_tag_slug' ) : _x( 'product-tag', 'slug', 'woocommerce' );
60
61 if ( 'yes' === get_option( 'woocommerce_prepend_shop_page_to_products' ) ) {
62 $product_base = trailingslashit( $base_slug );
63 } else {
64 $product_slug = get_option( 'woocommerce_product_slug' );
65 if ( false !== $product_slug && ! empty( $product_slug ) ) {
66 $product_base = trailingslashit( $product_slug );
67 } else {
68 $product_base = trailingslashit( _x( 'product', 'slug', 'woocommerce' ) );
69 }
70 }
71
72 if ( 'yes' === get_option( 'woocommerce_prepend_category_to_products' ) ) {
73 $product_base .= trailingslashit( '%product_cat%' );
74 }
75
76 $permalinks = array(
77 'product_base' => untrailingslashit( $product_base ),
78 'category_base' => untrailingslashit( $category_base . $category_slug ),
79 'attribute_base' => untrailingslashit( $category_base ),
80 'tag_base' => untrailingslashit( $category_base . $tag_slug ),
81 );
82
83 update_option( 'woocommerce_permalinks', $permalinks );
84 }
85 }
86
87 /**
88 * Update sub-category display options for 2.0
89 *
90 * @return void
91 */
92 function wc_update_200_subcat_display() {
93 // Update subcat display settings.
94 if ( 'yes' === get_option( 'woocommerce_shop_show_subcategories' ) ) {
95 if ( 'yes' === get_option( 'woocommerce_hide_products_when_showing_subcategories' ) ) {
96 update_option( 'woocommerce_shop_page_display', 'subcategories' );
97 } else {
98 update_option( 'woocommerce_shop_page_display', 'both' );
99 }
100 }
101
102 if ( 'yes' === get_option( 'woocommerce_show_subcategories' ) ) {
103 if ( 'yes' === get_option( 'woocommerce_hide_products_when_showing_subcategories' ) ) {
104 update_option( 'woocommerce_category_archive_display', 'subcategories' );
105 } else {
106 update_option( 'woocommerce_category_archive_display', 'both' );
107 }
108 }
109 }
110
111 /**
112 * Update tax rates for 2.0
113 *
114 * @return void
115 */
116 function wc_update_200_taxrates() {
117 global $wpdb;
118
119 // Update tax rates.
120 $loop = 0;
121 $tax_rates = get_option( 'woocommerce_tax_rates' );
122
123 if ( $tax_rates ) {
124 foreach ( $tax_rates as $tax_rate ) {
125
126 foreach ( $tax_rate['countries'] as $country => $states ) {
127
128 $states = array_reverse( $states );
129
130 foreach ( $states as $state ) {
131
132 if ( '*' === $state ) {
133 $state = '';
134 }
135
136 $wpdb->insert(
137 $wpdb->prefix . 'woocommerce_tax_rates',
138 array(
139 'tax_rate_country' => $country,
140 'tax_rate_state' => $state,
141 'tax_rate' => $tax_rate['rate'],
142 'tax_rate_name' => $tax_rate['label'],
143 'tax_rate_priority' => 1,
144 'tax_rate_compound' => ( 'yes' === $tax_rate['compound'] ) ? 1 : 0,
145 'tax_rate_shipping' => ( 'yes' === $tax_rate['shipping'] ) ? 1 : 0,
146 'tax_rate_order' => $loop,
147 'tax_rate_class' => $tax_rate['class'],
148 )
149 );
150
151 $loop++;
152 }
153 }
154 }
155 }
156
157 $local_tax_rates = get_option( 'woocommerce_local_tax_rates' );
158
159 if ( $local_tax_rates ) {
160 foreach ( $local_tax_rates as $tax_rate ) {
161
162 $location_type = ( 'postcode' === $tax_rate['location_type'] ) ? 'postcode' : 'city';
163
164 if ( '*' === $tax_rate['state'] ) {
165 $tax_rate['state'] = '';
166 }
167
168 $wpdb->insert(
169 $wpdb->prefix . 'woocommerce_tax_rates',
170 array(
171 'tax_rate_country' => $tax_rate['country'],
172 'tax_rate_state' => $tax_rate['state'],
173 'tax_rate' => $tax_rate['rate'],
174 'tax_rate_name' => $tax_rate['label'],
175 'tax_rate_priority' => 2,
176 'tax_rate_compound' => ( 'yes' === $tax_rate['compound'] ) ? 1 : 0,
177 'tax_rate_shipping' => ( 'yes' === $tax_rate['shipping'] ) ? 1 : 0,
178 'tax_rate_order' => $loop,
179 'tax_rate_class' => $tax_rate['class'],
180 )
181 );
182
183 $tax_rate_id = $wpdb->insert_id;
184
185 if ( $tax_rate['locations'] ) {
186 foreach ( $tax_rate['locations'] as $location ) {
187
188 $wpdb->insert(
189 $wpdb->prefix . 'woocommerce_tax_rate_locations',
190 array(
191 'location_code' => $location,
192 'tax_rate_id' => $tax_rate_id,
193 'location_type' => $location_type,
194 )
195 );
196
197 }
198 }
199
200 $loop++;
201 }
202 }
203
204 update_option( 'woocommerce_tax_rates_backup', $tax_rates );
205 update_option( 'woocommerce_local_tax_rates_backup', $local_tax_rates );
206 delete_option( 'woocommerce_tax_rates' );
207 delete_option( 'woocommerce_local_tax_rates' );
208 }
209
210 /**
211 * Update order item line items for 2.0
212 *
213 * @return void
214 */
215 function wc_update_200_line_items() {
216 global $wpdb;
217
218 // Now its time for the massive update to line items - move them to the new DB tables.
219 // Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_items' WHERE meta_key = '_order_items_old'.
220 $order_item_rows = $wpdb->get_results(
221 "SELECT meta_value, post_id FROM {$wpdb->postmeta} WHERE meta_key = '_order_items'"
222 );
223
224 foreach ( $order_item_rows as $order_item_row ) {
225
226 $order_items = (array) maybe_unserialize( $order_item_row->meta_value );
227
228 foreach ( $order_items as $order_item ) {
229
230 if ( ! isset( $order_item['line_total'] ) && isset( $order_item['taxrate'] ) && isset( $order_item['cost'] ) ) {
231 $order_item['line_tax'] = number_format( ( $order_item['cost'] * $order_item['qty'] ) * ( $order_item['taxrate'] / 100 ), 2, '.', '' );
232 $order_item['line_total'] = $order_item['cost'] * $order_item['qty'];
233 $order_item['line_subtotal_tax'] = $order_item['line_tax'];
234 $order_item['line_subtotal'] = $order_item['line_total'];
235 }
236
237 $order_item['line_tax'] = isset( $order_item['line_tax'] ) ? $order_item['line_tax'] : 0;
238 $order_item['line_total'] = isset( $order_item['line_total'] ) ? $order_item['line_total'] : 0;
239 $order_item['line_subtotal_tax'] = isset( $order_item['line_subtotal_tax'] ) ? $order_item['line_subtotal_tax'] : 0;
240 $order_item['line_subtotal'] = isset( $order_item['line_subtotal'] ) ? $order_item['line_subtotal'] : 0;
241
242 $item_id = wc_add_order_item(
243 $order_item_row->post_id,
244 array(
245 'order_item_name' => $order_item['name'],
246 'order_item_type' => 'line_item',
247 )
248 );
249
250 // Add line item meta.
251 if ( $item_id ) {
252 wc_add_order_item_meta( $item_id, '_qty', absint( $order_item['qty'] ) );
253 wc_add_order_item_meta( $item_id, '_tax_class', $order_item['tax_class'] );
254 wc_add_order_item_meta( $item_id, '_product_id', $order_item['id'] );
255 wc_add_order_item_meta( $item_id, '_variation_id', $order_item['variation_id'] );
256 wc_add_order_item_meta( $item_id, '_line_subtotal', wc_format_decimal( $order_item['line_subtotal'] ) );
257 wc_add_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( $order_item['line_subtotal_tax'] ) );
258 wc_add_order_item_meta( $item_id, '_line_total', wc_format_decimal( $order_item['line_total'] ) );
259 wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $order_item['line_tax'] ) );
260
261 $meta_rows = array();
262
263 // Insert meta.
264 if ( ! empty( $order_item['item_meta'] ) ) {
265 foreach ( $order_item['item_meta'] as $key => $meta ) {
266 // Backwards compatibility.
267 if ( is_array( $meta ) && isset( $meta['meta_name'] ) ) {
268 $meta_rows[] = '(' . $item_id . ',"' . esc_sql( $meta['meta_name'] ) . '","' . esc_sql( $meta['meta_value'] ) . '")';
269 } else {
270 $meta_rows[] = '(' . $item_id . ',"' . esc_sql( $key ) . '","' . esc_sql( $meta ) . '")';
271 }
272 }
273 }
274
275 // Insert meta rows at once.
276 if ( count( $meta_rows ) > 0 ) {
277 $wpdb->query(
278 $wpdb->prepare(
279 "INSERT INTO {$wpdb->prefix}woocommerce_order_itemmeta ( order_item_id, meta_key, meta_value )
280 VALUES " . implode( ',', $meta_rows ) . ';', // @codingStandardsIgnoreLine
281 $order_item_row->post_id
282 )
283 );
284 }
285
286 // Delete from DB (rename).
287 $wpdb->query(
288 $wpdb->prepare(
289 "UPDATE {$wpdb->postmeta}
290 SET meta_key = '_order_items_old'
291 WHERE meta_key = '_order_items'
292 AND post_id = %d",
293 $order_item_row->post_id
294 )
295 );
296 }
297
298 unset( $meta_rows, $item_id, $order_item );
299 }
300 }
301
302 // Do the same kind of update for order_taxes - move to lines.
303 // Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_taxes' WHERE meta_key = '_order_taxes_old'.
304 $order_tax_rows = $wpdb->get_results(
305 "SELECT meta_value, post_id FROM {$wpdb->postmeta}
306 WHERE meta_key = '_order_taxes'"
307 );
308
309 foreach ( $order_tax_rows as $order_tax_row ) {
310
311 $order_taxes = (array) maybe_unserialize( $order_tax_row->meta_value );
312
313 if ( ! empty( $order_taxes ) ) {
314 foreach ( $order_taxes as $order_tax ) {
315
316 if ( ! isset( $order_tax['label'] ) || ! isset( $order_tax['cart_tax'] ) || ! isset( $order_tax['shipping_tax'] ) ) {
317 continue;
318 }
319
320 $item_id = wc_add_order_item(
321 $order_tax_row->post_id,
322 array(
323 'order_item_name' => $order_tax['label'],
324 'order_item_type' => 'tax',
325 )
326 );
327
328 // Add line item meta.
329 if ( $item_id ) {
330 wc_add_order_item_meta( $item_id, 'compound', absint( isset( $order_tax['compound'] ) ? $order_tax['compound'] : 0 ) );
331 wc_add_order_item_meta( $item_id, 'tax_amount', wc_clean( $order_tax['cart_tax'] ) );
332 wc_add_order_item_meta( $item_id, 'shipping_tax_amount', wc_clean( $order_tax['shipping_tax'] ) );
333 }
334
335 // Delete from DB (rename).
336 $wpdb->query(
337 $wpdb->prepare(
338 "UPDATE {$wpdb->postmeta}
339 SET meta_key = '_order_taxes_old'
340 WHERE meta_key = '_order_taxes'
341 AND post_id = %d",
342 $order_tax_row->post_id
343 )
344 );
345
346 unset( $tax_amount );
347 }
348 }
349 }
350 }
351
352 /**
353 * Update image settings for 2.0
354 *
355 * @return void
356 */
357 function wc_update_200_images() {
358 // Grab the pre 2.0 Image options and use to populate the new image options settings,
359 // cleaning up afterwards like nice people do.
360 foreach ( array( 'catalog', 'single', 'thumbnail' ) as $value ) {
361
362 $old_settings = array_filter(
363 array(
364 'width' => get_option( 'woocommerce_' . $value . '_image_width' ),
365 'height' => get_option( 'woocommerce_' . $value . '_image_height' ),
366 'crop' => get_option( 'woocommerce_' . $value . '_image_crop' ),
367 )
368 );
369
370 if ( ! empty( $old_settings ) && update_option( 'shop_' . $value . '_image_size', $old_settings ) ) {
371
372 delete_option( 'woocommerce_' . $value . '_image_width' );
373 delete_option( 'woocommerce_' . $value . '_image_height' );
374 delete_option( 'woocommerce_' . $value . '_image_crop' );
375
376 }
377 }
378 }
379
380 /**
381 * Update DB version for 2.0
382 *
383 * @return void
384 */
385 function wc_update_200_db_version() {
386 WC_Install::update_db_version( '2.0.0' );
387 }
388
389 /**
390 * Update Brazilian States for 2.0.9
391 *
392 * @return void
393 */
394 function wc_update_209_brazillian_state() {
395 global $wpdb;
396
397 // phpcs:disable WordPress.DB.SlowDBQuery
398
399 // Update brazillian state codes.
400 $wpdb->update(
401 $wpdb->postmeta,
402 array(
403 'meta_value' => 'BA',
404 ),
405 array(
406 'meta_key' => '_billing_state',
407 'meta_value' => 'BH',
408 )
409 );
410 $wpdb->update(
411 $wpdb->postmeta,
412 array(
413 'meta_value' => 'BA',
414 ),
415 array(
416 'meta_key' => '_shipping_state',
417 'meta_value' => 'BH',
418 )
419 );
420 $wpdb->update(
421 $wpdb->usermeta,
422 array(
423 'meta_value' => 'BA',
424 ),
425 array(
426 'meta_key' => 'billing_state',
427 'meta_value' => 'BH',
428 )
429 );
430 $wpdb->update(
431 $wpdb->usermeta,
432 array(
433 'meta_value' => 'BA',
434 ),
435 array(
436 'meta_key' => 'shipping_state',
437 'meta_value' => 'BH',
438 )
439 );
440
441 // phpcs:enable WordPress.DB.SlowDBQuery
442 }
443
444 /**
445 * Update DB version for 2.0.9
446 *
447 * @return void
448 */
449 function wc_update_209_db_version() {
450 WC_Install::update_db_version( '2.0.9' );
451 }
452
453 /**
454 * Remove pages for 2.1
455 *
456 * @return void
457 */
458 function wc_update_210_remove_pages() {
459 // Pages no longer used.
460 wp_trash_post( get_option( 'woocommerce_pay_page_id' ) );
461 wp_trash_post( get_option( 'woocommerce_thanks_page_id' ) );
462 wp_trash_post( get_option( 'woocommerce_view_order_page_id' ) );
463 wp_trash_post( get_option( 'woocommerce_change_password_page_id' ) );
464 wp_trash_post( get_option( 'woocommerce_edit_address_page_id' ) );
465 wp_trash_post( get_option( 'woocommerce_lost_password_page_id' ) );
466 }
467
468 /**
469 * Update file paths to support multiple files for 2.1
470 *
471 * @return void
472 */
473 function wc_update_210_file_paths() {
474 global $wpdb;
475
476 // Upgrade file paths to support multiple file paths + names etc.
477 $existing_file_paths = $wpdb->get_results( "SELECT meta_value, meta_id FROM {$wpdb->postmeta} WHERE meta_key = '_file_paths' AND meta_value != '';" );
478
479 if ( $existing_file_paths ) {
480
481 foreach ( $existing_file_paths as $existing_file_path ) {
482
483 $needs_update = false;
484 $new_value = array();
485 $value = maybe_unserialize( trim( $existing_file_path->meta_value ) );
486
487 if ( $value ) {
488 foreach ( $value as $key => $file ) {
489 if ( ! is_array( $file ) ) {
490 $needs_update = true;
491 $new_value[ $key ] = array(
492 'file' => $file,
493 'name' => wc_get_filename_from_url( $file ),
494 );
495 } else {
496 $new_value[ $key ] = $file;
497 }
498 }
499 if ( $needs_update ) {
500 // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
501 $new_value = serialize( $new_value );
502
503 $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 ) );
504 }
505 }
506 }
507 }
508 }
509
510 /**
511 * Update DB version for 2.1
512 *
513 * @return void
514 */
515 function wc_update_210_db_version() {
516 WC_Install::update_db_version( '2.1.0' );
517 }
518
519 /**
520 * Update shipping options for 2.2
521 *
522 * @return void
523 */
524 function wc_update_220_shipping() {
525 $woocommerce_ship_to_destination = 'shipping';
526
527 if ( get_option( 'woocommerce_ship_to_billing_address_only' ) === 'yes' ) {
528 $woocommerce_ship_to_destination = 'billing_only';
529 } elseif ( get_option( 'woocommerce_ship_to_billing' ) === 'yes' ) {
530 $woocommerce_ship_to_destination = 'billing';
531 }
532
533 add_option( 'woocommerce_ship_to_destination', $woocommerce_ship_to_destination, '', 'no' );
534 }
535
536 /**
537 * Update order statuses for 2.2
538 *
539 * @return void
540 */
541 function wc_update_220_order_status() {
542 global $wpdb;
543 $wpdb->query(
544 "UPDATE {$wpdb->posts} as posts
545 LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
546 LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
547 LEFT JOIN {$wpdb->terms} AS term USING( term_id )
548 SET posts.post_status = 'wc-pending'
549 WHERE posts.post_type = 'shop_order'
550 AND posts.post_status = 'publish'
551 AND tax.taxonomy = 'shop_order_status'
552 AND term.slug LIKE 'pending%';"
553 );
554 $wpdb->query(
555 "UPDATE {$wpdb->posts} as posts
556 LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
557 LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
558 LEFT JOIN {$wpdb->terms} AS term USING( term_id )
559 SET posts.post_status = 'wc-processing'
560 WHERE posts.post_type = 'shop_order'
561 AND posts.post_status = 'publish'
562 AND tax.taxonomy = 'shop_order_status'
563 AND term.slug LIKE 'processing%';"
564 );
565 $wpdb->query(
566 "UPDATE {$wpdb->posts} as posts
567 LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
568 LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
569 LEFT JOIN {$wpdb->terms} AS term USING( term_id )
570 SET posts.post_status = 'wc-on-hold'
571 WHERE posts.post_type = 'shop_order'
572 AND posts.post_status = 'publish'
573 AND tax.taxonomy = 'shop_order_status'
574 AND term.slug LIKE 'on-hold%';"
575 );
576 $wpdb->query(
577 "UPDATE {$wpdb->posts} as posts
578 LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
579 LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
580 LEFT JOIN {$wpdb->terms} AS term USING( term_id )
581 SET posts.post_status = 'wc-completed'
582 WHERE posts.post_type = 'shop_order'
583 AND posts.post_status = 'publish'
584 AND tax.taxonomy = 'shop_order_status'
585 AND term.slug LIKE 'completed%';"
586 );
587 $wpdb->query(
588 "UPDATE {$wpdb->posts} as posts
589 LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
590 LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
591 LEFT JOIN {$wpdb->terms} AS term USING( term_id )
592 SET posts.post_status = 'wc-cancelled'
593 WHERE posts.post_type = 'shop_order'
594 AND posts.post_status = 'publish'
595 AND tax.taxonomy = 'shop_order_status'
596 AND term.slug LIKE 'cancelled%';"
597 );
598 $wpdb->query(
599 "UPDATE {$wpdb->posts} as posts
600 LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
601 LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
602 LEFT JOIN {$wpdb->terms} AS term USING( term_id )
603 SET posts.post_status = 'wc-refunded'
604 WHERE posts.post_type = 'shop_order'
605 AND posts.post_status = 'publish'
606 AND tax.taxonomy = 'shop_order_status'
607 AND term.slug LIKE 'refunded%';"
608 );
609 $wpdb->query(
610 "UPDATE {$wpdb->posts} as posts
611 LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id
612 LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
613 LEFT JOIN {$wpdb->terms} AS term USING( term_id )
614 SET posts.post_status = 'wc-failed'
615 WHERE posts.post_type = 'shop_order'
616 AND posts.post_status = 'publish'
617 AND tax.taxonomy = 'shop_order_status'
618 AND term.slug LIKE 'failed%';"
619 );
620 }
621
622 /**
623 * Update variations for 2.2
624 *
625 * @return void
626 */
627 function wc_update_220_variations() {
628 global $wpdb;
629 // Update variations which manage stock.
630 $update_variations = $wpdb->get_results(
631 "SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent FROM {$wpdb->posts} as posts
632 LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock'
633 LEFT OUTER JOIN {$wpdb->postmeta} as postmeta2 ON posts.ID = postmeta2.post_id AND postmeta2.meta_key = '_manage_stock'
634 WHERE posts.post_type = 'product_variation'
635 AND postmeta.meta_value IS NOT NULL
636 AND postmeta.meta_value != ''
637 AND postmeta2.meta_value IS NULL"
638 );
639
640 foreach ( $update_variations as $variation ) {
641 $parent_backorders = get_post_meta( $variation->variation_parent, '_backorders', true );
642 add_post_meta( $variation->variation_id, '_manage_stock', 'yes', true );
643 add_post_meta( $variation->variation_id, '_backorders', $parent_backorders ? $parent_backorders : 'no', true );
644 }
645 }
646
647 /**
648 * Update attributes for 2.2
649 *
650 * @return void
651 */
652 function wc_update_220_attributes() {
653 global $wpdb;
654 // Update taxonomy names with correct sanitized names.
655 $attribute_taxonomies = $wpdb->get_results( 'SELECT attribute_name, attribute_id FROM ' . $wpdb->prefix . 'woocommerce_attribute_taxonomies' );
656
657 foreach ( $attribute_taxonomies as $attribute_taxonomy ) {
658 $sanitized_attribute_name = wc_sanitize_taxonomy_name( $attribute_taxonomy->attribute_name );
659 if ( $sanitized_attribute_name !== $attribute_taxonomy->attribute_name ) {
660 if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT 1=1 FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_name = %s;", $sanitized_attribute_name ) ) ) {
661 // Update attribute.
662 $wpdb->update(
663 "{$wpdb->prefix}woocommerce_attribute_taxonomies",
664 array(
665 'attribute_name' => $sanitized_attribute_name,
666 ),
667 array(
668 'attribute_id' => $attribute_taxonomy->attribute_id,
669 )
670 );
671
672 // Update terms.
673 $wpdb->update(
674 $wpdb->term_taxonomy,
675 array( 'taxonomy' => wc_attribute_taxonomy_name( $sanitized_attribute_name ) ),
676 array( 'taxonomy' => 'pa_' . $attribute_taxonomy->attribute_name )
677 );
678 }
679 }
680 }
681
682 delete_transient( 'wc_attribute_taxonomies' );
683 WC_Cache_Helper::invalidate_cache_group( 'woocommerce-attributes' );
684 }
685
686 /**
687 * Update DB version for 2.2
688 *
689 * @return void
690 */
691 function wc_update_220_db_version() {
692 WC_Install::update_db_version( '2.2.0' );
693 }
694
695 /**
696 * Update options for 2.3
697 *
698 * @return void
699 */
700 function wc_update_230_options() {
701 // _money_spent and _order_count may be out of sync - clear them
702 delete_metadata( 'user', 0, '_money_spent', '', true );
703 delete_metadata( 'user', 0, '_order_count', '', true );
704 delete_metadata( 'user', 0, '_last_order', '', true );
705
706 // 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.
707 if ( '' === get_option( 'woocommerce_default_customer_address', false ) && wc_prices_include_tax() ) {
708 update_option( 'woocommerce_default_customer_address', 'base' );
709 }
710 }
711
712 /**
713 * Update DB version for 2.3
714 *
715 * @return void
716 */
717 function wc_update_230_db_version() {
718 WC_Install::update_db_version( '2.3.0' );
719 }
720
721 /**
722 * Update calc discount options for 2.4
723 *
724 * @return void
725 */
726 function wc_update_240_options() {
727 /**
728 * Coupon discount calculations.
729 * Maintain the old coupon logic for upgrades.
730 */
731 update_option( 'woocommerce_calc_discounts_sequentially', 'yes' );
732 }
733
734 /**
735 * Update shipping methods for 2.4
736 *
737 * @return void
738 */
739 function wc_update_240_shipping_methods() {
740 /**
741 * Flat Rate Shipping.
742 * Update legacy options to new math based options.
743 */
744 $shipping_methods = array(
745 'woocommerce_flat_rates' => new WC_Shipping_Legacy_Flat_Rate(),
746 'woocommerce_international_delivery_flat_rates' => new WC_Shipping_Legacy_International_Delivery(),
747 );
748 foreach ( $shipping_methods as $flat_rate_option_key => $shipping_method ) {
749 // Stop this running more than once if routine is repeated.
750 if ( version_compare( $shipping_method->get_option( 'version', 0 ), '2.4.0', '<' ) ) {
751 $shipping_classes = WC()->shipping()->get_shipping_classes();
752 $has_classes = count( $shipping_classes ) > 0;
753 $cost_key = $has_classes ? 'no_class_cost' : 'cost';
754 $min_fee = $shipping_method->get_option( 'minimum_fee' );
755 $math_cost_strings = array(
756 'cost' => array(),
757 'no_class_cost' => array(),
758 );
759
760 $math_cost_strings[ $cost_key ][] = $shipping_method->get_option( 'cost' );
761 $fee = $shipping_method->get_option( 'fee' );
762
763 if ( $fee ) {
764 $math_cost_strings[ $cost_key ][] = strstr( $fee, '%' ) ? '[fee percent="' . str_replace( '%', '', $fee ) . '" min="' . esc_attr( $min_fee ) . '"]' : $fee;
765 }
766
767 foreach ( $shipping_classes as $shipping_class ) {
768 $rate_key = 'class_cost_' . $shipping_class->slug;
769 $math_cost_strings[ $rate_key ] = $math_cost_strings['no_class_cost'];
770 }
771
772 $flat_rates = array_filter( (array) get_option( $flat_rate_option_key, array() ) );
773
774 if ( $flat_rates ) {
775 foreach ( $flat_rates as $shipping_class => $rate ) {
776 $rate_key = 'class_cost_' . $shipping_class;
777 if ( $rate['cost'] || $rate['fee'] ) {
778 $math_cost_strings[ $rate_key ][] = $rate['cost'];
779 $math_cost_strings[ $rate_key ][] = strstr( $rate['fee'], '%' ) ? '[fee percent="' . str_replace( '%', '', $rate['fee'] ) . '" min="' . esc_attr( $min_fee ) . '"]' : $rate['fee'];
780 }
781 }
782 }
783
784 if ( 'item' === $shipping_method->type ) {
785 foreach ( $math_cost_strings as $key => $math_cost_string ) {
786 $math_cost_strings[ $key ] = array_filter( array_map( 'trim', $math_cost_strings[ $key ] ) );
787 if ( ! empty( $math_cost_strings[ $key ] ) ) {
788 $last_key = max( 0, count( $math_cost_strings[ $key ] ) - 1 );
789 $math_cost_strings[ $key ][0] = '( ' . $math_cost_strings[ $key ][0];
790 $math_cost_strings[ $key ][ $last_key ] .= ' ) * [qty]';
791 }
792 }
793 }
794
795 $math_cost_strings['cost'][] = $shipping_method->get_option( 'cost_per_order' );
796
797 // Save settings.
798 foreach ( $math_cost_strings as $option_id => $math_cost_string ) {
799 $shipping_method->settings[ $option_id ] = implode( ' + ', array_filter( $math_cost_string ) );
800 }
801
802 $shipping_method->settings['version'] = '2.4.0';
803 $shipping_method->settings['type'] = 'item' === $shipping_method->settings['type'] ? 'class' : $shipping_method->settings['type'];
804
805 update_option( $shipping_method->plugin_id . $shipping_method->id . '_settings', $shipping_method->settings );
806 }
807 }
808 }
809
810 /**
811 * Update API keys for 2.4
812 *
813 * @return void
814 */
815 function wc_update_240_api_keys() {
816 global $wpdb;
817 /**
818 * Update the old user API keys to the new Apps keys.
819 */
820 $api_users = $wpdb->get_results( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'woocommerce_api_consumer_key'" );
821 $apps_keys = array();
822
823 // Get user data.
824 foreach ( $api_users as $_user ) {
825 $user = get_userdata( $_user->user_id );
826 $apps_keys[] = array(
827 'user_id' => $user->ID,
828 'permissions' => $user->woocommerce_api_key_permissions,
829 'consumer_key' => wc_api_hash( $user->woocommerce_api_consumer_key ),
830 'consumer_secret' => $user->woocommerce_api_consumer_secret,
831 'truncated_key' => substr( $user->woocommerce_api_consumer_secret, -7 ),
832 );
833 }
834
835 if ( ! empty( $apps_keys ) ) {
836 // Create new apps.
837 foreach ( $apps_keys as $app ) {
838 $wpdb->insert(
839 $wpdb->prefix . 'woocommerce_api_keys',
840 $app,
841 array(
842 '%d',
843 '%s',
844 '%s',
845 '%s',
846 '%s',
847 )
848 );
849 }
850
851 // Delete old user keys from usermeta.
852 foreach ( $api_users as $_user ) {
853 $user_id = intval( $_user->user_id );
854 delete_user_meta( $user_id, 'woocommerce_api_consumer_key' );
855 delete_user_meta( $user_id, 'woocommerce_api_consumer_secret' );
856 delete_user_meta( $user_id, 'woocommerce_api_key_permissions' );
857 }
858 }
859 }
860
861 /**
862 * Update webhooks for 2.4
863 *
864 * @return void
865 */
866 function wc_update_240_webhooks() {
867 // phpcs:disable WordPress.DB.SlowDBQuery
868
869 /**
870 * Webhooks.
871 * Make sure order.update webhooks get the woocommerce_order_edit_status hook.
872 */
873 $order_update_webhooks = get_posts(
874 array(
875 'posts_per_page' => -1,
876 'post_type' => 'shop_webhook',
877 'meta_key' => '_topic',
878 'meta_value' => 'order.updated',
879 )
880 );
881 foreach ( $order_update_webhooks as $order_update_webhook ) {
882 $webhook = new WC_Webhook( $order_update_webhook->ID );
883 $webhook->set_topic( 'order.updated' );
884 }
885
886 // phpcs:enable WordPress.DB.SlowDBQuery
887 }
888
889 /**
890 * Update refunds for 2.4
891 *
892 * @return void
893 */
894 function wc_update_240_refunds() {
895 global $wpdb;
896 /**
897 * Refunds for full refunded orders.
898 * Update fully refunded orders to ensure they have a refund line item so reports add up.
899 */
900 $refunded_orders = get_posts(
901 array(
902 'posts_per_page' => -1,
903 'post_type' => 'shop_order',
904 'post_status' => array( 'wc-refunded' ),
905 )
906 );
907
908 // Ensure emails are disabled during this update routine.
909 remove_all_actions( 'woocommerce_order_status_refunded_notification' );
910 remove_all_actions( 'woocommerce_order_partially_refunded_notification' );
911 remove_action( 'woocommerce_order_status_refunded', array( 'WC_Emails', 'send_transactional_email' ) );
912 remove_action( 'woocommerce_order_partially_refunded', array( 'WC_Emails', 'send_transactional_email' ) );
913
914 foreach ( $refunded_orders as $refunded_order ) {
915 $order_total = get_post_meta( $refunded_order->ID, '_order_total', true );
916 $refunded_total = $wpdb->get_var(
917 $wpdb->prepare(
918 "SELECT SUM( postmeta.meta_value )
919 FROM $wpdb->postmeta AS postmeta
920 INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )
921 WHERE postmeta.meta_key = '_refund_amount'
922 AND postmeta.post_id = posts.ID",
923 $refunded_order->ID
924 )
925 );
926
927 if ( $order_total > $refunded_total ) {
928 wc_create_refund(
929 array(
930 'amount' => $order_total - $refunded_total,
931 'reason' => __( 'Order fully refunded', 'woocommerce' ),
932 'order_id' => $refunded_order->ID,
933 'line_items' => array(),
934 'date' => $refunded_order->post_modified,
935 )
936 );
937 }
938 }
939
940 wc_delete_shop_order_transients();
941 }
942
943 /**
944 * Update DB version for 2.4
945 *
946 * @return void
947 */
948 function wc_update_240_db_version() {
949 WC_Install::update_db_version( '2.4.0' );
950 }
951
952 /**
953 * Update variations for 2.4.1
954 *
955 * @return void
956 */
957 function wc_update_241_variations() {
958 global $wpdb;
959
960 // Select variations that don't have any _stock_status implemented on WooCommerce 2.2.
961 $update_variations = $wpdb->get_results(
962 "SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent
963 FROM {$wpdb->posts} as posts
964 LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock_status'
965 WHERE posts.post_type = 'product_variation'
966 AND postmeta.meta_value IS NULL"
967 );
968
969 foreach ( $update_variations as $variation ) {
970 // Get the parent _stock_status.
971 $parent_stock_status = get_post_meta( $variation->variation_parent, '_stock_status', true );
972
973 // Set the _stock_status.
974 add_post_meta( $variation->variation_id, '_stock_status', $parent_stock_status ? $parent_stock_status : 'instock', true );
975
976 // Delete old product children array.
977 delete_transient( 'wc_product_children_' . $variation->variation_parent );
978 }
979
980 // Invalidate old transients such as wc_var_price.
981 WC_Cache_Helper::get_transient_version( 'product', true );
982 }
983
984 /**
985 * Update DB version for 2.4.1
986 *
987 * @return void
988 */
989 function wc_update_241_db_version() {
990 WC_Install::update_db_version( '2.4.1' );
991 }
992
993 /**
994 * Update currency settings for 2.5
995 *
996 * @return void
997 */
998 function wc_update_250_currency() {
999 global $wpdb;
1000 // Fix currency settings for LAK currency.
1001 $current_currency = get_option( 'woocommerce_currency' );
1002
1003 if ( 'KIP' === $current_currency ) {
1004 update_option( 'woocommerce_currency', 'LAK' );
1005 }
1006
1007 // phpcs:disable WordPress.DB.SlowDBQuery
1008
1009 // Update LAK currency code.
1010 $wpdb->update(
1011 $wpdb->postmeta,
1012 array(
1013 'meta_value' => 'LAK',
1014 ),
1015 array(
1016 'meta_key' => '_order_currency',
1017 'meta_value' => 'KIP',
1018 )
1019 );
1020
1021 // phpcs:enable WordPress.DB.SlowDBQuery
1022 }
1023
1024 /**
1025 * Update DB version for 2.5
1026 *
1027 * @return void
1028 */
1029 function wc_update_250_db_version() {
1030 WC_Install::update_db_version( '2.5.0' );
1031 }
1032
1033 /**
1034 * Update ship to countries options for 2.6
1035 *
1036 * @return void
1037 */
1038 function wc_update_260_options() {
1039 // woocommerce_calc_shipping option has been removed in 2.6.
1040 if ( 'no' === get_option( 'woocommerce_calc_shipping' ) ) {
1041 update_option( 'woocommerce_ship_to_countries', 'disabled' );
1042 }
1043
1044 WC_Admin_Notices::add_notice( 'legacy_shipping' );
1045 }
1046
1047 /**
1048 * Update term meta for 2.6
1049 *
1050 * @return void
1051 */
1052 function wc_update_260_termmeta() {
1053 global $wpdb;
1054 /**
1055 * Migrate term meta to WordPress tables.
1056 */
1057 if ( get_option( 'db_version' ) >= 34370 && $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}woocommerce_termmeta';" ) ) {
1058 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;" ) ) {
1059 $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_termmeta" );
1060 wp_cache_flush();
1061 }
1062 }
1063 }
1064
1065 /**
1066 * Update zones for 2.6
1067 *
1068 * @return void
1069 */
1070 function wc_update_260_zones() {
1071 global $wpdb;
1072 /**
1073 * Old (table rate) shipping zones to new core shipping zones migration.
1074 * zone_enabled and zone_type are no longer used, but it's safe to leave them be.
1075 */
1076 if ( $wpdb->get_var( "SHOW COLUMNS FROM `{$wpdb->prefix}woocommerce_shipping_zones` LIKE 'zone_enabled';" ) ) {
1077 $wpdb->query( "ALTER TABLE {$wpdb->prefix}woocommerce_shipping_zones CHANGE `zone_type` `zone_type` VARCHAR(40) NOT NULL DEFAULT '';" );
1078 $wpdb->query( "ALTER TABLE {$wpdb->prefix}woocommerce_shipping_zones CHANGE `zone_enabled` `zone_enabled` INT(1) NOT NULL DEFAULT 1;" );
1079 }
1080 }
1081
1082 /**
1083 * Update zone methods for 2.6
1084 *
1085 * @return void
1086 */
1087 function wc_update_260_zone_methods() {
1088 global $wpdb;
1089
1090 /**
1091 * Shipping zones in WC 2.6.0 use a table named woocommerce_shipping_zone_methods.
1092 * 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).
1093 */
1094 if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}woocommerce_shipping_zone_shipping_methods';" ) ) {
1095 $old_methods = $wpdb->get_results( "SELECT zone_id, shipping_method_type, shipping_method_order, shipping_method_id FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods;" );
1096
1097 if ( $old_methods ) {
1098 $max_new_id = $wpdb->get_var( "SELECT MAX(instance_id) FROM {$wpdb->prefix}woocommerce_shipping_zone_methods" );
1099 $max_old_id = $wpdb->get_var( "SELECT MAX(shipping_method_id) FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods" );
1100
1101 // Avoid ID conflicts.
1102 $wpdb->query( $wpdb->prepare( "ALTER TABLE {$wpdb->prefix}woocommerce_shipping_zone_methods AUTO_INCREMENT = %d;", max( $max_new_id, $max_old_id ) + 1 ) );
1103
1104 // Store changes.
1105 $changes = array();
1106
1107 // Move data.
1108 foreach ( $old_methods as $old_method ) {
1109 $wpdb->insert(
1110 $wpdb->prefix . 'woocommerce_shipping_zone_methods',
1111 array(
1112 'zone_id' => $old_method->zone_id,
1113 'method_id' => $old_method->shipping_method_type,
1114 'method_order' => $old_method->shipping_method_order,
1115 )
1116 );
1117
1118 $new_instance_id = $wpdb->insert_id;
1119
1120 // Move main settings.
1121 $older_settings_key = 'woocommerce_' . $old_method->shipping_method_type . '-' . $old_method->shipping_method_id . '_settings';
1122 $old_settings_key = 'woocommerce_' . $old_method->shipping_method_type . '_' . $old_method->shipping_method_id . '_settings';
1123 add_option( 'woocommerce_' . $old_method->shipping_method_type . '_' . $new_instance_id . '_settings', get_option( $old_settings_key, get_option( $older_settings_key ) ) );
1124
1125 // Handling for table rate and flat rate box shipping.
1126 if ( 'table_rate' === $old_method->shipping_method_type ) {
1127 // Move priority settings.
1128 add_option( 'woocommerce_table_rate_default_priority_' . $new_instance_id, get_option( 'woocommerce_table_rate_default_priority_' . $old_method->shipping_method_id ) );
1129 add_option( 'woocommerce_table_rate_priorities_' . $new_instance_id, get_option( 'woocommerce_table_rate_priorities_' . $old_method->shipping_method_id ) );
1130
1131 // Move rates.
1132 $wpdb->update(
1133 $wpdb->prefix . 'woocommerce_shipping_table_rates',
1134 array(
1135 'shipping_method_id' => $new_instance_id,
1136 ),
1137 array(
1138 'shipping_method_id' => $old_method->shipping_method_id,
1139 )
1140 );
1141 } elseif ( 'flat_rate_boxes' === $old_method->shipping_method_type ) {
1142 $wpdb->update(
1143 $wpdb->prefix . 'woocommerce_shipping_flat_rate_boxes',
1144 array(
1145 'shipping_method_id' => $new_instance_id,
1146 ),
1147 array(
1148 'shipping_method_id' => $old_method->shipping_method_id,
1149 )
1150 );
1151 }
1152
1153 $changes[ $old_method->shipping_method_id ] = $new_instance_id;
1154 }
1155
1156 // $changes contains keys (old method ids) and values (new instance ids) if extra processing is needed in plugins.
1157 // Store this to an option so extensions can pick it up later, then fire an action.
1158 update_option( 'woocommerce_updated_instance_ids', $changes );
1159 do_action( 'woocommerce_updated_instance_ids', $changes );
1160 }
1161 }
1162
1163 // Change ranges used to ...
1164 $wpdb->query( "UPDATE {$wpdb->prefix}woocommerce_shipping_zone_locations SET location_code = REPLACE( location_code, '-', '...' );" );
1165 }
1166
1167 /**
1168 * Update refunds for 2.6
1169 *
1170 * @return void
1171 */
1172 function wc_update_260_refunds() {
1173 global $wpdb;
1174 /**
1175 * Refund item qty should be negative.
1176 */
1177 $wpdb->query(
1178 "UPDATE {$wpdb->prefix}woocommerce_order_itemmeta as item_meta
1179 LEFT JOIN {$wpdb->prefix}woocommerce_order_items as items ON item_meta.order_item_id = items.order_item_id
1180 LEFT JOIN {$wpdb->posts} as posts ON items.order_id = posts.ID
1181 SET item_meta.meta_value = item_meta.meta_value * -1
1182 WHERE item_meta.meta_value > 0 AND item_meta.meta_key = '_qty' AND posts.post_type = 'shop_order_refund'"
1183 );
1184 }
1185
1186 /**
1187 * Update DB version for 2.6
1188 *
1189 * @return void
1190 */
1191 function wc_update_260_db_version() {
1192 WC_Install::update_db_version( '2.6.0' );
1193 }
1194
1195 /**
1196 * Update webhooks for 3.0
1197 *
1198 * @return void
1199 */
1200 function wc_update_300_webhooks() {
1201 // phpcs:disable WordPress.DB.SlowDBQuery
1202
1203 /**
1204 * Make sure product.update webhooks get the woocommerce_product_quick_edit_save
1205 * and woocommerce_product_bulk_edit_save hooks.
1206 */
1207 $product_update_webhooks = get_posts(
1208 array(
1209 'posts_per_page' => -1,
1210 'post_type' => 'shop_webhook',
1211 'meta_key' => '_topic',
1212 'meta_value' => 'product.updated',
1213 )
1214 );
1215 foreach ( $product_update_webhooks as $product_update_webhook ) {
1216 $webhook = new WC_Webhook( $product_update_webhook->ID );
1217 $webhook->set_topic( 'product.updated' );
1218 }
1219
1220 // phpcs:enable WordPress.DB.SlowDBQuery
1221 }
1222
1223 /**
1224 * Add an index to the field comment_type to improve the response time of the query
1225 * used by WC_Comments::wp_count_comments() to get the number of comments by type.
1226 */
1227 function wc_update_300_comment_type_index() {
1228 global $wpdb;
1229
1230 $index_exists = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->comments} WHERE column_name = 'comment_type' and key_name = 'woo_idx_comment_type'" );
1231
1232 if ( is_null( $index_exists ) ) {
1233 // Add an index to the field comment_type to improve the response time of the query
1234 // used by WC_Comments::wp_count_comments() to get the number of comments by type.
1235 $wpdb->query( "ALTER TABLE {$wpdb->comments} ADD INDEX woo_idx_comment_type (comment_type)" );
1236 }
1237 }
1238
1239 /**
1240 * Update grouped products for 3.0
1241 *
1242 * @return void
1243 */
1244 function wc_update_300_grouped_products() {
1245 global $wpdb;
1246 $parents = $wpdb->get_col( "SELECT DISTINCT( post_parent ) FROM {$wpdb->posts} WHERE post_parent > 0 AND post_type = 'product';" );
1247 foreach ( $parents as $parent_id ) {
1248 $parent = wc_get_product( $parent_id );
1249 if ( $parent && $parent->is_type( 'grouped' ) ) {
1250 $children_ids = get_posts(
1251 array(
1252 'post_parent' => $parent_id,
1253 'posts_per_page' => -1,
1254 'post_type' => 'product',
1255 'fields' => 'ids',
1256 )
1257 );
1258 update_post_meta( $parent_id, '_children', $children_ids );
1259
1260 // Update children to remove the parent.
1261 $wpdb->update(
1262 $wpdb->posts,
1263 array(
1264 'post_parent' => 0,
1265 ),
1266 array(
1267 'post_parent' => $parent_id,
1268 )
1269 );
1270 }
1271 }
1272 }
1273
1274 /**
1275 * Update shipping tax classes for 3.0
1276 *
1277 * @return void
1278 */
1279 function wc_update_300_settings() {
1280 $woocommerce_shipping_tax_class = get_option( 'woocommerce_shipping_tax_class' );
1281 if ( '' === $woocommerce_shipping_tax_class ) {
1282 update_option( 'woocommerce_shipping_tax_class', 'inherit' );
1283 } elseif ( 'standard' === $woocommerce_shipping_tax_class ) {
1284 update_option( 'woocommerce_shipping_tax_class', '' );
1285 }
1286 }
1287
1288 /**
1289 * Convert meta values into term for product visibility.
1290 */
1291 function wc_update_300_product_visibility() {
1292 global $wpdb;
1293
1294 WC_Install::create_terms();
1295
1296 $featured_term = get_term_by( 'name', 'featured', 'product_visibility' );
1297
1298 if ( $featured_term ) {
1299 $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_featured' AND meta_value = 'yes';", $featured_term->term_taxonomy_id ) );
1300 }
1301
1302 $exclude_search_term = get_term_by( 'name', 'exclude-from-search', 'product_visibility' );
1303
1304 if ( $exclude_search_term ) {
1305 $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_visibility' AND meta_value IN ('hidden', 'catalog');", $exclude_search_term->term_taxonomy_id ) );
1306 }
1307
1308 $exclude_catalog_term = get_term_by( 'name', 'exclude-from-catalog', 'product_visibility' );
1309
1310 if ( $exclude_catalog_term ) {
1311 $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_visibility' AND meta_value IN ('hidden', 'search');", $exclude_catalog_term->term_taxonomy_id ) );
1312 }
1313
1314 $outofstock_term = get_term_by( 'name', 'outofstock', 'product_visibility' );
1315
1316 if ( $outofstock_term ) {
1317 $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_stock_status' AND meta_value = 'outofstock';", $outofstock_term->term_taxonomy_id ) );
1318 }
1319
1320 $rating_term = get_term_by( 'name', 'rated-1', 'product_visibility' );
1321
1322 if ( $rating_term ) {
1323 $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 1;", $rating_term->term_taxonomy_id ) );
1324 }
1325
1326 $rating_term = get_term_by( 'name', 'rated-2', 'product_visibility' );
1327
1328 if ( $rating_term ) {
1329 $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 2;", $rating_term->term_taxonomy_id ) );
1330 }
1331
1332 $rating_term = get_term_by( 'name', 'rated-3', 'product_visibility' );
1333
1334 if ( $rating_term ) {
1335 $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 3;", $rating_term->term_taxonomy_id ) );
1336 }
1337
1338 $rating_term = get_term_by( 'name', 'rated-4', 'product_visibility' );
1339
1340 if ( $rating_term ) {
1341 $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 4;", $rating_term->term_taxonomy_id ) );
1342 }
1343
1344 $rating_term = get_term_by( 'name', 'rated-5', 'product_visibility' );
1345
1346 if ( $rating_term ) {
1347 $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 5;", $rating_term->term_taxonomy_id ) );
1348 }
1349 }
1350
1351 /**
1352 * Update DB Version.
1353 */
1354 function wc_update_300_db_version() {
1355 WC_Install::update_db_version( '3.0.0' );
1356 }
1357
1358 /**
1359 * Add an index to the downloadable product permissions table to improve performance of update_user_by_order_id.
1360 */
1361 function wc_update_310_downloadable_products() {
1362 global $wpdb;
1363
1364 $index_exists = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE column_name = 'order_id' and key_name = 'order_id'" );
1365
1366 if ( is_null( $index_exists ) ) {
1367 $wpdb->query( "ALTER TABLE {$wpdb->prefix}woocommerce_downloadable_product_permissions ADD INDEX order_id (order_id)" );
1368 }
1369 }
1370
1371 /**
1372 * Find old order notes and ensure they have the correct type for exclusion.
1373 */
1374 function wc_update_310_old_comments() {
1375 global $wpdb;
1376
1377 $wpdb->query( "UPDATE $wpdb->comments comments LEFT JOIN $wpdb->posts as posts ON comments.comment_post_ID = posts.ID SET comment_type = 'order_note' WHERE posts.post_type = 'shop_order' AND comment_type = '';" );
1378 }
1379
1380 /**
1381 * Update DB Version.
1382 */
1383 function wc_update_310_db_version() {
1384 WC_Install::update_db_version( '3.1.0' );
1385 }
1386
1387 /**
1388 * Update shop_manager capabilities.
1389 */
1390 function wc_update_312_shop_manager_capabilities() {
1391 $role = get_role( 'shop_manager' );
1392 $role->remove_cap( 'unfiltered_html' );
1393 }
1394
1395 /**
1396 * Update DB Version.
1397 */
1398 function wc_update_312_db_version() {
1399 WC_Install::update_db_version( '3.1.2' );
1400 }
1401
1402 /**
1403 * Update state codes for Mexico.
1404 */
1405 function wc_update_320_mexican_states() {
1406 global $wpdb;
1407
1408 $mx_states = array(
1409 'Distrito Federal' => 'CMX',
1410 'Jalisco' => 'JAL',
1411 'Nuevo Leon' => 'NLE',
1412 'Aguascalientes' => 'AGS',
1413 'Baja California' => 'BCN',
1414 'Baja California Sur' => 'BCS',
1415 'Campeche' => 'CAM',
1416 'Chiapas' => 'CHP',
1417 'Chihuahua' => 'CHH',
1418 'Coahuila' => 'COA',
1419 'Colima' => 'COL',
1420 'Durango' => 'DGO',
1421 'Guanajuato' => 'GTO',
1422 'Guerrero' => 'GRO',
1423 'Hidalgo' => 'HGO',
1424 'Estado de Mexico' => 'MEX',
1425 'Michoacan' => 'MIC',
1426 'Morelos' => 'MOR',
1427 'Nayarit' => 'NAY',
1428 'Oaxaca' => 'OAX',
1429 'Puebla' => 'PUE',
1430 'Queretaro' => 'QRO',
1431 'Quintana Roo' => 'ROO',
1432 'San Luis Potosi' => 'SLP',
1433 'Sinaloa' => 'SIN',
1434 'Sonora' => 'SON',
1435 'Tabasco' => 'TAB',
1436 'Tamaulipas' => 'TMP',
1437 'Tlaxcala' => 'TLA',
1438 'Veracruz' => 'VER',
1439 'Yucatan' => 'YUC',
1440 'Zacatecas' => 'ZAC',
1441 );
1442
1443 foreach ( $mx_states as $old => $new ) {
1444 $wpdb->query(
1445 $wpdb->prepare(
1446 "UPDATE $wpdb->postmeta
1447 SET meta_value = %s
1448 WHERE meta_key IN ( '_billing_state', '_shipping_state' )
1449 AND meta_value = %s",
1450 $new,
1451 $old
1452 )
1453 );
1454 $wpdb->update(
1455 "{$wpdb->prefix}woocommerce_shipping_zone_locations",
1456 array(
1457 'location_code' => 'MX:' . $new,
1458 ),
1459 array(
1460 'location_code' => 'MX:' . $old,
1461 )
1462 );
1463 $wpdb->update(
1464 "{$wpdb->prefix}woocommerce_tax_rates",
1465 array(
1466 'tax_rate_state' => strtoupper( $new ),
1467 ),
1468 array(
1469 'tax_rate_state' => strtoupper( $old ),
1470 )
1471 );
1472 }
1473 }
1474
1475 /**
1476 * Update DB Version.
1477 */
1478 function wc_update_320_db_version() {
1479 WC_Install::update_db_version( '3.2.0' );
1480 }
1481
1482 /**
1483 * Update image settings to use new aspect ratios and widths.
1484 */
1485 function wc_update_330_image_options() {
1486 $old_thumbnail_size = get_option( 'shop_catalog_image_size', array() );
1487 $old_single_size = get_option( 'shop_single_image_size', array() );
1488
1489 if ( ! empty( $old_thumbnail_size['width'] ) ) {
1490 $width = absint( $old_thumbnail_size['width'] );
1491 $height = absint( $old_thumbnail_size['height'] );
1492 $hard_crop = ! empty( $old_thumbnail_size['crop'] );
1493
1494 if ( ! $width ) {
1495 $width = 300;
1496 }
1497
1498 if ( ! $height ) {
1499 $height = $width;
1500 }
1501
1502 update_option( 'woocommerce_thumbnail_image_width', $width );
1503
1504 // Calculate cropping mode from old image options.
1505 if ( ! $hard_crop ) {
1506 update_option( 'woocommerce_thumbnail_cropping', 'uncropped' );
1507 } elseif ( $width === $height ) {
1508 update_option( 'woocommerce_thumbnail_cropping', '1:1' );
1509 } else {
1510 $ratio = $width / $height;
1511 $fraction = wc_decimal_to_fraction( $ratio );
1512
1513 if ( $fraction ) {
1514 update_option( 'woocommerce_thumbnail_cropping', 'custom' );
1515 update_option( 'woocommerce_thumbnail_cropping_custom_width', $fraction[0] );
1516 update_option( 'woocommerce_thumbnail_cropping_custom_height', $fraction[1] );
1517 }
1518 }
1519 }
1520
1521 // Single is uncropped.
1522 if ( ! empty( $old_single_size['width'] ) ) {
1523 update_option( 'woocommerce_single_image_width', absint( $old_single_size['width'] ) );
1524 }
1525 }
1526
1527 /**
1528 * Migrate webhooks from post type to CRUD.
1529 */
1530 function wc_update_330_webhooks() {
1531 register_post_type( 'shop_webhook' );
1532
1533 // Map statuses from post_type to Webhooks CRUD.
1534 $statuses = array(
1535 'publish' => 'active',
1536 'draft' => 'paused',
1537 'pending' => 'disabled',
1538 );
1539
1540 $posts = get_posts(
1541 array(
1542 'posts_per_page' => -1,
1543 'post_type' => 'shop_webhook',
1544 'post_status' => 'any',
1545 )
1546 );
1547
1548 foreach ( $posts as $post ) {
1549 $webhook = new WC_Webhook();
1550 $webhook->set_name( $post->post_title );
1551 $webhook->set_status( isset( $statuses[ $post->post_status ] ) ? $statuses[ $post->post_status ] : 'disabled' );
1552 $webhook->set_delivery_url( get_post_meta( $post->ID, '_delivery_url', true ) );
1553 $webhook->set_secret( get_post_meta( $post->ID, '_secret', true ) );
1554 $webhook->set_topic( get_post_meta( $post->ID, '_topic', true ) );
1555 $webhook->set_api_version( get_post_meta( $post->ID, '_api_version', true ) );
1556 $webhook->set_user_id( $post->post_author );
1557 $webhook->set_pending_delivery( false );
1558 $webhook->save();
1559
1560 wp_delete_post( $post->ID, true );
1561 }
1562
1563 unregister_post_type( 'shop_webhook' );
1564 }
1565
1566 /**
1567 * Assign default cat to all products with no cats.
1568 */
1569 function wc_update_330_set_default_product_cat() {
1570 global $wpdb;
1571
1572 $default_category = get_option( 'default_product_cat', 0 );
1573
1574 if ( $default_category ) {
1575 $wpdb->query(
1576 $wpdb->prepare(
1577 "INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id)
1578 SELECT DISTINCT posts.ID, %s FROM {$wpdb->posts} posts
1579 LEFT JOIN
1580 (
1581 SELECT object_id FROM {$wpdb->term_relationships} term_relationships
1582 LEFT JOIN {$wpdb->term_taxonomy} term_taxonomy ON term_relationships.term_taxonomy_id = term_taxonomy.term_taxonomy_id
1583 WHERE term_taxonomy.taxonomy = 'product_cat'
1584 ) AS tax_query
1585 ON posts.ID = tax_query.object_id
1586 WHERE posts.post_type = 'product'
1587 AND tax_query.object_id IS NULL",
1588 $default_category
1589 )
1590 );
1591 wp_cache_flush();
1592 delete_transient( 'wc_term_counts' );
1593 wp_update_term_count_now( array( $default_category ), 'product_cat' );
1594 }
1595 }
1596
1597 /**
1598 * Update product stock status to use the new onbackorder status.
1599 */
1600 function wc_update_330_product_stock_status() {
1601 global $wpdb;
1602
1603 if ( 'yes' !== get_option( 'woocommerce_manage_stock' ) ) {
1604 return;
1605 }
1606
1607 $min_stock_amount = (int) get_option( 'woocommerce_notify_no_stock_amount', 0 );
1608
1609 // Get all products that have stock management enabled, stock less than or equal to min stock amount, and backorders enabled.
1610 $post_ids = $wpdb->get_col(
1611 $wpdb->prepare(
1612 "SELECT t1.post_id FROM $wpdb->postmeta t1
1613 INNER JOIN $wpdb->postmeta t2
1614 ON t1.post_id = t2.post_id
1615 AND t1.meta_key = '_manage_stock' AND t1.meta_value = 'yes'
1616 AND t2.meta_key = '_stock' AND t2.meta_value <= %d
1617 INNER JOIN $wpdb->postmeta t3
1618 ON t2.post_id = t3.post_id
1619 AND t3.meta_key = '_backorders' AND ( t3.meta_value = 'yes' OR t3.meta_value = 'notify' )",
1620 $min_stock_amount
1621 )
1622 );
1623
1624 if ( empty( $post_ids ) ) {
1625 return;
1626 }
1627
1628 $post_ids = array_map( 'absint', $post_ids );
1629
1630 // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
1631 // Set the status to onbackorder for those products.
1632 $wpdb->query(
1633 "UPDATE $wpdb->postmeta
1634 SET meta_value = 'onbackorder'
1635 WHERE meta_key = '_stock_status' AND post_id IN ( " . implode( ',', $post_ids ) . ' )'
1636 );
1637 // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
1638 }
1639
1640 /**
1641 * Clear addons page transients
1642 */
1643 function wc_update_330_clear_transients() {
1644 delete_transient( 'wc_addons_sections' );
1645 delete_transient( 'wc_addons_featured' );
1646 }
1647
1648 /**
1649 * Set PayPal's sandbox credentials.
1650 */
1651 function wc_update_330_set_paypal_sandbox_credentials() {
1652
1653 $paypal_settings = get_option( 'woocommerce_paypal_settings' );
1654
1655 if ( isset( $paypal_settings['testmode'] ) && 'yes' === $paypal_settings['testmode'] ) {
1656 foreach ( array( 'api_username', 'api_password', 'api_signature' ) as $credential ) {
1657 if ( ! empty( $paypal_settings[ $credential ] ) ) {
1658 $paypal_settings[ 'sandbox_' . $credential ] = $paypal_settings[ $credential ];
1659 }
1660 }
1661
1662 update_option( 'woocommerce_paypal_settings', $paypal_settings );
1663 }
1664 }
1665
1666 /**
1667 * Update DB Version.
1668 */
1669 function wc_update_330_db_version() {
1670 WC_Install::update_db_version( '3.3.0' );
1671 }
1672
1673 /**
1674 * Update state codes for Ireland and BD.
1675 */
1676 function wc_update_340_states() {
1677 $country_states = array(
1678 'IE' => array(
1679 'CK' => 'CO',
1680 'DN' => 'D',
1681 'GY' => 'G',
1682 'TY' => 'TA',
1683 ),
1684 'BD' => array(
1685 'BAG' => 'BD-05',
1686 'BAN' => 'BD-01',
1687 'BAR' => 'BD-02',
1688 'BARI' => 'BD-06',
1689 'BHO' => 'BD-07',
1690 'BOG' => 'BD-03',
1691 'BRA' => 'BD-04',
1692 'CHA' => 'BD-09',
1693 'CHI' => 'BD-10',
1694 'CHU' => 'BD-12',
1695 'COX' => 'BD-11',
1696 'COM' => 'BD-08',
1697 'DHA' => 'BD-13',
1698 'DIN' => 'BD-14',
1699 'FAR' => 'BD-15',
1700 'FEN' => 'BD-16',
1701 'GAI' => 'BD-19',
1702 'GAZI' => 'BD-18',
1703 'GOP' => 'BD-17',
1704 'HAB' => 'BD-20',
1705 'JAM' => 'BD-21',
1706 'JES' => 'BD-22',
1707 'JHA' => 'BD-25',
1708 'JHE' => 'BD-23',
1709 'JOY' => 'BD-24',
1710 'KHA' => 'BD-29',
1711 'KHU' => 'BD-27',
1712 'KIS' => 'BD-26',
1713 'KUR' => 'BD-28',
1714 'KUS' => 'BD-30',
1715 'LAK' => 'BD-31',
1716 'LAL' => 'BD-32',
1717 'MAD' => 'BD-36',
1718 'MAG' => 'BD-37',
1719 'MAN' => 'BD-33',
1720 'MEH' => 'BD-39',
1721 'MOU' => 'BD-38',
1722 'MUN' => 'BD-35',
1723 'MYM' => 'BD-34',
1724 'NAO' => 'BD-48',
1725 'NAR' => 'BD-43',
1726 'NARG' => 'BD-40',
1727 'NARD' => 'BD-42',
1728 'NAT' => 'BD-44',
1729 'NAW' => 'BD-45',
1730 'NET' => 'BD-41',
1731 'NIL' => 'BD-46',
1732 'NOA' => 'BD-47',
1733 'PAB' => 'BD-49',
1734 'PAN' => 'BD-52',
1735 'PAT' => 'BD-51',
1736 'PIR' => 'BD-50',
1737 'RAJB' => 'BD-53',
1738 'RAJ' => 'BD-54',
1739 'RAN' => 'BD-56',
1740 'RANP' => 'BD-55',
1741 'SAT' => 'BD-58',
1742 'SHA' => 'BD-57',
1743 'SIR' => 'BD-59',
1744 'SUN' => 'BD-61',
1745 'SYL' => 'BD-60',
1746 'TAN' => 'BD-63',
1747 'THA' => 'BD-64',
1748 ),
1749 );
1750
1751 update_option( 'woocommerce_update_340_states', $country_states );
1752 }
1753
1754 /**
1755 * Update next state in the queue.
1756 *
1757 * @return bool True to run again, false if completed.
1758 */
1759 function wc_update_340_state() {
1760 global $wpdb;
1761
1762 $country_states = array_filter( (array) get_option( 'woocommerce_update_340_states', array() ) );
1763
1764 if ( empty( $country_states ) ) {
1765 return false;
1766 }
1767
1768 foreach ( $country_states as $country => $states ) {
1769 foreach ( $states as $old => $new ) {
1770 $wpdb->query(
1771 $wpdb->prepare(
1772 "UPDATE $wpdb->postmeta
1773 SET meta_value = %s
1774 WHERE meta_key IN ( '_billing_state', '_shipping_state' )
1775 AND meta_value = %s",
1776 $new,
1777 $old
1778 )
1779 );
1780 $wpdb->update(
1781 "{$wpdb->prefix}woocommerce_shipping_zone_locations",
1782 array(
1783 'location_code' => $country . ':' . $new,
1784 ),
1785 array(
1786 'location_code' => $country . ':' . $old,
1787 )
1788 );
1789 $wpdb->update(
1790 "{$wpdb->prefix}woocommerce_tax_rates",
1791 array(
1792 'tax_rate_state' => strtoupper( $new ),
1793 ),
1794 array(
1795 'tax_rate_state' => strtoupper( $old ),
1796 )
1797 );
1798 unset( $country_states[ $country ][ $old ] );
1799
1800 if ( empty( $country_states[ $country ] ) ) {
1801 unset( $country_states[ $country ] );
1802 }
1803 break 2;
1804 }
1805 }
1806
1807 if ( ! empty( $country_states ) ) {
1808 return update_option( 'woocommerce_update_340_states', $country_states );
1809 }
1810
1811 delete_option( 'woocommerce_update_340_states' );
1812
1813 return false;
1814 }
1815
1816 /**
1817 * Set last active prop for users.
1818 */
1819 function wc_update_340_last_active() {
1820 global $wpdb;
1821 // @codingStandardsIgnoreStart.
1822 $wpdb->query(
1823 $wpdb->prepare( "
1824 INSERT INTO {$wpdb->usermeta} (user_id, meta_key, meta_value)
1825 SELECT DISTINCT users.ID, 'wc_last_active', %s
1826 FROM {$wpdb->users} as users
1827 LEFT OUTER JOIN {$wpdb->usermeta} AS usermeta ON users.ID = usermeta.user_id AND usermeta.meta_key = 'wc_last_active'
1828 WHERE usermeta.meta_value IS NULL
1829 ",
1830 (string) strtotime( date( 'Y-m-d', current_time( 'timestamp', true ) ) )
1831 )
1832 );
1833 // @codingStandardsIgnoreEnd.
1834 }
1835
1836 /**
1837 * Update DB Version.
1838 */
1839 function wc_update_340_db_version() {
1840 WC_Install::update_db_version( '3.4.0' );
1841 }
1842
1843 /**
1844 * Remove duplicate foreign keys
1845 *
1846 * @return void
1847 */
1848 function wc_update_343_cleanup_foreign_keys() {
1849 global $wpdb;
1850
1851 $results = $wpdb->get_results(
1852 "SELECT CONSTRAINT_NAME
1853 FROM information_schema.TABLE_CONSTRAINTS
1854 WHERE CONSTRAINT_SCHEMA = '{$wpdb->dbname}'
1855 AND CONSTRAINT_NAME LIKE '%wc_download_log_ib%'
1856 AND CONSTRAINT_TYPE = 'FOREIGN KEY'
1857 AND TABLE_NAME = '{$wpdb->prefix}wc_download_log'"
1858 );
1859
1860 if ( $results ) {
1861 foreach ( $results as $fk ) {
1862 $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_download_log DROP FOREIGN KEY {$fk->CONSTRAINT_NAME}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
1863 }
1864 }
1865 }
1866
1867 /**
1868 * Update DB version.
1869 *
1870 * @return void
1871 */
1872 function wc_update_343_db_version() {
1873 WC_Install::update_db_version( '3.4.3' );
1874 }
1875
1876 /**
1877 * Recreate user roles so existing users will get the new capabilities.
1878 *
1879 * @return void
1880 */
1881 function wc_update_344_recreate_roles() {
1882 WC_Install::remove_roles();
1883 WC_Install::create_roles();
1884 }
1885
1886 /**
1887 * Update DB version.
1888 *
1889 * @return void
1890 */
1891 function wc_update_344_db_version() {
1892 WC_Install::update_db_version( '3.4.4' );
1893 }
1894
1895 /**
1896 * Set the comment type to 'review' for product reviews that don't have a comment type.
1897 */
1898 function wc_update_350_reviews_comment_type() {
1899 global $wpdb;
1900
1901 $wpdb->query(
1902 "UPDATE {$wpdb->prefix}comments JOIN {$wpdb->prefix}posts ON {$wpdb->prefix}posts.ID = {$wpdb->prefix}comments.comment_post_ID AND ( {$wpdb->prefix}posts.post_type = 'product' OR {$wpdb->prefix}posts.post_type = 'product_variation' ) SET {$wpdb->prefix}comments.comment_type = 'review' WHERE {$wpdb->prefix}comments.comment_type = ''"
1903 );
1904 }
1905
1906 /**
1907 * Update DB Version.
1908 */
1909 function wc_update_350_db_version() {
1910 WC_Install::update_db_version( '3.5.0' );
1911 }
1912
1913 /**
1914 * Drop the fk_wc_download_log_permission_id FK as we use a new one with the table and blog prefix for MS compatability.
1915 *
1916 * @return void
1917 */
1918 function wc_update_352_drop_download_log_fk() {
1919 global $wpdb;
1920 $results = $wpdb->get_results(
1921 "SELECT CONSTRAINT_NAME
1922 FROM information_schema.TABLE_CONSTRAINTS
1923 WHERE CONSTRAINT_SCHEMA = '{$wpdb->dbname}'
1924 AND CONSTRAINT_NAME = 'fk_wc_download_log_permission_id'
1925 AND CONSTRAINT_TYPE = 'FOREIGN KEY'
1926 AND TABLE_NAME = '{$wpdb->prefix}wc_download_log'"
1927 );
1928
1929 // We only need to drop the old key as WC_Install::create_tables() takes care of creating the new FK.
1930 if ( $results ) {
1931 $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_download_log DROP FOREIGN KEY fk_wc_download_log_permission_id" ); // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
1932 }
1933 }
1934
1935 /**
1936 * Remove edit_user capabilities from shop managers and use "translated" capabilities instead.
1937 * See wc_shop_manager_has_capability function.
1938 */
1939 function wc_update_354_modify_shop_manager_caps() {
1940 global $wp_roles;
1941
1942 if ( ! class_exists( 'WP_Roles' ) ) {
1943 return;
1944 }
1945
1946 if ( ! isset( $wp_roles ) ) {
1947 $wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
1948 }
1949
1950 $wp_roles->remove_cap( 'shop_manager', 'edit_users' );
1951 }
1952
1953 /**
1954 * Update DB Version.
1955 */
1956 function wc_update_354_db_version() {
1957 WC_Install::update_db_version( '3.5.4' );
1958 }
1959
1960 /**
1961 * Update product lookup tables in bulk.
1962 */
1963 function wc_update_360_product_lookup_tables() {
1964 wc_update_product_lookup_tables();
1965 }
1966
1967 /**
1968 * Renames ordering meta to be consistent across taxonomies.
1969 */
1970 function wc_update_360_term_meta() {
1971 global $wpdb;
1972
1973 $wpdb->query( "UPDATE {$wpdb->termmeta} SET meta_key = 'order' WHERE meta_key LIKE 'order_pa_%';" );
1974 }
1975
1976 /**
1977 * Add new user_order_remaining_expires to speed up user download permission fetching.
1978 *
1979 * @return void
1980 */
1981 function wc_update_360_downloadable_product_permissions_index() {
1982 global $wpdb;
1983
1984 $index_exists = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE key_name = 'user_order_remaining_expires'" );
1985
1986 if ( is_null( $index_exists ) ) {
1987 $wpdb->query( "ALTER TABLE {$wpdb->prefix}woocommerce_downloadable_product_permissions ADD INDEX user_order_remaining_expires (user_id,order_id,downloads_remaining,access_expires)" );
1988 }
1989 }
1990
1991 /**
1992 * Update DB Version.
1993 */
1994 function wc_update_360_db_version() {
1995 WC_Install::update_db_version( '3.6.0' );
1996 }
1997
1998 /**
1999 * Put tax classes into a DB table.
2000 *
2001 * @return void
2002 */
2003 function wc_update_370_tax_rate_classes() {
2004 global $wpdb;
2005
2006 $classes = array_map( 'trim', explode( "\n", get_option( 'woocommerce_tax_classes' ) ) );
2007
2008 if ( $classes ) {
2009 foreach ( $classes as $class ) {
2010 if ( empty( $class ) ) {
2011 continue;
2012 }
2013 WC_Tax::create_tax_class( $class );
2014 }
2015 }
2016 delete_option( 'woocommerce_tax_classes' );
2017 }
2018
2019 /**
2020 * Update currency settings for 3.7.0
2021 *
2022 * @return void
2023 */
2024 function wc_update_370_mro_std_currency() {
2025 global $wpdb;
2026
2027 // Fix currency settings for MRU and STN currency.
2028 $current_currency = get_option( 'woocommerce_currency' );
2029
2030 if ( 'MRO' === $current_currency ) {
2031 update_option( 'woocommerce_currency', 'MRU' );
2032 }
2033
2034 if ( 'STD' === $current_currency ) {
2035 update_option( 'woocommerce_currency', 'STN' );
2036 }
2037
2038 // Update MRU currency code.
2039 $wpdb->update(
2040 $wpdb->postmeta,
2041 array(
2042 'meta_value' => 'MRU', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
2043 ),
2044 array(
2045 'meta_key' => '_order_currency', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
2046 'meta_value' => 'MRO', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
2047 )
2048 );
2049
2050 // Update STN currency code.
2051 $wpdb->update(
2052 $wpdb->postmeta,
2053 array(
2054 'meta_value' => 'STN', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
2055 ),
2056 array(
2057 'meta_key' => '_order_currency', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
2058 'meta_value' => 'STD', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
2059 )
2060 );
2061 }
2062
2063 /**
2064 * Update DB Version.
2065 */
2066 function wc_update_370_db_version() {
2067 WC_Install::update_db_version( '3.7.0' );
2068 }
2069
2070 /**
2071 * We've moved the MaxMind database to a new location, as per the TOS' requirement that the database not
2072 * be publicly accessible.
2073 */
2074 function wc_update_390_move_maxmind_database() {
2075 // Make sure to use all of the correct filters to pull the local database path.
2076 $old_path = apply_filters( 'woocommerce_geolocation_local_database_path', WP_CONTENT_DIR . '/uploads/GeoLite2-Country.mmdb', 2 );
2077
2078 // Generate a prefix for the old file and store it in the integration as it would expect it.
2079 $prefix = wp_generate_password( 32, false );
2080 update_option( 'woocommerce_maxmind_geolocation_settings', array( 'database_prefix' => $prefix ) );
2081
2082 // Generate the new path in the same way that the integration will.
2083 $uploads_dir = wp_upload_dir();
2084 $new_path = trailingslashit( $uploads_dir['basedir'] ) . 'woocommerce_uploads/' . $prefix . '-GeoLite2-Country.mmdb';
2085 $new_path = apply_filters( 'woocommerce_geolocation_local_database_path', $new_path, 2 );
2086 $new_path = apply_filters( 'woocommerce_maxmind_geolocation_database_path', $new_path );
2087
2088 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
2089 @rename( $old_path, $new_path );
2090 }
2091
2092 /**
2093 * So that we can best meet MaxMind's TOS, the geolocation database update cron should run once per 15 days.
2094 */
2095 function wc_update_390_change_geolocation_database_update_cron() {
2096 wp_clear_scheduled_hook( 'woocommerce_geoip_updater' );
2097 wp_schedule_event( time() + ( DAY_IN_SECONDS * 15 ), 'fifteendays', 'woocommerce_geoip_updater' );
2098 }
2099
2100 /**
2101 * Update DB version.
2102 */
2103 function wc_update_390_db_version() {
2104 WC_Install::update_db_version( '3.9.0' );
2105 }
2106
2107 /**
2108 * Increase column size
2109 */
2110 function wc_update_400_increase_size_of_column() {
2111 global $wpdb;
2112 $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_product_meta_lookup MODIFY COLUMN `min_price` decimal(19,4) NULL default NULL" );
2113 $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_product_meta_lookup MODIFY COLUMN `max_price` decimal(19,4) NULL default NULL" );
2114 }
2115
2116 /**
2117 * Reset ActionScheduler migration status. Needs AS >= 3.0 shipped with WC >= 4.0.
2118 */
2119 function wc_update_400_reset_action_scheduler_migration_status() {
2120 if (
2121 class_exists( 'ActionScheduler_DataController' ) &&
2122 method_exists( 'ActionScheduler_DataController', 'mark_migration_incomplete' )
2123 ) {
2124 \ActionScheduler_DataController::mark_migration_incomplete();
2125 }
2126 }
2127
2128 /**
2129 * Update DB version.
2130 */
2131 function wc_update_400_db_version() {
2132 WC_Install::update_db_version( '4.0.0' );
2133 }
2134
2135 /**
2136 * Register attributes as terms for variable products, in increments of 100 products.
2137 *
2138 * This migration was added to support a new mechanism to improve the filtering of
2139 * variable products by attribute (https://github.com/woocommerce/woocommerce/pull/26260),
2140 * however that mechanism was later reverted (https://github.com/woocommerce/woocommerce/pull/27625)
2141 * due to numerous issues found. Thus the migration is no longer needed.
2142 *
2143 * @return bool true if the migration needs to be run again.
2144 */
2145 function wc_update_440_insert_attribute_terms_for_variable_products() {
2146 return false;
2147 }
2148
2149 /**
2150 * Update DB version.
2151 */
2152 function wc_update_440_db_version() {
2153 WC_Install::update_db_version( '4.4.0' );
2154 }
2155
2156 /**
2157 * Update DB version to 4.5.0.
2158 */
2159 function wc_update_450_db_version() {
2160 WC_Install::update_db_version( '4.5.0' );
2161 }
2162
2163 /**
2164 * Sanitize all coupons code.
2165 *
2166 * @return bool True to run again, false if completed.
2167 */
2168 function wc_update_450_sanitize_coupons_code() {
2169 global $wpdb;
2170
2171 $coupon_id = 0;
2172 $last_coupon_id = get_option( 'woocommerce_update_450_last_coupon_id', '0' );
2173
2174 $coupons = $wpdb->get_results(
2175 $wpdb->prepare(
2176 "SELECT ID, post_title FROM $wpdb->posts WHERE ID > %d AND post_type = 'shop_coupon' LIMIT 10",
2177 $last_coupon_id
2178 ),
2179 ARRAY_A
2180 );
2181
2182 if ( empty( $coupons ) ) {
2183 delete_option( 'woocommerce_update_450_last_coupon_id' );
2184 return false;
2185 }
2186
2187 foreach ( $coupons as $key => $data ) {
2188 $coupon_id = intval( $data['ID'] );
2189 $code = trim( wp_filter_kses( $data['post_title'] ) );
2190
2191 if ( ! empty( $code ) && $data['post_title'] !== $code ) {
2192 $wpdb->update(
2193 $wpdb->posts,
2194 array(
2195 'post_title' => $code,
2196 ),
2197 array(
2198 'ID' => $coupon_id,
2199 ),
2200 array(
2201 '%s',
2202 ),
2203 array(
2204 '%d',
2205 )
2206 );
2207
2208 // Clean cache.
2209 clean_post_cache( $coupon_id );
2210 wp_cache_delete( WC_Cache_Helper::get_cache_prefix( 'coupons' ) . 'coupon_id_from_code_' . $data['post_title'], 'coupons' );
2211 }
2212 }
2213
2214 // Start the run again.
2215 if ( $coupon_id ) {
2216 return update_option( 'woocommerce_update_450_last_coupon_id', $coupon_id );
2217 }
2218
2219 delete_option( 'woocommerce_update_450_last_coupon_id' );
2220 return false;
2221 }
2222
2223 /**
2224 * Fixes product review count that might have been incorrect.
2225 *
2226 * See @link https://github.com/woocommerce/woocommerce/issues/27688.
2227 */
2228 function wc_update_500_fix_product_review_count() {
2229 global $wpdb;
2230
2231 $product_id = 0;
2232 $last_product_id = get_option( 'woocommerce_update_500_last_product_id', '0' );
2233
2234 $products_data = $wpdb->get_results(
2235 $wpdb->prepare(
2236 "
2237 SELECT post_id, meta_value
2238 FROM $wpdb->postmeta
2239 JOIN $wpdb->posts
2240 ON $wpdb->postmeta.post_id = $wpdb->posts.ID
2241 WHERE
2242 post_type = 'product'
2243 AND post_status = 'publish'
2244 AND post_id > %d
2245 AND meta_key = '_wc_review_count'
2246 ORDER BY post_id ASC
2247 LIMIT 10
2248 ",
2249 $last_product_id
2250 ),
2251 ARRAY_A
2252 );
2253
2254 if ( empty( $products_data ) ) {
2255 delete_option( 'woocommerce_update_500_last_product_id' );
2256 return false;
2257 }
2258
2259 $product_ids_to_check = array_column( $products_data, 'post_id' );
2260 $actual_review_counts = WC_Comments::get_review_counts_for_product_ids( $product_ids_to_check );
2261
2262 foreach ( $products_data as $product_data ) {
2263 $product_id = intval( $product_data['post_id'] );
2264 $current_review_count = intval( $product_data['meta_value'] );
2265
2266 if ( intval( $actual_review_counts[ $product_id ] ) !== $current_review_count ) {
2267 WC_Comments::clear_transients( $product_id );
2268 }
2269 }
2270
2271 // Start the run again.
2272 if ( $product_id ) {
2273 return update_option( 'woocommerce_update_500_last_product_id', $product_id );
2274 }
2275
2276 delete_option( 'woocommerce_update_500_last_product_id' );
2277 return false;
2278 }
2279
2280 /**
2281 * Update DB version to 5.0.0.
2282 */
2283 function wc_update_500_db_version() {
2284 WC_Install::update_db_version( '5.0.0' );
2285 }
2286