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