PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 7.4.0-rc.2
WooCommerce v7.4.0-rc.2
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 / class-wc-install.php
woocommerce / includes Last commit date
abstracts 3 years ago admin 3 years ago blocks 5 years ago cli 3 years ago customizer 3 years ago data-stores 3 years ago emails 3 years ago export 3 years ago gateways 3 years ago import 3 years ago integrations 4 years ago interfaces 3 years ago legacy 3 years ago libraries 3 years ago log-handlers 4 years ago payment-tokens 5 years ago queue 4 years ago react-admin 3 years ago rest-api 3 years ago shipping 4 years ago shortcodes 3 years ago theme-support 3 years ago tracks 3 years ago traits 5 years ago walkers 5 years ago wccom-site 5 years ago widgets 4 years ago class-wc-ajax.php 3 years ago class-wc-api.php 4 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 3 years ago class-wc-cart-totals.php 4 years ago class-wc-cart.php 3 years ago class-wc-checkout.php 3 years ago class-wc-cli.php 3 years ago class-wc-comments.php 3 years ago class-wc-countries.php 3 years ago class-wc-coupon.php 4 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 3 years ago class-wc-datetime.php 4 years ago class-wc-deprecated-action-hooks.php 8 years ago class-wc-deprecated-filter-hooks.php 4 years ago class-wc-discounts.php 3 years ago class-wc-download-handler.php 3 years ago class-wc-emails.php 3 years ago class-wc-embed.php 5 years ago class-wc-form-handler.php 4 years ago class-wc-frontend-scripts.php 3 years ago class-wc-geo-ip.php 4 years ago class-wc-geolite-integration.php 6 years ago class-wc-geolocation.php 3 years ago class-wc-https.php 4 years ago class-wc-install.php 3 years ago class-wc-integrations.php 5 years ago class-wc-log-levels.php 5 years ago class-wc-logger.php 4 years ago class-wc-meta-data.php 4 years ago class-wc-order-factory.php 3 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 3 years ago class-wc-order.php 3 years ago class-wc-payment-gateways.php 4 years ago class-wc-payment-tokens.php 3 years ago class-wc-post-data.php 3 years ago class-wc-post-types.php 3 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 3 years ago class-wc-product-variable.php 4 years ago class-wc-product-variation.php 4 years ago class-wc-query.php 3 years ago class-wc-rate-limiter.php 4 years ago class-wc-regenerate-images-request.php 3 years ago class-wc-regenerate-images.php 3 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 3 years ago class-wc-shipping-rate.php 3 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 4 years ago class-wc-template-loader.php 3 years ago class-wc-tracker.php 3 years ago class-wc-validation.php 3 years ago class-wc-webhook.php 3 years ago class-woocommerce.php 3 years ago wc-account-functions.php 3 years ago wc-attribute-functions.php 3 years ago wc-cart-functions.php 3 years ago wc-conditional-functions.php 3 years ago wc-core-functions.php 3 years ago wc-coupon-functions.php 5 years ago wc-deprecated-functions.php 3 years ago wc-formatting-functions.php 3 years ago wc-notice-functions.php 5 years ago wc-order-functions.php 3 years ago wc-order-item-functions.php 3 years ago wc-page-functions.php 5 years ago wc-product-functions.php 3 years ago wc-rest-functions.php 3 years ago wc-stock-functions.php 4 years ago wc-template-functions.php 3 years ago wc-template-hooks.php 5 years ago wc-term-functions.php 3 years ago wc-update-functions.php 3 years ago wc-user-functions.php 3 years ago wc-webhook-functions.php 4 years ago wc-widget-functions.php 5 years ago
class-wc-install.php
2289 lines
1 <?php
2 /**
3 * Installation related functions and actions.
4 *
5 * @package WooCommerce\Classes
6 * @version 3.0.0
7 */
8
9 use Automattic\Jetpack\Constants;
10 use Automattic\WooCommerce\Admin\Notes\Notes;
11 use Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator;
12 use Automattic\WooCommerce\Internal\ProductDownloads\ApprovedDirectories\Register as Download_Directories;
13 use Automattic\WooCommerce\Internal\ProductDownloads\ApprovedDirectories\Synchronize as Download_Directories_Sync;
14 use Automattic\WooCommerce\Internal\Utilities\DatabaseUtil;
15 use Automattic\WooCommerce\Internal\WCCom\ConnectionHelper as WCConnectionHelper;
16
17 defined( 'ABSPATH' ) || exit;
18
19 /**
20 * WC_Install Class.
21 */
22 class WC_Install {
23
24 /**
25 * DB updates and callbacks that need to be run per version.
26 *
27 * Please note that these functions are invoked when WooCommerce is updated from a previous version,
28 * but NOT when WooCommerce is newly installed.
29 *
30 * Database schema changes must be incorporated to the SQL returned by get_schema, which is applied
31 * via dbDelta at both install and update time. If any other kind of database change is required
32 * at install time (e.g. populating tables), use the 'woocommerce_installed' hook.
33 *
34 * @var array
35 */
36 private static $db_updates = array(
37 '2.0.0' => array(
38 'wc_update_200_file_paths',
39 'wc_update_200_permalinks',
40 'wc_update_200_subcat_display',
41 'wc_update_200_taxrates',
42 'wc_update_200_line_items',
43 'wc_update_200_images',
44 'wc_update_200_db_version',
45 ),
46 '2.0.9' => array(
47 'wc_update_209_brazillian_state',
48 'wc_update_209_db_version',
49 ),
50 '2.1.0' => array(
51 'wc_update_210_remove_pages',
52 'wc_update_210_file_paths',
53 'wc_update_210_db_version',
54 ),
55 '2.2.0' => array(
56 'wc_update_220_shipping',
57 'wc_update_220_order_status',
58 'wc_update_220_variations',
59 'wc_update_220_attributes',
60 'wc_update_220_db_version',
61 ),
62 '2.3.0' => array(
63 'wc_update_230_options',
64 'wc_update_230_db_version',
65 ),
66 '2.4.0' => array(
67 'wc_update_240_options',
68 'wc_update_240_shipping_methods',
69 'wc_update_240_api_keys',
70 'wc_update_240_refunds',
71 'wc_update_240_db_version',
72 ),
73 '2.4.1' => array(
74 'wc_update_241_variations',
75 'wc_update_241_db_version',
76 ),
77 '2.5.0' => array(
78 'wc_update_250_currency',
79 'wc_update_250_db_version',
80 ),
81 '2.6.0' => array(
82 'wc_update_260_options',
83 'wc_update_260_termmeta',
84 'wc_update_260_zones',
85 'wc_update_260_zone_methods',
86 'wc_update_260_refunds',
87 'wc_update_260_db_version',
88 ),
89 '3.0.0' => array(
90 'wc_update_300_grouped_products',
91 'wc_update_300_settings',
92 'wc_update_300_product_visibility',
93 'wc_update_300_db_version',
94 ),
95 '3.1.0' => array(
96 'wc_update_310_downloadable_products',
97 'wc_update_310_old_comments',
98 'wc_update_310_db_version',
99 ),
100 '3.1.2' => array(
101 'wc_update_312_shop_manager_capabilities',
102 'wc_update_312_db_version',
103 ),
104 '3.2.0' => array(
105 'wc_update_320_mexican_states',
106 'wc_update_320_db_version',
107 ),
108 '3.3.0' => array(
109 'wc_update_330_image_options',
110 'wc_update_330_webhooks',
111 'wc_update_330_product_stock_status',
112 'wc_update_330_set_default_product_cat',
113 'wc_update_330_clear_transients',
114 'wc_update_330_set_paypal_sandbox_credentials',
115 'wc_update_330_db_version',
116 ),
117 '3.4.0' => array(
118 'wc_update_340_states',
119 'wc_update_340_state',
120 'wc_update_340_last_active',
121 'wc_update_340_db_version',
122 ),
123 '3.4.3' => array(
124 'wc_update_343_cleanup_foreign_keys',
125 'wc_update_343_db_version',
126 ),
127 '3.4.4' => array(
128 'wc_update_344_recreate_roles',
129 'wc_update_344_db_version',
130 ),
131 '3.5.0' => array(
132 'wc_update_350_reviews_comment_type',
133 'wc_update_350_db_version',
134 ),
135 '3.5.2' => array(
136 'wc_update_352_drop_download_log_fk',
137 ),
138 '3.5.4' => array(
139 'wc_update_354_modify_shop_manager_caps',
140 'wc_update_354_db_version',
141 ),
142 '3.6.0' => array(
143 'wc_update_360_product_lookup_tables',
144 'wc_update_360_term_meta',
145 'wc_update_360_downloadable_product_permissions_index',
146 'wc_update_360_db_version',
147 ),
148 '3.7.0' => array(
149 'wc_update_370_tax_rate_classes',
150 'wc_update_370_mro_std_currency',
151 'wc_update_370_db_version',
152 ),
153 '3.9.0' => array(
154 'wc_update_390_move_maxmind_database',
155 'wc_update_390_change_geolocation_database_update_cron',
156 'wc_update_390_db_version',
157 ),
158 '4.0.0' => array(
159 'wc_update_product_lookup_tables',
160 'wc_update_400_increase_size_of_column',
161 'wc_update_400_reset_action_scheduler_migration_status',
162 'wc_admin_update_0201_order_status_index',
163 'wc_admin_update_0230_rename_gross_total',
164 'wc_admin_update_0251_remove_unsnooze_action',
165 'wc_update_400_db_version',
166 ),
167 '4.4.0' => array(
168 'wc_update_440_insert_attribute_terms_for_variable_products',
169 'wc_admin_update_110_remove_facebook_note',
170 'wc_admin_update_130_remove_dismiss_action_from_tracking_opt_in_note',
171 'wc_update_440_db_version',
172 ),
173 '4.5.0' => array(
174 'wc_update_450_sanitize_coupons_code',
175 'wc_update_450_db_version',
176 ),
177 '5.0.0' => array(
178 'wc_update_500_fix_product_review_count',
179 'wc_admin_update_160_remove_facebook_note',
180 'wc_admin_update_170_homescreen_layout',
181 'wc_update_500_db_version',
182 ),
183 '5.6.0' => array(
184 'wc_update_560_create_refund_returns_page',
185 'wc_update_560_db_version',
186 ),
187 '6.0.0' => array(
188 'wc_update_600_migrate_rate_limit_options',
189 'wc_admin_update_270_delete_report_downloads',
190 'wc_admin_update_271_update_task_list_options',
191 'wc_admin_update_280_order_status',
192 'wc_admin_update_290_update_apperance_task_option',
193 'wc_admin_update_290_delete_default_homepage_layout_option',
194 'wc_update_600_db_version',
195 ),
196 '6.3.0' => array(
197 'wc_update_630_create_product_attributes_lookup_table',
198 'wc_admin_update_300_update_is_read_from_last_read',
199 'wc_update_630_db_version',
200 ),
201 '6.4.0' => array(
202 'wc_update_640_add_primary_key_to_product_attributes_lookup_table',
203 'wc_admin_update_340_remove_is_primary_from_note_action',
204 'wc_update_640_db_version',
205 ),
206 '6.5.0' => array(
207 'wc_update_650_approved_download_directories',
208 ),
209 '6.5.1' => array(
210 'wc_update_651_approved_download_directories',
211 ),
212 '6.7.0' => array(
213 'wc_update_670_purge_comments_count_cache',
214 'wc_update_670_delete_deprecated_remote_inbox_notifications_option',
215 ),
216 '7.0.0' => array(
217 'wc_update_700_remove_download_log_fk',
218 'wc_update_700_remove_recommended_marketing_plugins_transient',
219 ),
220 '7.2.1' => array(
221 'wc_update_721_adjust_new_zealand_states',
222 'wc_update_721_adjust_ukraine_states',
223 ),
224 '7.2.2' => array(
225 'wc_update_722_adjust_new_zealand_states',
226 'wc_update_722_adjust_ukraine_states',
227 ),
228 );
229
230 /**
231 * Hook in tabs.
232 */
233 public static function init() {
234 add_action( 'init', array( __CLASS__, 'check_version' ), 5 );
235 add_action( 'init', array( __CLASS__, 'manual_database_update' ), 20 );
236 add_action( 'admin_init', array( __CLASS__, 'wc_admin_db_update_notice' ) );
237 add_action( 'admin_init', array( __CLASS__, 'add_admin_note_after_page_created' ) );
238 add_action( 'woocommerce_run_update_callback', array( __CLASS__, 'run_update_callback' ) );
239 add_action( 'woocommerce_update_db_to_current_version', array( __CLASS__, 'update_db_version' ) );
240 add_action( 'admin_init', array( __CLASS__, 'install_actions' ) );
241 add_action( 'woocommerce_page_created', array( __CLASS__, 'page_created' ), 10, 2 );
242 add_filter( 'plugin_action_links_' . WC_PLUGIN_BASENAME, array( __CLASS__, 'plugin_action_links' ) );
243 add_filter( 'plugin_row_meta', array( __CLASS__, 'plugin_row_meta' ), 10, 2 );
244 add_filter( 'wpmu_drop_tables', array( __CLASS__, 'wpmu_drop_tables' ) );
245 add_filter( 'cron_schedules', array( __CLASS__, 'cron_schedules' ) );
246 }
247
248 /**
249 * Check WooCommerce version and run the updater is required.
250 *
251 * This check is done on all requests and runs if the versions do not match.
252 */
253 public static function check_version() {
254 $wc_version = get_option( 'woocommerce_version' );
255 $wc_code_version = WC()->version;
256 $requires_update = version_compare( $wc_version, $wc_code_version, '<' );
257 if ( ! Constants::is_defined( 'IFRAME_REQUEST' ) && $requires_update ) {
258 self::install();
259 /**
260 * Run after WooCommerce has been updated.
261 *
262 * @since 2.2.0
263 */
264 do_action( 'woocommerce_updated' );
265 do_action_deprecated( 'woocommerce_admin_updated', array(), $wc_code_version, 'woocommerce_updated' );
266 // If there is no woocommerce_version option, consider it as a new install.
267 if ( ! $wc_version ) {
268 /**
269 * Run when WooCommerce has been installed for the first time.
270 *
271 * @since 6.5.0
272 */
273 do_action( 'woocommerce_newly_installed' );
274 do_action_deprecated( 'woocommerce_admin_newly_installed', array(), $wc_code_version, 'woocommerce_newly_installed' );
275 }
276 }
277 }
278
279 /**
280 * Performan manual database update when triggered by WooCommerce System Tools.
281 *
282 * @since 3.6.5
283 */
284 public static function manual_database_update() {
285 $blog_id = get_current_blog_id();
286
287 add_action( 'wp_' . $blog_id . '_wc_updater_cron', array( __CLASS__, 'run_manual_database_update' ) );
288 }
289
290 /**
291 * Add WC Admin based db update notice.
292 *
293 * @since 4.0.0
294 */
295 public static function wc_admin_db_update_notice() {
296 if (
297 WC()->is_wc_admin_active() &&
298 false !== get_option( 'woocommerce_admin_install_timestamp' )
299 ) {
300 new WC_Notes_Run_Db_Update();
301 }
302 }
303
304 /**
305 * Run manual database update.
306 */
307 public static function run_manual_database_update() {
308 self::update();
309 }
310
311 /**
312 * Run an update callback when triggered by ActionScheduler.
313 *
314 * @param string $update_callback Callback name.
315 *
316 * @since 3.6.0
317 */
318 public static function run_update_callback( $update_callback ) {
319 include_once dirname( __FILE__ ) . '/wc-update-functions.php';
320
321 if ( is_callable( $update_callback ) ) {
322 self::run_update_callback_start( $update_callback );
323 $result = (bool) call_user_func( $update_callback );
324 self::run_update_callback_end( $update_callback, $result );
325 }
326 }
327
328 /**
329 * Triggered when a callback will run.
330 *
331 * @since 3.6.0
332 * @param string $callback Callback name.
333 */
334 protected static function run_update_callback_start( $callback ) {
335 wc_maybe_define_constant( 'WC_UPDATING', true );
336 }
337
338 /**
339 * Triggered when a callback has ran.
340 *
341 * @since 3.6.0
342 * @param string $callback Callback name.
343 * @param bool $result Return value from callback. Non-false need to run again.
344 */
345 protected static function run_update_callback_end( $callback, $result ) {
346 if ( $result ) {
347 WC()->queue()->add(
348 'woocommerce_run_update_callback',
349 array(
350 'update_callback' => $callback,
351 ),
352 'woocommerce-db-updates'
353 );
354 }
355 }
356
357 /**
358 * Install actions when a update button is clicked within the admin area.
359 *
360 * This function is hooked into admin_init to affect admin only.
361 */
362 public static function install_actions() {
363 if ( ! empty( $_GET['do_update_woocommerce'] ) ) { // WPCS: input var ok.
364 check_admin_referer( 'wc_db_update', 'wc_db_update_nonce' );
365 self::update();
366 WC_Admin_Notices::add_notice( 'update', true );
367 }
368 }
369
370 /**
371 * Install WC.
372 */
373 public static function install() {
374 if ( ! is_blog_installed() ) {
375 return;
376 }
377
378 // Check if we are not already running this routine.
379 if ( self::is_installing() ) {
380 return;
381 }
382
383 // If we made it till here nothing is running yet, lets set the transient now.
384 set_transient( 'wc_installing', 'yes', MINUTE_IN_SECONDS * 10 );
385 wc_maybe_define_constant( 'WC_INSTALLING', true );
386
387 WC()->wpdb_table_fix();
388 self::remove_admin_notices();
389 self::create_tables();
390 self::verify_base_tables();
391 self::create_options();
392 self::migrate_options();
393 self::create_roles();
394 self::setup_environment();
395 self::create_terms();
396 self::create_cron_jobs();
397 self::delete_obsolete_notes();
398 self::create_files();
399 self::maybe_create_pages();
400 self::maybe_set_activation_transients();
401 self::set_paypal_standard_load_eligibility();
402 self::update_wc_version();
403 self::maybe_update_db_version();
404
405 delete_transient( 'wc_installing' );
406
407 // Use add_option() here to avoid overwriting this value with each
408 // plugin version update. We base plugin age off of this value.
409 add_option( 'woocommerce_admin_install_timestamp', time() );
410
411 /**
412 * Flush the rewrite rules after install or update.
413 *
414 * @since 2.7.0
415 */
416 do_action( 'woocommerce_flush_rewrite_rules' );
417 /**
418 * Run after WooCommerce has been installed or updated.
419 *
420 * @since 3.2.0
421 */
422 do_action( 'woocommerce_installed' );
423 /**
424 * Run after WooCommerce Admin has been installed or updated.
425 *
426 * @since 6.5.0
427 */
428 do_action( 'woocommerce_admin_installed' );
429 }
430
431 /**
432 * Returns true if we're installing.
433 *
434 * @return bool
435 */
436 private static function is_installing() {
437 return 'yes' === get_transient( 'wc_installing' );
438 }
439
440 /**
441 * Check if all the base tables are present.
442 *
443 * @param bool $modify_notice Whether to modify notice based on if all tables are present.
444 * @param bool $execute Whether to execute get_schema queries as well.
445 *
446 * @return array List of queries.
447 */
448 public static function verify_base_tables( $modify_notice = true, $execute = false ) {
449 if ( $execute ) {
450 self::create_tables();
451 }
452
453 $missing_tables = wc_get_container()
454 ->get( DatabaseUtil::class )
455 ->get_missing_tables( self::get_schema() );
456
457 if ( 0 < count( $missing_tables ) ) {
458 if ( $modify_notice ) {
459 WC_Admin_Notices::add_notice( 'base_tables_missing' );
460 }
461 update_option( 'woocommerce_schema_missing_tables', $missing_tables );
462 } else {
463 if ( $modify_notice ) {
464 WC_Admin_Notices::remove_notice( 'base_tables_missing' );
465 }
466 update_option( 'woocommerce_schema_version', WC()->db_version );
467 delete_option( 'woocommerce_schema_missing_tables' );
468 }
469 return $missing_tables;
470 }
471
472 /**
473 * Reset any notices added to admin.
474 *
475 * @since 3.2.0
476 */
477 private static function remove_admin_notices() {
478 include_once dirname( __FILE__ ) . '/admin/class-wc-admin-notices.php';
479 WC_Admin_Notices::remove_all_notices();
480 }
481
482 /**
483 * Setup WC environment - post types, taxonomies, endpoints.
484 *
485 * @since 3.2.0
486 */
487 private static function setup_environment() {
488 WC_Post_types::register_post_types();
489 WC_Post_types::register_taxonomies();
490 WC()->query->init_query_vars();
491 WC()->query->add_endpoints();
492 WC_API::add_endpoint();
493 WC_Auth::add_endpoint();
494 }
495
496 /**
497 * Is this a brand new WC install?
498 *
499 * A brand new install has no version yet. Also treat empty installs as 'new'.
500 *
501 * @since 3.2.0
502 * @return boolean
503 */
504 public static function is_new_install() {
505 $product_count = array_sum( (array) wp_count_posts( 'product' ) );
506
507 return is_null( get_option( 'woocommerce_version', null ) ) || ( 0 === $product_count && -1 === wc_get_page_id( 'shop' ) );
508 }
509
510 /**
511 * Is a DB update needed?
512 *
513 * @since 3.2.0
514 * @return boolean
515 */
516 public static function needs_db_update() {
517 $current_db_version = get_option( 'woocommerce_db_version', null );
518 $updates = self::get_db_update_callbacks();
519 $update_versions = array_keys( $updates );
520 usort( $update_versions, 'version_compare' );
521
522 return ! is_null( $current_db_version ) && version_compare( $current_db_version, end( $update_versions ), '<' );
523 }
524
525 /**
526 * See if we need to set redirect transients for activation or not.
527 *
528 * @since 4.6.0
529 */
530 private static function maybe_set_activation_transients() {
531 if ( self::is_new_install() ) {
532 set_transient( '_wc_activation_redirect', 1, 30 );
533 }
534 }
535
536 /**
537 * See if we need to show or run database updates during install.
538 *
539 * @since 3.2.0
540 */
541 private static function maybe_update_db_version() {
542 if ( self::needs_db_update() ) {
543 /**
544 * Allow WooCommerce to auto-update without prompting the user.
545 *
546 * @since 3.2.0
547 */
548 if ( apply_filters( 'woocommerce_enable_auto_update_db', false ) ) {
549 self::update();
550 } else {
551 WC_Admin_Notices::add_notice( 'update', true );
552 }
553 } else {
554 self::update_db_version();
555 }
556 }
557
558 /**
559 * Update WC version to current.
560 */
561 private static function update_wc_version() {
562 update_option( 'woocommerce_version', WC()->version );
563 }
564
565 /**
566 * Get list of DB update callbacks.
567 *
568 * @since 3.0.0
569 * @return array
570 */
571 public static function get_db_update_callbacks() {
572 return self::$db_updates;
573 }
574
575 /**
576 * Push all needed DB updates to the queue for processing.
577 */
578 private static function update() {
579 $current_db_version = get_option( 'woocommerce_db_version' );
580 $loop = 0;
581
582 foreach ( self::get_db_update_callbacks() as $version => $update_callbacks ) {
583 if ( version_compare( $current_db_version, $version, '<' ) ) {
584 foreach ( $update_callbacks as $update_callback ) {
585 WC()->queue()->schedule_single(
586 time() + $loop,
587 'woocommerce_run_update_callback',
588 array(
589 'update_callback' => $update_callback,
590 ),
591 'woocommerce-db-updates'
592 );
593 $loop++;
594 }
595 }
596 }
597
598 // After the callbacks finish, update the db version to the current WC version.
599 $current_wc_version = WC()->version;
600 if ( version_compare( $current_db_version, $current_wc_version, '<' ) &&
601 ! WC()->queue()->get_next( 'woocommerce_update_db_to_current_version' ) ) {
602 WC()->queue()->schedule_single(
603 time() + $loop,
604 'woocommerce_update_db_to_current_version',
605 array(
606 'version' => $current_wc_version,
607 ),
608 'woocommerce-db-updates'
609 );
610 }
611 }
612
613 /**
614 * Update DB version to current.
615 *
616 * @param string|null $version New WooCommerce DB version or null.
617 */
618 public static function update_db_version( $version = null ) {
619 update_option( 'woocommerce_db_version', is_null( $version ) ? WC()->version : $version );
620 }
621
622 /**
623 * Add more cron schedules.
624 *
625 * @param array $schedules List of WP scheduled cron jobs.
626 *
627 * @return array
628 */
629 public static function cron_schedules( $schedules ) {
630 $schedules['monthly'] = array(
631 'interval' => 2635200,
632 'display' => __( 'Monthly', 'woocommerce' ),
633 );
634 $schedules['fifteendays'] = array(
635 'interval' => 1296000,
636 'display' => __( 'Every 15 Days', 'woocommerce' ),
637 );
638 return $schedules;
639 }
640
641 /**
642 * Create cron jobs (clear them first).
643 */
644 private static function create_cron_jobs() {
645 wp_clear_scheduled_hook( 'woocommerce_scheduled_sales' );
646 wp_clear_scheduled_hook( 'woocommerce_cancel_unpaid_orders' );
647 wp_clear_scheduled_hook( 'woocommerce_cleanup_sessions' );
648 wp_clear_scheduled_hook( 'woocommerce_cleanup_personal_data' );
649 wp_clear_scheduled_hook( 'woocommerce_cleanup_logs' );
650 wp_clear_scheduled_hook( 'woocommerce_geoip_updater' );
651 wp_clear_scheduled_hook( 'woocommerce_tracker_send_event' );
652 wp_clear_scheduled_hook( 'woocommerce_cleanup_rate_limits' );
653
654 $ve = get_option( 'gmt_offset' ) > 0 ? '-' : '+';
655
656 wp_schedule_event( strtotime( '00:00 tomorrow ' . $ve . absint( get_option( 'gmt_offset' ) ) . ' HOURS' ), 'daily', 'woocommerce_scheduled_sales' );
657
658 $held_duration = get_option( 'woocommerce_hold_stock_minutes', '60' );
659
660 if ( '' !== $held_duration ) {
661 /**
662 * Determines the interval at which to cancel unpaid orders in minutes.
663 *
664 * @since 5.1.0
665 */
666 $cancel_unpaid_interval = apply_filters( 'woocommerce_cancel_unpaid_orders_interval_minutes', absint( $held_duration ) );
667 wp_schedule_single_event( time() + ( absint( $cancel_unpaid_interval ) * 60 ), 'woocommerce_cancel_unpaid_orders' );
668 }
669
670 // Delay the first run of `woocommerce_cleanup_personal_data` by 10 seconds
671 // so it doesn't occur in the same request. WooCommerce Admin also schedules
672 // a daily cron that gets lost due to a race condition. WC_Privacy's background
673 // processing instance updates the cron schedule from within a cron job.
674 wp_schedule_event( time() + 10, 'daily', 'woocommerce_cleanup_personal_data' );
675 wp_schedule_event( time() + ( 3 * HOUR_IN_SECONDS ), 'daily', 'woocommerce_cleanup_logs' );
676 wp_schedule_event( time() + ( 6 * HOUR_IN_SECONDS ), 'twicedaily', 'woocommerce_cleanup_sessions' );
677 wp_schedule_event( time() + MINUTE_IN_SECONDS, 'fifteendays', 'woocommerce_geoip_updater' );
678 /**
679 * How frequent to schedule the tracker send event.
680 *
681 * @since 2.3.0
682 */
683 wp_schedule_event( time() + 10, apply_filters( 'woocommerce_tracker_event_recurrence', 'daily' ), 'woocommerce_tracker_send_event' );
684 wp_schedule_event( time() + ( 3 * HOUR_IN_SECONDS ), 'daily', 'woocommerce_cleanup_rate_limits' );
685
686 if ( ! wp_next_scheduled( 'wc_admin_daily' ) ) {
687 wp_schedule_event( time(), 'daily', 'wc_admin_daily' );
688 }
689 // Note: this is potentially redundant when the core package exists.
690 wp_schedule_single_event( time() + 10, 'generate_category_lookup_table' );
691 }
692
693 /**
694 * Create pages on installation.
695 */
696 public static function maybe_create_pages() {
697 if ( empty( get_option( 'woocommerce_db_version' ) ) ) {
698 self::create_pages();
699 }
700 }
701
702 /**
703 * Create pages that the plugin relies on, storing page IDs in variables.
704 */
705 public static function create_pages() {
706 include_once dirname( __FILE__ ) . '/admin/wc-admin-functions.php';
707
708 /**
709 * Determines the cart shortcode tag used for the cart page.
710 *
711 * @since 2.1.0
712 */
713 $cart_shortcode = apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' );
714
715 /**
716 * Determines the checkout shortcode tag used on the checkout page.
717 *
718 * @since 2.1.0
719 */
720 $checkout_shortcode = apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' );
721
722 /**
723 * Determines the my account shortcode tag used on the my account page.
724 *
725 * @since 2.1.0
726 */
727 $my_account_shortcode = apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' );
728
729 /**
730 * Determines which pages are created during install.
731 *
732 * @since 2.1.0
733 */
734 $pages = apply_filters(
735 'woocommerce_create_pages',
736 array(
737 'shop' => array(
738 'name' => _x( 'shop', 'Page slug', 'woocommerce' ),
739 'title' => _x( 'Shop', 'Page title', 'woocommerce' ),
740 'content' => '',
741 ),
742 'cart' => array(
743 'name' => _x( 'cart', 'Page slug', 'woocommerce' ),
744 'title' => _x( 'Cart', 'Page title', 'woocommerce' ),
745 'content' => '<!-- wp:shortcode -->[' . $cart_shortcode . ']<!-- /wp:shortcode -->',
746 ),
747 'checkout' => array(
748 'name' => _x( 'checkout', 'Page slug', 'woocommerce' ),
749 'title' => _x( 'Checkout', 'Page title', 'woocommerce' ),
750 'content' => '<!-- wp:shortcode -->[' . $checkout_shortcode . ']<!-- /wp:shortcode -->',
751 ),
752 'myaccount' => array(
753 'name' => _x( 'my-account', 'Page slug', 'woocommerce' ),
754 'title' => _x( 'My account', 'Page title', 'woocommerce' ),
755 'content' => '<!-- wp:shortcode -->[' . $my_account_shortcode . ']<!-- /wp:shortcode -->',
756 ),
757 'refund_returns' => array(
758 'name' => _x( 'refund_returns', 'Page slug', 'woocommerce' ),
759 'title' => _x( 'Refund and Returns Policy', 'Page title', 'woocommerce' ),
760 'content' => self::get_refunds_return_policy_page_content(),
761 'post_status' => 'draft',
762 ),
763 )
764 );
765
766 foreach ( $pages as $key => $page ) {
767 wc_create_page(
768 esc_sql( $page['name'] ),
769 'woocommerce_' . $key . '_page_id',
770 $page['title'],
771 $page['content'],
772 ! empty( $page['parent'] ) ? wc_get_page_id( $page['parent'] ) : '',
773 ! empty( $page['post_status'] ) ? $page['post_status'] : 'publish'
774 );
775 }
776 }
777
778 /**
779 * Default options.
780 *
781 * Sets up the default options used on the settings page.
782 */
783 private static function create_options() {
784 // Include settings so that we can run through defaults.
785 include_once dirname( __FILE__ ) . '/admin/class-wc-admin-settings.php';
786
787 $settings = WC_Admin_Settings::get_settings_pages();
788
789 foreach ( $settings as $section ) {
790 if ( ! is_a( $section, 'WC_Settings_Page' ) || ! method_exists( $section, 'get_settings' ) ) {
791 continue;
792 }
793 $subsections = array_unique( array_merge( array( '' ), array_keys( $section->get_sections() ) ) );
794
795 /**
796 * We are using 'WC_Settings_Page::get_settings' on purpose even thought it's deprecated.
797 * See the method documentation for an explanation.
798 */
799
800 foreach ( $subsections as $subsection ) {
801 foreach ( $section->get_settings( $subsection ) as $value ) {
802 if ( isset( $value['default'] ) && isset( $value['id'] ) ) {
803 $autoload = isset( $value['autoload'] ) ? (bool) $value['autoload'] : true;
804 add_option( $value['id'], $value['default'], '', ( $autoload ? 'yes' : 'no' ) );
805 }
806 }
807 }
808 }
809
810 // Define other defaults if not in setting screens.
811 add_option( 'woocommerce_single_image_width', '600', '', 'yes' );
812 add_option( 'woocommerce_thumbnail_image_width', '300', '', 'yes' );
813 add_option( 'woocommerce_checkout_highlight_required_fields', 'yes', '', 'yes' );
814 add_option( 'woocommerce_demo_store', 'no', '', 'no' );
815
816 if ( self::is_new_install() ) {
817 // Define initial tax classes.
818 WC_Tax::create_tax_class( __( 'Reduced rate', 'woocommerce' ) );
819 WC_Tax::create_tax_class( __( 'Zero rate', 'woocommerce' ) );
820
821 // For new installs, setup and enable Approved Product Download Directories.
822 wc_get_container()->get( Download_Directories_Sync::class )->init_feature( false, true );
823 }
824 }
825
826 /**
827 * Delete obsolete notes.
828 */
829 public static function delete_obsolete_notes() {
830 global $wpdb;
831 $obsolete_notes_names = array(
832 'wc-admin-welcome-note',
833 'wc-admin-insight-first-product-and-payment',
834 'wc-admin-store-notice-setting-moved',
835 'wc-admin-store-notice-giving-feedback',
836 'wc-admin-first-downloadable-product',
837 'wc-admin-learn-more-about-product-settings',
838 'wc-admin-adding-and-managing-products',
839 'wc-admin-onboarding-profiler-reminder',
840 'wc-admin-historical-data',
841 'wc-admin-manage-store-activity-from-home-screen',
842 'wc-admin-review-shipping-settings',
843 'wc-admin-home-screen-feedback',
844 'wc-admin-update-store-details',
845 'wc-admin-effortless-payments-by-mollie',
846 'wc-admin-google-ads-and-marketing',
847 'wc-admin-insight-first-sale',
848 'wc-admin-marketing-intro',
849 'wc-admin-draw-attention',
850 'wc-admin-welcome-to-woocommerce-for-store-users',
851 'wc-admin-need-some-inspiration',
852 'wc-admin-choose-niche',
853 'wc-admin-start-dropshipping-business',
854 'wc-admin-filter-by-product-variations-in-reports',
855 'wc-admin-learn-more-about-variable-products',
856 'wc-admin-getting-started-ecommerce-webinar',
857 'wc-admin-navigation-feedback',
858 'wc-admin-navigation-feedback-follow-up',
859 'wc-admin-set-up-additional-payment-types',
860 'wc-admin-deactivate-plugin',
861 'wc-admin-complete-store-details',
862 );
863
864 /**
865 * An array of deprecated notes to delete on update.
866 *
867 * @since 6.5.0
868 */
869 $additional_obsolete_notes_names = apply_filters(
870 'woocommerce_admin_obsolete_notes_names',
871 array()
872 );
873
874 if ( is_array( $additional_obsolete_notes_names ) ) {
875 $obsolete_notes_names = array_merge(
876 $obsolete_notes_names,
877 $additional_obsolete_notes_names
878 );
879 }
880
881 foreach ( $obsolete_notes_names as $obsolete_notes_name ) {
882 $wpdb->delete( $wpdb->prefix . 'wc_admin_notes', array( 'name' => $obsolete_notes_name ) );
883 $wpdb->delete( $wpdb->prefix . 'wc_admin_note_actions', array( 'name' => $obsolete_notes_name ) );
884 }
885 }
886
887 /**
888 * Migrate option values to their new keys/names.
889 */
890 public static function migrate_options() {
891
892 $migrated_options = array(
893 'woocommerce_onboarding_profile' => 'wc_onboarding_profile',
894 'woocommerce_admin_install_timestamp' => 'wc_admin_install_timestamp',
895 'woocommerce_onboarding_opt_in' => 'wc_onboarding_opt_in',
896 'woocommerce_admin_import_stats' => 'wc_admin_import_stats',
897 'woocommerce_admin_version' => 'wc_admin_version',
898 'woocommerce_admin_last_orders_milestone' => 'wc_admin_last_orders_milestone',
899 'woocommerce_admin-wc-helper-last-refresh' => 'wc-admin-wc-helper-last-refresh',
900 'woocommerce_admin_report_export_status' => 'wc_admin_report_export_status',
901 'woocommerce_task_list_complete' => 'woocommerce_task_list_complete',
902 'woocommerce_task_list_hidden' => 'woocommerce_task_list_hidden',
903 'woocommerce_extended_task_list_complete' => 'woocommerce_extended_task_list_complete',
904 'woocommerce_extended_task_list_hidden' => 'woocommerce_extended_task_list_hidden',
905 );
906
907 wc_maybe_define_constant( 'WC_ADMIN_MIGRATING_OPTIONS', true );
908
909 foreach ( $migrated_options as $new_option => $old_option ) {
910 $old_option_value = get_option( $old_option, false );
911
912 // Continue if no option value was previously set.
913 if ( false === $old_option_value ) {
914 continue;
915 }
916
917 if ( '1' === $old_option_value ) {
918 $old_option_value = 'yes';
919 } elseif ( '0' === $old_option_value ) {
920 $old_option_value = 'no';
921 }
922
923 update_option( $new_option, $old_option_value );
924 if ( $new_option !== $old_option ) {
925 delete_option( $old_option );
926 }
927 }
928 }
929 /**
930 * Add the default terms for WC taxonomies - product types and order statuses. Modify this at your own risk.
931 */
932 public static function create_terms() {
933 $taxonomies = array(
934 'product_type' => array(
935 'simple',
936 'grouped',
937 'variable',
938 'external',
939 ),
940 'product_visibility' => array(
941 'exclude-from-search',
942 'exclude-from-catalog',
943 'featured',
944 'outofstock',
945 'rated-1',
946 'rated-2',
947 'rated-3',
948 'rated-4',
949 'rated-5',
950 ),
951 );
952
953 foreach ( $taxonomies as $taxonomy => $terms ) {
954 foreach ( $terms as $term ) {
955 if ( ! get_term_by( 'name', $term, $taxonomy ) ) { // @codingStandardsIgnoreLine.
956 wp_insert_term( $term, $taxonomy );
957 }
958 }
959 }
960
961 $woocommerce_default_category = (int) get_option( 'default_product_cat', 0 );
962
963 if ( ! $woocommerce_default_category || ! term_exists( $woocommerce_default_category, 'product_cat' ) ) {
964 $default_product_cat_id = 0;
965 $default_product_cat_slug = sanitize_title( _x( 'Uncategorized', 'Default category slug', 'woocommerce' ) );
966 $default_product_cat = get_term_by( 'slug', $default_product_cat_slug, 'product_cat' ); // @codingStandardsIgnoreLine.
967
968 if ( $default_product_cat ) {
969 $default_product_cat_id = absint( $default_product_cat->term_taxonomy_id );
970 } else {
971 $result = wp_insert_term( _x( 'Uncategorized', 'Default category slug', 'woocommerce' ), 'product_cat', array( 'slug' => $default_product_cat_slug ) );
972
973 if ( ! is_wp_error( $result ) && ! empty( $result['term_taxonomy_id'] ) ) {
974 $default_product_cat_id = absint( $result['term_taxonomy_id'] );
975 }
976 }
977
978 if ( $default_product_cat_id ) {
979 update_option( 'default_product_cat', $default_product_cat_id );
980 }
981 }
982 }
983
984 /**
985 * Set up the database tables which the plugin needs to function.
986 * WARNING: If you are modifying this method, make sure that its safe to call regardless of the state of database.
987 *
988 * This is called from `install` method and is executed in-sync when WC is installed or updated. This can also be called optionally from `verify_base_tables`.
989 *
990 * TODO: Add all crucial tables that we have created from workers in the past.
991 *
992 * Tables:
993 * woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined
994 * woocommerce_downloadable_product_permissions - Table for storing user and guest download permissions.
995 * KEY(order_id, product_id, download_id) used for organizing downloads on the My Account page
996 * woocommerce_order_items - Order line items are stored in a table to make them easily queryable for reports
997 * woocommerce_order_itemmeta - Order line item meta is stored in a table for storing extra data.
998 * woocommerce_tax_rates - Tax Rates are stored inside 2 tables making tax queries simple and efficient.
999 * woocommerce_tax_rate_locations - Each rate can be applied to more than one postcode/city hence the second table.
1000 */
1001 public static function create_tables() {
1002 global $wpdb;
1003
1004 $wpdb->hide_errors();
1005
1006 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
1007
1008 /**
1009 * Before updating with DBDELTA, remove any primary keys which could be
1010 * modified due to schema updates.
1011 */
1012 if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}woocommerce_downloadable_product_permissions';" ) ) {
1013 if ( ! $wpdb->get_var( "SHOW COLUMNS FROM `{$wpdb->prefix}woocommerce_downloadable_product_permissions` LIKE 'permission_id';" ) ) {
1014 $wpdb->query( "ALTER TABLE {$wpdb->prefix}woocommerce_downloadable_product_permissions DROP PRIMARY KEY, ADD `permission_id` BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT;" );
1015 }
1016 }
1017
1018 /**
1019 * Change wp_woocommerce_sessions schema to use a bigint auto increment field instead of char(32) field as
1020 * the primary key as it is not a good practice to use a char(32) field as the primary key of a table and as
1021 * there were reports of issues with this table (see https://github.com/woocommerce/woocommerce/issues/20912).
1022 *
1023 * This query needs to run before dbDelta() as this WP function is not able to handle primary key changes
1024 * (see https://github.com/woocommerce/woocommerce/issues/21534 and https://core.trac.wordpress.org/ticket/40357).
1025 */
1026 if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}woocommerce_sessions'" ) ) {
1027 if ( ! $wpdb->get_var( "SHOW KEYS FROM {$wpdb->prefix}woocommerce_sessions WHERE Key_name = 'PRIMARY' AND Column_name = 'session_id'" ) ) {
1028 $wpdb->query(
1029 "ALTER TABLE `{$wpdb->prefix}woocommerce_sessions` DROP PRIMARY KEY, DROP KEY `session_id`, ADD PRIMARY KEY(`session_id`), ADD UNIQUE KEY(`session_key`)"
1030 );
1031 }
1032 }
1033
1034 dbDelta( self::get_schema() );
1035
1036 $index_exists = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->comments} WHERE column_name = 'comment_type' and key_name = 'woo_idx_comment_type'" );
1037
1038 if ( is_null( $index_exists ) ) {
1039 // Add an index to the field comment_type to improve the response time of the query
1040 // used by WC_Comments::wp_count_comments() to get the number of comments by type.
1041 $wpdb->query( "ALTER TABLE {$wpdb->comments} ADD INDEX woo_idx_comment_type (comment_type)" );
1042 }
1043
1044 // Clear table caches.
1045 delete_transient( 'wc_attribute_taxonomies' );
1046 }
1047
1048 /**
1049 * Get Table schema.
1050 *
1051 * See https://github.com/woocommerce/woocommerce/wiki/Database-Description/
1052 *
1053 * A note on indexes; Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that.
1054 * As of WordPress 4.2, however, we moved to utf8mb4, which uses 4 bytes per character. This means that an index which
1055 * used to have room for floor(767/3) = 255 characters, now only has room for floor(767/4) = 191 characters.
1056 *
1057 * Changing indexes may cause duplicate index notices in logs due to https://core.trac.wordpress.org/ticket/34870 but dropping
1058 * indexes first causes too much load on some servers/larger DB.
1059 *
1060 * When adding or removing a table, make sure to update the list of tables in WC_Install::get_tables().
1061 *
1062 * @return string
1063 */
1064 private static function get_schema() {
1065 global $wpdb;
1066
1067 $collate = '';
1068
1069 if ( $wpdb->has_cap( 'collation' ) ) {
1070 $collate = $wpdb->get_charset_collate();
1071 }
1072
1073 /*
1074 * Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that.
1075 * As of WP 4.2, however, they moved to utf8mb4, which uses 4 bytes per character. This means that an index which
1076 * used to have room for floor(767/3) = 255 characters, now only has room for floor(767/4) = 191 characters.
1077 */
1078 $max_index_length = 191;
1079
1080 $product_attributes_lookup_table_creation_sql = wc_get_container()->get( DataRegenerator::class )->get_table_creation_sql();
1081
1082 $tables = "
1083 CREATE TABLE {$wpdb->prefix}woocommerce_sessions (
1084 session_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
1085 session_key char(32) NOT NULL,
1086 session_value longtext NOT NULL,
1087 session_expiry BIGINT UNSIGNED NOT NULL,
1088 PRIMARY KEY (session_id),
1089 UNIQUE KEY session_key (session_key)
1090 ) $collate;
1091 CREATE TABLE {$wpdb->prefix}woocommerce_api_keys (
1092 key_id BIGINT UNSIGNED NOT NULL auto_increment,
1093 user_id BIGINT UNSIGNED NOT NULL,
1094 description varchar(200) NULL,
1095 permissions varchar(10) NOT NULL,
1096 consumer_key char(64) NOT NULL,
1097 consumer_secret char(43) NOT NULL,
1098 nonces longtext NULL,
1099 truncated_key char(7) NOT NULL,
1100 last_access datetime NULL default null,
1101 PRIMARY KEY (key_id),
1102 KEY consumer_key (consumer_key),
1103 KEY consumer_secret (consumer_secret)
1104 ) $collate;
1105 CREATE TABLE {$wpdb->prefix}woocommerce_attribute_taxonomies (
1106 attribute_id BIGINT UNSIGNED NOT NULL auto_increment,
1107 attribute_name varchar(200) NOT NULL,
1108 attribute_label varchar(200) NULL,
1109 attribute_type varchar(20) NOT NULL,
1110 attribute_orderby varchar(20) NOT NULL,
1111 attribute_public int(1) NOT NULL DEFAULT 1,
1112 PRIMARY KEY (attribute_id),
1113 KEY attribute_name (attribute_name(20))
1114 ) $collate;
1115 CREATE TABLE {$wpdb->prefix}woocommerce_downloadable_product_permissions (
1116 permission_id BIGINT UNSIGNED NOT NULL auto_increment,
1117 download_id varchar(36) NOT NULL,
1118 product_id BIGINT UNSIGNED NOT NULL,
1119 order_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
1120 order_key varchar(200) NOT NULL,
1121 user_email varchar(200) NOT NULL,
1122 user_id BIGINT UNSIGNED NULL,
1123 downloads_remaining varchar(9) NULL,
1124 access_granted datetime NOT NULL default '0000-00-00 00:00:00',
1125 access_expires datetime NULL default null,
1126 download_count BIGINT UNSIGNED NOT NULL DEFAULT 0,
1127 PRIMARY KEY (permission_id),
1128 KEY download_order_key_product (product_id,order_id,order_key(16),download_id),
1129 KEY download_order_product (download_id,order_id,product_id),
1130 KEY order_id (order_id),
1131 KEY user_order_remaining_expires (user_id,order_id,downloads_remaining,access_expires)
1132 ) $collate;
1133 CREATE TABLE {$wpdb->prefix}woocommerce_order_items (
1134 order_item_id BIGINT UNSIGNED NOT NULL auto_increment,
1135 order_item_name TEXT NOT NULL,
1136 order_item_type varchar(200) NOT NULL DEFAULT '',
1137 order_id BIGINT UNSIGNED NOT NULL,
1138 PRIMARY KEY (order_item_id),
1139 KEY order_id (order_id)
1140 ) $collate;
1141 CREATE TABLE {$wpdb->prefix}woocommerce_order_itemmeta (
1142 meta_id BIGINT UNSIGNED NOT NULL auto_increment,
1143 order_item_id BIGINT UNSIGNED NOT NULL,
1144 meta_key varchar(255) default NULL,
1145 meta_value longtext NULL,
1146 PRIMARY KEY (meta_id),
1147 KEY order_item_id (order_item_id),
1148 KEY meta_key (meta_key(32))
1149 ) $collate;
1150 CREATE TABLE {$wpdb->prefix}woocommerce_tax_rates (
1151 tax_rate_id BIGINT UNSIGNED NOT NULL auto_increment,
1152 tax_rate_country varchar(2) NOT NULL DEFAULT '',
1153 tax_rate_state varchar(200) NOT NULL DEFAULT '',
1154 tax_rate varchar(8) NOT NULL DEFAULT '',
1155 tax_rate_name varchar(200) NOT NULL DEFAULT '',
1156 tax_rate_priority BIGINT UNSIGNED NOT NULL,
1157 tax_rate_compound int(1) NOT NULL DEFAULT 0,
1158 tax_rate_shipping int(1) NOT NULL DEFAULT 1,
1159 tax_rate_order BIGINT UNSIGNED NOT NULL,
1160 tax_rate_class varchar(200) NOT NULL DEFAULT '',
1161 PRIMARY KEY (tax_rate_id),
1162 KEY tax_rate_country (tax_rate_country),
1163 KEY tax_rate_state (tax_rate_state(2)),
1164 KEY tax_rate_class (tax_rate_class(10)),
1165 KEY tax_rate_priority (tax_rate_priority)
1166 ) $collate;
1167 CREATE TABLE {$wpdb->prefix}woocommerce_tax_rate_locations (
1168 location_id BIGINT UNSIGNED NOT NULL auto_increment,
1169 location_code varchar(200) NOT NULL,
1170 tax_rate_id BIGINT UNSIGNED NOT NULL,
1171 location_type varchar(40) NOT NULL,
1172 PRIMARY KEY (location_id),
1173 KEY tax_rate_id (tax_rate_id),
1174 KEY location_type_code (location_type(10),location_code(20))
1175 ) $collate;
1176 CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zones (
1177 zone_id BIGINT UNSIGNED NOT NULL auto_increment,
1178 zone_name varchar(200) NOT NULL,
1179 zone_order BIGINT UNSIGNED NOT NULL,
1180 PRIMARY KEY (zone_id)
1181 ) $collate;
1182 CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zone_locations (
1183 location_id BIGINT UNSIGNED NOT NULL auto_increment,
1184 zone_id BIGINT UNSIGNED NOT NULL,
1185 location_code varchar(200) NOT NULL,
1186 location_type varchar(40) NOT NULL,
1187 PRIMARY KEY (location_id),
1188 KEY location_id (location_id),
1189 KEY location_type_code (location_type(10),location_code(20))
1190 ) $collate;
1191 CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zone_methods (
1192 zone_id BIGINT UNSIGNED NOT NULL,
1193 instance_id BIGINT UNSIGNED NOT NULL auto_increment,
1194 method_id varchar(200) NOT NULL,
1195 method_order BIGINT UNSIGNED NOT NULL,
1196 is_enabled tinyint(1) NOT NULL DEFAULT '1',
1197 PRIMARY KEY (instance_id)
1198 ) $collate;
1199 CREATE TABLE {$wpdb->prefix}woocommerce_payment_tokens (
1200 token_id BIGINT UNSIGNED NOT NULL auto_increment,
1201 gateway_id varchar(200) NOT NULL,
1202 token text NOT NULL,
1203 user_id BIGINT UNSIGNED NOT NULL DEFAULT '0',
1204 type varchar(200) NOT NULL,
1205 is_default tinyint(1) NOT NULL DEFAULT '0',
1206 PRIMARY KEY (token_id),
1207 KEY user_id (user_id)
1208 ) $collate;
1209 CREATE TABLE {$wpdb->prefix}woocommerce_payment_tokenmeta (
1210 meta_id BIGINT UNSIGNED NOT NULL auto_increment,
1211 payment_token_id BIGINT UNSIGNED NOT NULL,
1212 meta_key varchar(255) NULL,
1213 meta_value longtext NULL,
1214 PRIMARY KEY (meta_id),
1215 KEY payment_token_id (payment_token_id),
1216 KEY meta_key (meta_key(32))
1217 ) $collate;
1218 CREATE TABLE {$wpdb->prefix}woocommerce_log (
1219 log_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
1220 timestamp datetime NOT NULL,
1221 level smallint(4) NOT NULL,
1222 source varchar(200) NOT NULL,
1223 message longtext NOT NULL,
1224 context longtext NULL,
1225 PRIMARY KEY (log_id),
1226 KEY level (level)
1227 ) $collate;
1228 CREATE TABLE {$wpdb->prefix}wc_webhooks (
1229 webhook_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
1230 status varchar(200) NOT NULL,
1231 name text NOT NULL,
1232 user_id BIGINT UNSIGNED NOT NULL,
1233 delivery_url text NOT NULL,
1234 secret text NOT NULL,
1235 topic varchar(200) NOT NULL,
1236 date_created datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
1237 date_created_gmt datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
1238 date_modified datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
1239 date_modified_gmt datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
1240 api_version smallint(4) NOT NULL,
1241 failure_count smallint(10) NOT NULL DEFAULT '0',
1242 pending_delivery tinyint(1) NOT NULL DEFAULT '0',
1243 PRIMARY KEY (webhook_id),
1244 KEY user_id (user_id)
1245 ) $collate;
1246 CREATE TABLE {$wpdb->prefix}wc_download_log (
1247 download_log_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
1248 timestamp datetime NOT NULL,
1249 permission_id BIGINT UNSIGNED NOT NULL,
1250 user_id BIGINT UNSIGNED NULL,
1251 user_ip_address VARCHAR(100) NULL DEFAULT '',
1252 PRIMARY KEY (download_log_id),
1253 KEY permission_id (permission_id),
1254 KEY timestamp (timestamp)
1255 ) $collate;
1256 CREATE TABLE {$wpdb->prefix}wc_product_meta_lookup (
1257 `product_id` bigint(20) NOT NULL,
1258 `sku` varchar(100) NULL default '',
1259 `virtual` tinyint(1) NULL default 0,
1260 `downloadable` tinyint(1) NULL default 0,
1261 `min_price` decimal(19,4) NULL default NULL,
1262 `max_price` decimal(19,4) NULL default NULL,
1263 `onsale` tinyint(1) NULL default 0,
1264 `stock_quantity` double NULL default NULL,
1265 `stock_status` varchar(100) NULL default 'instock',
1266 `rating_count` bigint(20) NULL default 0,
1267 `average_rating` decimal(3,2) NULL default 0.00,
1268 `total_sales` bigint(20) NULL default 0,
1269 `tax_status` varchar(100) NULL default 'taxable',
1270 `tax_class` varchar(100) NULL default '',
1271 PRIMARY KEY (`product_id`),
1272 KEY `virtual` (`virtual`),
1273 KEY `downloadable` (`downloadable`),
1274 KEY `stock_status` (`stock_status`),
1275 KEY `stock_quantity` (`stock_quantity`),
1276 KEY `onsale` (`onsale`),
1277 KEY min_max_price (`min_price`, `max_price`)
1278 ) $collate;
1279 CREATE TABLE {$wpdb->prefix}wc_tax_rate_classes (
1280 tax_rate_class_id BIGINT UNSIGNED NOT NULL auto_increment,
1281 name varchar(200) NOT NULL DEFAULT '',
1282 slug varchar(200) NOT NULL DEFAULT '',
1283 PRIMARY KEY (tax_rate_class_id),
1284 UNIQUE KEY slug (slug($max_index_length))
1285 ) $collate;
1286 CREATE TABLE {$wpdb->prefix}wc_reserved_stock (
1287 `order_id` bigint(20) NOT NULL,
1288 `product_id` bigint(20) NOT NULL,
1289 `stock_quantity` double NOT NULL DEFAULT 0,
1290 `timestamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
1291 `expires` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
1292 PRIMARY KEY (`order_id`, `product_id`)
1293 ) $collate;
1294 CREATE TABLE {$wpdb->prefix}wc_rate_limits (
1295 rate_limit_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
1296 rate_limit_key varchar(200) NOT NULL,
1297 rate_limit_expiry BIGINT UNSIGNED NOT NULL,
1298 rate_limit_remaining smallint(10) NOT NULL DEFAULT '0',
1299 PRIMARY KEY (rate_limit_id),
1300 UNIQUE KEY rate_limit_key (rate_limit_key($max_index_length))
1301 ) $collate;
1302 $product_attributes_lookup_table_creation_sql
1303 CREATE TABLE {$wpdb->prefix}wc_product_download_directories (
1304 url_id BIGINT UNSIGNED NOT NULL auto_increment,
1305 url varchar(256) NOT NULL,
1306 enabled TINYINT(1) NOT NULL DEFAULT 0,
1307 PRIMARY KEY (url_id),
1308 KEY url (url($max_index_length))
1309 ) $collate;
1310 CREATE TABLE {$wpdb->prefix}wc_order_stats (
1311 order_id bigint(20) unsigned NOT NULL,
1312 parent_id bigint(20) unsigned DEFAULT 0 NOT NULL,
1313 date_created datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
1314 date_created_gmt datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
1315 num_items_sold int(11) DEFAULT 0 NOT NULL,
1316 total_sales double DEFAULT 0 NOT NULL,
1317 tax_total double DEFAULT 0 NOT NULL,
1318 shipping_total double DEFAULT 0 NOT NULL,
1319 net_total double DEFAULT 0 NOT NULL,
1320 returning_customer boolean DEFAULT NULL,
1321 status varchar(200) NOT NULL,
1322 customer_id BIGINT UNSIGNED NOT NULL,
1323 PRIMARY KEY (order_id),
1324 KEY date_created (date_created),
1325 KEY customer_id (customer_id),
1326 KEY status (status({$max_index_length}))
1327 ) $collate;
1328 CREATE TABLE {$wpdb->prefix}wc_order_product_lookup (
1329 order_item_id BIGINT UNSIGNED NOT NULL,
1330 order_id BIGINT UNSIGNED NOT NULL,
1331 product_id BIGINT UNSIGNED NOT NULL,
1332 variation_id BIGINT UNSIGNED NOT NULL,
1333 customer_id BIGINT UNSIGNED NULL,
1334 date_created datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
1335 product_qty INT NOT NULL,
1336 product_net_revenue double DEFAULT 0 NOT NULL,
1337 product_gross_revenue double DEFAULT 0 NOT NULL,
1338 coupon_amount double DEFAULT 0 NOT NULL,
1339 tax_amount double DEFAULT 0 NOT NULL,
1340 shipping_amount double DEFAULT 0 NOT NULL,
1341 shipping_tax_amount double DEFAULT 0 NOT NULL,
1342 PRIMARY KEY (order_item_id),
1343 KEY order_id (order_id),
1344 KEY product_id (product_id),
1345 KEY customer_id (customer_id),
1346 KEY date_created (date_created)
1347 ) $collate;
1348 CREATE TABLE {$wpdb->prefix}wc_order_tax_lookup (
1349 order_id BIGINT UNSIGNED NOT NULL,
1350 tax_rate_id BIGINT UNSIGNED NOT NULL,
1351 date_created datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
1352 shipping_tax double DEFAULT 0 NOT NULL,
1353 order_tax double DEFAULT 0 NOT NULL,
1354 total_tax double DEFAULT 0 NOT NULL,
1355 PRIMARY KEY (order_id, tax_rate_id),
1356 KEY tax_rate_id (tax_rate_id),
1357 KEY date_created (date_created)
1358 ) $collate;
1359 CREATE TABLE {$wpdb->prefix}wc_order_coupon_lookup (
1360 order_id BIGINT UNSIGNED NOT NULL,
1361 coupon_id BIGINT NOT NULL,
1362 date_created datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
1363 discount_amount double DEFAULT 0 NOT NULL,
1364 PRIMARY KEY (order_id, coupon_id),
1365 KEY coupon_id (coupon_id),
1366 KEY date_created (date_created)
1367 ) $collate;
1368 CREATE TABLE {$wpdb->prefix}wc_admin_notes (
1369 note_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
1370 name varchar(255) NOT NULL,
1371 type varchar(20) NOT NULL,
1372 locale varchar(20) NOT NULL,
1373 title longtext NOT NULL,
1374 content longtext NOT NULL,
1375 content_data longtext NULL default null,
1376 status varchar(200) NOT NULL,
1377 source varchar(200) NOT NULL,
1378 date_created datetime NOT NULL default '0000-00-00 00:00:00',
1379 date_reminder datetime NULL default null,
1380 is_snoozable boolean DEFAULT 0 NOT NULL,
1381 layout varchar(20) DEFAULT '' NOT NULL,
1382 image varchar(200) NULL DEFAULT NULL,
1383 is_deleted boolean DEFAULT 0 NOT NULL,
1384 is_read boolean DEFAULT 0 NOT NULL,
1385 icon varchar(200) NOT NULL default 'info',
1386 PRIMARY KEY (note_id)
1387 ) $collate;
1388 CREATE TABLE {$wpdb->prefix}wc_admin_note_actions (
1389 action_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
1390 note_id BIGINT UNSIGNED NOT NULL,
1391 name varchar(255) NOT NULL,
1392 label varchar(255) NOT NULL,
1393 query longtext NOT NULL,
1394 status varchar(255) NOT NULL,
1395 actioned_text varchar(255) NOT NULL,
1396 nonce_action varchar(255) NULL DEFAULT NULL,
1397 nonce_name varchar(255) NULL DEFAULT NULL,
1398 PRIMARY KEY (action_id),
1399 KEY note_id (note_id)
1400 ) $collate;
1401 CREATE TABLE {$wpdb->prefix}wc_customer_lookup (
1402 customer_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
1403 user_id BIGINT UNSIGNED DEFAULT NULL,
1404 username varchar(60) DEFAULT '' NOT NULL,
1405 first_name varchar(255) NOT NULL,
1406 last_name varchar(255) NOT NULL,
1407 email varchar(100) NULL default NULL,
1408 date_last_active timestamp NULL default null,
1409 date_registered timestamp NULL default null,
1410 country char(2) DEFAULT '' NOT NULL,
1411 postcode varchar(20) DEFAULT '' NOT NULL,
1412 city varchar(100) DEFAULT '' NOT NULL,
1413 state varchar(100) DEFAULT '' NOT NULL,
1414 PRIMARY KEY (customer_id),
1415 UNIQUE KEY user_id (user_id),
1416 KEY email (email)
1417 ) $collate;
1418 CREATE TABLE {$wpdb->prefix}wc_category_lookup (
1419 category_tree_id BIGINT UNSIGNED NOT NULL,
1420 category_id BIGINT UNSIGNED NOT NULL,
1421 PRIMARY KEY (category_tree_id,category_id)
1422 ) $collate;
1423 ";
1424
1425 return $tables;
1426 }
1427
1428 /**
1429 * Return a list of WooCommerce tables. Used to make sure all WC tables are dropped when uninstalling the plugin
1430 * in a single site or multi site environment.
1431 *
1432 * @return array WC tables.
1433 */
1434 public static function get_tables() {
1435 global $wpdb;
1436
1437 $tables = array(
1438 "{$wpdb->prefix}wc_download_log",
1439 "{$wpdb->prefix}wc_product_download_directories",
1440 "{$wpdb->prefix}wc_product_meta_lookup",
1441 "{$wpdb->prefix}wc_tax_rate_classes",
1442 "{$wpdb->prefix}wc_webhooks",
1443 "{$wpdb->prefix}woocommerce_api_keys",
1444 "{$wpdb->prefix}woocommerce_attribute_taxonomies",
1445 "{$wpdb->prefix}woocommerce_downloadable_product_permissions",
1446 "{$wpdb->prefix}woocommerce_log",
1447 "{$wpdb->prefix}woocommerce_order_itemmeta",
1448 "{$wpdb->prefix}woocommerce_order_items",
1449 "{$wpdb->prefix}woocommerce_payment_tokenmeta",
1450 "{$wpdb->prefix}woocommerce_payment_tokens",
1451 "{$wpdb->prefix}woocommerce_sessions",
1452 "{$wpdb->prefix}woocommerce_shipping_zone_locations",
1453 "{$wpdb->prefix}woocommerce_shipping_zone_methods",
1454 "{$wpdb->prefix}woocommerce_shipping_zones",
1455 "{$wpdb->prefix}woocommerce_tax_rate_locations",
1456 "{$wpdb->prefix}woocommerce_tax_rates",
1457 "{$wpdb->prefix}wc_reserved_stock",
1458 "{$wpdb->prefix}wc_rate_limits",
1459 wc_get_container()->get( DataRegenerator::class )->get_lookup_table_name(),
1460
1461 // WCA Tables.
1462 "{$wpdb->prefix}wc_order_stats",
1463 "{$wpdb->prefix}wc_order_product_lookup",
1464 "{$wpdb->prefix}wc_order_tax_lookup",
1465 "{$wpdb->prefix}wc_order_coupon_lookup",
1466 "{$wpdb->prefix}wc_admin_notes",
1467 "{$wpdb->prefix}wc_admin_note_actions",
1468 "{$wpdb->prefix}wc_customer_lookup",
1469 "{$wpdb->prefix}wc_category_lookup",
1470 );
1471
1472 /**
1473 * Filter the list of known WooCommerce tables.
1474 *
1475 * If WooCommerce plugins need to add new tables, they can inject them here.
1476 *
1477 * @param array $tables An array of WooCommerce-specific database table names.
1478 * @since 3.4.0
1479 */
1480 $tables = apply_filters( 'woocommerce_install_get_tables', $tables );
1481
1482 return $tables;
1483 }
1484
1485 /**
1486 * Drop WooCommerce tables.
1487 *
1488 * @return void
1489 */
1490 public static function drop_tables() {
1491 global $wpdb;
1492
1493 $tables = self::get_tables();
1494
1495 foreach ( $tables as $table ) {
1496 $wpdb->query( "DROP TABLE IF EXISTS {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
1497 }
1498 }
1499
1500 /**
1501 * Uninstall tables when MU blog is deleted.
1502 *
1503 * @param array $tables List of tables that will be deleted by WP.
1504 *
1505 * @return string[]
1506 */
1507 public static function wpmu_drop_tables( $tables ) {
1508 return array_merge( $tables, self::get_tables() );
1509 }
1510
1511 /**
1512 * Create roles and capabilities.
1513 */
1514 public static function create_roles() {
1515 global $wp_roles;
1516
1517 if ( ! class_exists( 'WP_Roles' ) ) {
1518 return;
1519 }
1520
1521 if ( ! isset( $wp_roles ) ) {
1522 $wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
1523 }
1524
1525 // Dummy gettext calls to get strings in the catalog.
1526 /* translators: user role */
1527 _x( 'Customer', 'User role', 'woocommerce' );
1528 /* translators: user role */
1529 _x( 'Shop manager', 'User role', 'woocommerce' );
1530
1531 // Customer role.
1532 add_role(
1533 'customer',
1534 'Customer',
1535 array(
1536 'read' => true,
1537 )
1538 );
1539
1540 // Shop manager role.
1541 add_role(
1542 'shop_manager',
1543 'Shop manager',
1544 array(
1545 'level_9' => true,
1546 'level_8' => true,
1547 'level_7' => true,
1548 'level_6' => true,
1549 'level_5' => true,
1550 'level_4' => true,
1551 'level_3' => true,
1552 'level_2' => true,
1553 'level_1' => true,
1554 'level_0' => true,
1555 'read' => true,
1556 'read_private_pages' => true,
1557 'read_private_posts' => true,
1558 'edit_posts' => true,
1559 'edit_pages' => true,
1560 'edit_published_posts' => true,
1561 'edit_published_pages' => true,
1562 'edit_private_pages' => true,
1563 'edit_private_posts' => true,
1564 'edit_others_posts' => true,
1565 'edit_others_pages' => true,
1566 'publish_posts' => true,
1567 'publish_pages' => true,
1568 'delete_posts' => true,
1569 'delete_pages' => true,
1570 'delete_private_pages' => true,
1571 'delete_private_posts' => true,
1572 'delete_published_pages' => true,
1573 'delete_published_posts' => true,
1574 'delete_others_posts' => true,
1575 'delete_others_pages' => true,
1576 'manage_categories' => true,
1577 'manage_links' => true,
1578 'moderate_comments' => true,
1579 'upload_files' => true,
1580 'export' => true,
1581 'import' => true,
1582 'list_users' => true,
1583 'edit_theme_options' => true,
1584 )
1585 );
1586
1587 $capabilities = self::get_core_capabilities();
1588
1589 foreach ( $capabilities as $cap_group ) {
1590 foreach ( $cap_group as $cap ) {
1591 $wp_roles->add_cap( 'shop_manager', $cap );
1592 $wp_roles->add_cap( 'administrator', $cap );
1593 }
1594 }
1595 }
1596
1597 /**
1598 * Get capabilities for WooCommerce - these are assigned to admin/shop manager during installation or reset.
1599 *
1600 * @return array
1601 */
1602 public static function get_core_capabilities() {
1603 $capabilities = array();
1604
1605 $capabilities['core'] = array(
1606 'manage_woocommerce',
1607 'view_woocommerce_reports',
1608 );
1609
1610 $capability_types = array( 'product', 'shop_order', 'shop_coupon' );
1611
1612 foreach ( $capability_types as $capability_type ) {
1613
1614 $capabilities[ $capability_type ] = array(
1615 // Post type.
1616 "edit_{$capability_type}",
1617 "read_{$capability_type}",
1618 "delete_{$capability_type}",
1619 "edit_{$capability_type}s",
1620 "edit_others_{$capability_type}s",
1621 "publish_{$capability_type}s",
1622 "read_private_{$capability_type}s",
1623 "delete_{$capability_type}s",
1624 "delete_private_{$capability_type}s",
1625 "delete_published_{$capability_type}s",
1626 "delete_others_{$capability_type}s",
1627 "edit_private_{$capability_type}s",
1628 "edit_published_{$capability_type}s",
1629
1630 // Terms.
1631 "manage_{$capability_type}_terms",
1632 "edit_{$capability_type}_terms",
1633 "delete_{$capability_type}_terms",
1634 "assign_{$capability_type}_terms",
1635 );
1636 }
1637
1638 return $capabilities;
1639 }
1640
1641 /**
1642 * Remove WooCommerce roles.
1643 */
1644 public static function remove_roles() {
1645 global $wp_roles;
1646
1647 if ( ! class_exists( 'WP_Roles' ) ) {
1648 return;
1649 }
1650
1651 if ( ! isset( $wp_roles ) ) {
1652 $wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
1653 }
1654
1655 $capabilities = self::get_core_capabilities();
1656
1657 foreach ( $capabilities as $cap_group ) {
1658 foreach ( $cap_group as $cap ) {
1659 $wp_roles->remove_cap( 'shop_manager', $cap );
1660 $wp_roles->remove_cap( 'administrator', $cap );
1661 }
1662 }
1663
1664 remove_role( 'customer' );
1665 remove_role( 'shop_manager' );
1666 }
1667
1668 /**
1669 * Create files/directories.
1670 */
1671 private static function create_files() {
1672 /**
1673 * Bypass if filesystem is read-only and/or non-standard upload system is used.
1674 *
1675 * @since 3.2.0
1676 */
1677 if ( apply_filters( 'woocommerce_install_skip_create_files', false ) ) {
1678 return;
1679 }
1680
1681 // Install files and folders for uploading files and prevent hotlinking.
1682 $upload_dir = wp_get_upload_dir();
1683 $download_method = get_option( 'woocommerce_file_download_method', 'force' );
1684
1685 $files = array(
1686 array(
1687 'base' => $upload_dir['basedir'] . '/woocommerce_uploads',
1688 'file' => 'index.html',
1689 'content' => '',
1690 ),
1691 array(
1692 'base' => WC_LOG_DIR,
1693 'file' => '.htaccess',
1694 'content' => 'deny from all',
1695 ),
1696 array(
1697 'base' => WC_LOG_DIR,
1698 'file' => 'index.html',
1699 'content' => '',
1700 ),
1701 array(
1702 'base' => $upload_dir['basedir'] . '/woocommerce_uploads',
1703 'file' => '.htaccess',
1704 'content' => 'redirect' === $download_method ? 'Options -Indexes' : 'deny from all',
1705 ),
1706 );
1707
1708 foreach ( $files as $file ) {
1709 if ( wp_mkdir_p( $file['base'] ) && ! file_exists( trailingslashit( $file['base'] ) . $file['file'] ) ) {
1710 $file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'wb' ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen
1711 if ( $file_handle ) {
1712 fwrite( $file_handle, $file['content'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fwrite
1713 fclose( $file_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose
1714 }
1715 }
1716 }
1717
1718 // Create attachment for placeholders.
1719 self::create_placeholder_image();
1720 }
1721
1722 /**
1723 * Create a placeholder image in the media library.
1724 *
1725 * @since 3.5.0
1726 */
1727 private static function create_placeholder_image() {
1728 $placeholder_image = get_option( 'woocommerce_placeholder_image', 0 );
1729
1730 // Validate current setting if set. If set, return.
1731 if ( ! empty( $placeholder_image ) ) {
1732 if ( ! is_numeric( $placeholder_image ) ) {
1733 return;
1734 } elseif ( $placeholder_image && wp_attachment_is_image( $placeholder_image ) ) {
1735 return;
1736 }
1737 }
1738
1739 $upload_dir = wp_upload_dir();
1740 $source = WC()->plugin_path() . '/assets/images/placeholder-attachment.png';
1741 $filename = $upload_dir['basedir'] . '/woocommerce-placeholder.png';
1742
1743 if ( ! file_exists( $filename ) ) {
1744 copy( $source, $filename ); // @codingStandardsIgnoreLine.
1745 }
1746
1747 if ( ! file_exists( $filename ) ) {
1748 update_option( 'woocommerce_placeholder_image', 0 );
1749 return;
1750 }
1751
1752 $filetype = wp_check_filetype( basename( $filename ), null );
1753 $attachment = array(
1754 'guid' => $upload_dir['url'] . '/' . basename( $filename ),
1755 'post_mime_type' => $filetype['type'],
1756 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
1757 'post_content' => '',
1758 'post_status' => 'inherit',
1759 );
1760
1761 $attach_id = wp_insert_attachment( $attachment, $filename );
1762 if ( is_wp_error( $attach_id ) ) {
1763 update_option( 'woocommerce_placeholder_image', 0 );
1764 return;
1765 }
1766
1767 update_option( 'woocommerce_placeholder_image', $attach_id );
1768
1769 // Make sure that this file is included, as wp_generate_attachment_metadata() depends on it.
1770 require_once ABSPATH . 'wp-admin/includes/image.php';
1771
1772 // Generate the metadata for the attachment, and update the database record.
1773 $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
1774 wp_update_attachment_metadata( $attach_id, $attach_data );
1775 }
1776
1777 /**
1778 * Show action links on the plugin screen.
1779 *
1780 * @param mixed $links Plugin Action links.
1781 *
1782 * @return array
1783 */
1784 public static function plugin_action_links( $links ) {
1785 $action_links = array(
1786 'settings' => '<a href="' . admin_url( 'admin.php?page=wc-settings' ) . '" aria-label="' . esc_attr__( 'View WooCommerce settings', 'woocommerce' ) . '">' . esc_html__( 'Settings', 'woocommerce' ) . '</a>',
1787 );
1788
1789 return array_merge( $action_links, $links );
1790 }
1791
1792 /**
1793 * Show row meta on the plugin screen.
1794 *
1795 * @param mixed $links Plugin Row Meta.
1796 * @param mixed $file Plugin Base file.
1797 *
1798 * @return array
1799 */
1800 public static function plugin_row_meta( $links, $file ) {
1801 if ( WC_PLUGIN_BASENAME !== $file ) {
1802 return $links;
1803 }
1804
1805 /**
1806 * The WooCommerce documentation URL.
1807 *
1808 * @since 2.7.0
1809 */
1810 $docs_url = apply_filters( 'woocommerce_docs_url', 'https://docs.woocommerce.com/documentation/plugins/woocommerce/' );
1811
1812 /**
1813 * The WooCommerce API documentation URL.
1814 *
1815 * @since 2.2.0
1816 */
1817 $api_docs_url = apply_filters( 'woocommerce_apidocs_url', 'https://docs.woocommerce.com/wc-apidocs/' );
1818
1819 /**
1820 * The community WooCommerce support URL.
1821 *
1822 * @since 2.2.0
1823 */
1824 $community_support_url = apply_filters( 'woocommerce_community_support_url', 'https://wordpress.org/support/plugin/woocommerce/' );
1825
1826 /**
1827 * The premium support URL.
1828 *
1829 * @since
1830 */
1831 $support_url = apply_filters( 'woocommerce_support_url', 'https://woocommerce.com/my-account/create-a-ticket/' );
1832
1833 $row_meta = array(
1834 'docs' => '<a href="' . esc_url( $docs_url ) . '" aria-label="' . esc_attr__( 'View WooCommerce documentation', 'woocommerce' ) . '">' . esc_html__( 'Docs', 'woocommerce' ) . '</a>',
1835 'apidocs' => '<a href="' . esc_url( $api_docs_url ) . '" aria-label="' . esc_attr__( 'View WooCommerce API docs', 'woocommerce' ) . '">' . esc_html__( 'API docs', 'woocommerce' ) . '</a>',
1836 'support' => '<a href="' . esc_url( $community_support_url ) . '" aria-label="' . esc_attr__( 'Visit community forums', 'woocommerce' ) . '">' . esc_html__( 'Community support', 'woocommerce' ) . '</a>',
1837 );
1838
1839 if ( WCConnectionHelper::is_connected() ) {
1840 $row_meta['premium_support'] = '<a href="' . esc_url( $support_url ) . '" aria-label="' . esc_attr__( 'Visit premium customer support', 'woocommerce' ) . '">' . esc_html__( 'Premium support', 'woocommerce' ) . '</a>';
1841 }
1842
1843 return array_merge( $links, $row_meta );
1844 }
1845
1846 /**
1847 * Get slug from path and associate it with the path.
1848 *
1849 * @param array $plugins Associative array of plugin files to paths.
1850 * @param string $key Plugin relative path. Example: woocommerce/woocommerce.php.
1851 */
1852 private static function associate_plugin_file( $plugins, $key ) {
1853 $path = explode( '/', $key );
1854 $filename = end( $path );
1855 $plugins[ $filename ] = $key;
1856 return $plugins;
1857 }
1858
1859 /**
1860 * Install a plugin from .org in the background via a cron job (used by
1861 * installer - opt in).
1862 *
1863 * @param string $plugin_to_install_id Plugin ID.
1864 * @param array $plugin_to_install Plugin information.
1865 *
1866 * @throws Exception If unable to proceed with plugin installation.
1867 * @since 2.6.0
1868 */
1869 public static function background_installer( $plugin_to_install_id, $plugin_to_install ) {
1870 // Explicitly clear the event.
1871 $args = func_get_args();
1872
1873 if ( ! empty( $plugin_to_install['repo-slug'] ) ) {
1874 require_once ABSPATH . 'wp-admin/includes/file.php';
1875 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
1876 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
1877 require_once ABSPATH . 'wp-admin/includes/plugin.php';
1878
1879 WP_Filesystem();
1880
1881 $skin = new Automatic_Upgrader_Skin();
1882 $upgrader = new WP_Upgrader( $skin );
1883 $installed_plugins = array_reduce( array_keys( get_plugins() ), array( __CLASS__, 'associate_plugin_file' ) );
1884 if ( empty( $installed_plugins ) ) {
1885 $installed_plugins = array();
1886 }
1887 $plugin_slug = $plugin_to_install['repo-slug'];
1888 $plugin_file = isset( $plugin_to_install['file'] ) ? $plugin_to_install['file'] : $plugin_slug . '.php';
1889 $installed = false;
1890 $activate = false;
1891
1892 // See if the plugin is installed already.
1893 if ( isset( $installed_plugins[ $plugin_file ] ) ) {
1894 $installed = true;
1895 $activate = ! is_plugin_active( $installed_plugins[ $plugin_file ] );
1896 }
1897
1898 // Install this thing!
1899 if ( ! $installed ) {
1900 // Suppress feedback.
1901 ob_start();
1902
1903 try {
1904 $plugin_information = plugins_api(
1905 'plugin_information',
1906 array(
1907 'slug' => $plugin_slug,
1908 'fields' => array(
1909 'short_description' => false,
1910 'sections' => false,
1911 'requires' => false,
1912 'rating' => false,
1913 'ratings' => false,
1914 'downloaded' => false,
1915 'last_updated' => false,
1916 'added' => false,
1917 'tags' => false,
1918 'homepage' => false,
1919 'donate_link' => false,
1920 'author_profile' => false,
1921 'author' => false,
1922 ),
1923 )
1924 );
1925
1926 if ( is_wp_error( $plugin_information ) ) {
1927 throw new Exception( $plugin_information->get_error_message() );
1928 }
1929
1930 $package = $plugin_information->download_link;
1931 $download = $upgrader->download_package( $package );
1932
1933 if ( is_wp_error( $download ) ) {
1934 throw new Exception( $download->get_error_message() );
1935 }
1936
1937 $working_dir = $upgrader->unpack_package( $download, true );
1938
1939 if ( is_wp_error( $working_dir ) ) {
1940 throw new Exception( $working_dir->get_error_message() );
1941 }
1942
1943 $result = $upgrader->install_package(
1944 array(
1945 'source' => $working_dir,
1946 'destination' => WP_PLUGIN_DIR,
1947 'clear_destination' => false,
1948 'abort_if_destination_exists' => false,
1949 'clear_working' => true,
1950 'hook_extra' => array(
1951 'type' => 'plugin',
1952 'action' => 'install',
1953 ),
1954 )
1955 );
1956
1957 if ( is_wp_error( $result ) ) {
1958 throw new Exception( $result->get_error_message() );
1959 }
1960
1961 $activate = true;
1962
1963 } catch ( Exception $e ) {
1964 WC_Admin_Notices::add_custom_notice(
1965 $plugin_to_install_id . '_install_error',
1966 sprintf(
1967 // translators: 1: plugin name, 2: error message, 3: URL to install plugin manually.
1968 __( '%1$s could not be installed (%2$s). <a href="%3$s">Please install it manually by clicking here.</a>', 'woocommerce' ),
1969 $plugin_to_install['name'],
1970 $e->getMessage(),
1971 esc_url( admin_url( 'index.php?wc-install-plugin-redirect=' . $plugin_slug ) )
1972 )
1973 );
1974 }
1975
1976 // Discard feedback.
1977 ob_end_clean();
1978 }
1979
1980 wp_clean_plugins_cache();
1981
1982 // Activate this thing.
1983 if ( $activate ) {
1984 try {
1985 add_action( 'add_option_mailchimp_woocommerce_plugin_do_activation_redirect', array( __CLASS__, 'remove_mailchimps_redirect' ), 10, 2 );
1986 $result = activate_plugin( $installed ? $installed_plugins[ $plugin_file ] : $plugin_slug . '/' . $plugin_file );
1987
1988 if ( is_wp_error( $result ) ) {
1989 throw new Exception( $result->get_error_message() );
1990 }
1991 } catch ( Exception $e ) {
1992 WC_Admin_Notices::add_custom_notice(
1993 $plugin_to_install_id . '_install_error',
1994 sprintf(
1995 // translators: 1: plugin name, 2: URL to WP plugin page.
1996 __( '%1$s was installed but could not be activated. <a href="%2$s">Please activate it manually by clicking here.</a>', 'woocommerce' ),
1997 $plugin_to_install['name'],
1998 admin_url( 'plugins.php' )
1999 )
2000 );
2001 }
2002 }
2003 }
2004 }
2005
2006 /**
2007 * Removes redirect added during MailChimp plugin's activation.
2008 *
2009 * @param string $option Option name.
2010 * @param string $value Option value.
2011 */
2012 public static function remove_mailchimps_redirect( $option, $value ) {
2013 // Remove this action to prevent infinite looping.
2014 remove_action( 'add_option_mailchimp_woocommerce_plugin_do_activation_redirect', array( __CLASS__, 'remove_mailchimps_redirect' ) );
2015
2016 // Update redirect back to false.
2017 update_option( 'mailchimp_woocommerce_plugin_do_activation_redirect', false );
2018 }
2019
2020 /**
2021 * Install a theme from .org in the background via a cron job (used by installer - opt in).
2022 *
2023 * @param string $theme_slug Theme slug.
2024 *
2025 * @throws Exception If unable to proceed with theme installation.
2026 * @since 3.1.0
2027 */
2028 public static function theme_background_installer( $theme_slug ) {
2029 // Explicitly clear the event.
2030 $args = func_get_args();
2031
2032 if ( ! empty( $theme_slug ) ) {
2033 // Suppress feedback.
2034 ob_start();
2035
2036 try {
2037 $theme = wp_get_theme( $theme_slug );
2038
2039 if ( ! $theme->exists() ) {
2040 require_once ABSPATH . 'wp-admin/includes/file.php';
2041 include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
2042 include_once ABSPATH . 'wp-admin/includes/theme.php';
2043
2044 WP_Filesystem();
2045
2046 $skin = new Automatic_Upgrader_Skin();
2047 $upgrader = new Theme_Upgrader( $skin );
2048 $api = themes_api(
2049 'theme_information',
2050 array(
2051 'slug' => $theme_slug,
2052 'fields' => array( 'sections' => false ),
2053 )
2054 );
2055 $result = $upgrader->install( $api->download_link );
2056
2057 if ( is_wp_error( $result ) ) {
2058 throw new Exception( $result->get_error_message() );
2059 } elseif ( is_wp_error( $skin->result ) ) {
2060 throw new Exception( $skin->result->get_error_message() );
2061 } elseif ( is_null( $result ) ) {
2062 throw new Exception( 'Unable to connect to the filesystem. Please confirm your credentials.' );
2063 }
2064 }
2065
2066 switch_theme( $theme_slug );
2067 } catch ( Exception $e ) {
2068 WC_Admin_Notices::add_custom_notice(
2069 $theme_slug . '_install_error',
2070 sprintf(
2071 // translators: 1: theme slug, 2: error message, 3: URL to install theme manually.
2072 __( '%1$s could not be installed (%2$s). <a href="%3$s">Please install it manually by clicking here.</a>', 'woocommerce' ),
2073 $theme_slug,
2074 $e->getMessage(),
2075 esc_url( admin_url( 'update.php?action=install-theme&theme=' . $theme_slug . '&_wpnonce=' . wp_create_nonce( 'install-theme_' . $theme_slug ) ) )
2076 )
2077 );
2078 }
2079
2080 // Discard feedback.
2081 ob_end_clean();
2082 }
2083 }
2084
2085 /**
2086 * Sets whether PayPal Standard will be loaded on install.
2087 *
2088 * @since 5.5.0
2089 */
2090 private static function set_paypal_standard_load_eligibility() {
2091 // Initiating the payment gateways sets the flag.
2092 if ( class_exists( 'WC_Gateway_Paypal' ) ) {
2093 ( new WC_Gateway_Paypal() )->should_load();
2094 }
2095 }
2096
2097 /**
2098 * Gets the content of the sample refunds and return policy page.
2099 *
2100 * @since 5.6.0
2101 * @return string The content for the page
2102 */
2103 private static function get_refunds_return_policy_page_content() {
2104 return <<<EOT
2105 <!-- wp:paragraph -->
2106 <p><b>This is a sample page.</b></p>
2107 <!-- /wp:paragraph -->
2108
2109 <!-- wp:paragraph -->
2110 <h3>Overview</h3>
2111 <!-- /wp:paragraph -->
2112
2113 <!-- wp:paragraph -->
2114 <p>Our refund and returns policy lasts 30 days. If 30 days have passed since your purchase, we can’t offer you a full refund or exchange.</p>
2115 <!-- /wp:paragraph -->
2116
2117 <!-- wp:paragraph -->
2118 <p>To be eligible for a return, your item must be unused and in the same condition that you received it. It must also be in the original packaging.</p>
2119 <!-- /wp:paragraph -->
2120
2121 <!-- wp:paragraph -->
2122 <p>Several types of goods are exempt from being returned. Perishable goods such as food, flowers, newspapers or magazines cannot be returned. We also do not accept products that are intimate or sanitary goods, hazardous materials, or flammable liquids or gases.</p>
2123 <!-- /wp:paragraph -->
2124
2125 <!-- wp:paragraph -->
2126 <p>Additional non-returnable items:</p>
2127 <!-- /wp:paragraph -->
2128
2129 <!-- wp:list -->
2130 <ul>
2131 <li>Gift cards</li>
2132 <li>Downloadable software products</li>
2133 <li>Some health and personal care items</li>
2134 </ul>
2135 <!-- /wp:list -->
2136
2137 <!-- wp:paragraph -->
2138 <p>To complete your return, we require a receipt or proof of purchase.</p>
2139 <!-- /wp:paragraph -->
2140
2141 <!-- wp:paragraph -->
2142 <p>Please do not send your purchase back to the manufacturer.</p>
2143 <!-- /wp:paragraph -->
2144
2145 <!-- wp:paragraph -->
2146 <p>There are certain situations where only partial refunds are granted:</p>
2147 <!-- /wp:paragraph -->
2148
2149 <!-- wp:list -->
2150 <ul>
2151 <li>Book with obvious signs of use</li>
2152 <li>CD, DVD, VHS tape, software, video game, cassette tape, or vinyl record that has been opened.</li>
2153 <li>Any item not in its original condition, is damaged or missing parts for reasons not due to our error.</li>
2154 <li>Any item that is returned more than 30 days after delivery</li>
2155 </ul>
2156 <!-- /wp:list -->
2157
2158 <!-- wp:paragraph -->
2159 <h2>Refunds</h2>
2160 <!-- /wp:paragraph -->
2161
2162 <!-- wp:paragraph -->
2163 <p>Once your return is received and inspected, we will send you an email to notify you that we have received your returned item. We will also notify you of the approval or rejection of your refund.</p>
2164 <!-- /wp:paragraph -->
2165
2166 <!-- wp:paragraph -->
2167 <p>If you are approved, then your refund will be processed, and a credit will automatically be applied to your credit card or original method of payment, within a certain amount of days.</p>
2168 <!-- /wp:paragraph -->
2169
2170 <!-- wp:paragraph -->
2171 <b>Late or missing refunds</b>
2172 <!-- /wp:paragraph -->
2173
2174 <!-- wp:paragraph -->
2175 <p>If you haven’t received a refund yet, first check your bank account again.</p>
2176 <!-- /wp:paragraph -->
2177
2178 <!-- wp:paragraph -->
2179 <p>Then contact your credit card company, it may take some time before your refund is officially posted.</p>
2180 <!-- /wp:paragraph -->
2181
2182 <!-- wp:paragraph -->
2183 <p>Next contact your bank. There is often some processing time before a refund is posted.</p>
2184 <!-- /wp:paragraph -->
2185
2186 <!-- wp:paragraph -->
2187 <p>If you’ve done all of this and you still have not received your refund yet, please contact us at {email address}.</p>
2188 <!-- /wp:paragraph -->
2189
2190 <!-- wp:paragraph -->
2191 <b>Sale items</b>
2192 <!-- /wp:paragraph -->
2193
2194 <!-- wp:paragraph -->
2195 <p>Only regular priced items may be refunded. Sale items cannot be refunded.</p>
2196 <!-- /wp:paragraph -->
2197
2198 <!-- wp:paragraph -->
2199 <h2>Exchanges</h2>
2200 <!-- /wp:paragraph -->
2201
2202 <!-- wp:paragraph -->
2203 <p>We only replace items if they are defective or damaged. If you need to exchange it for the same item, send us an email at {email address} and send your item to: {physical address}.</p>
2204 <!-- /wp:paragraph -->
2205
2206 <!-- wp:paragraph -->
2207 <h2>Gifts</h2>
2208 <!-- /wp:paragraph -->
2209
2210 <!-- wp:paragraph -->
2211 <p>If the item was marked as a gift when purchased and shipped directly to you, you’ll receive a gift credit for the value of your return. Once the returned item is received, a gift certificate will be mailed to you.</p>
2212 <!-- /wp:paragraph -->
2213
2214 <!-- wp:paragraph -->
2215 <p>If the item wasn’t marked as a gift when purchased, or the gift giver had the order shipped to themselves to give to you later, we will send a refund to the gift giver and they will find out about your return.</p>
2216 <!-- /wp:paragraph -->
2217
2218 <!-- wp:paragraph -->
2219 <h2>Shipping returns</h2>
2220 <!-- /wp:paragraph -->
2221
2222 <!-- wp:paragraph -->
2223 <p>To return your product, you should mail your product to: {physical address}.</p>
2224 <!-- /wp:paragraph -->
2225
2226 <!-- wp:paragraph -->
2227 <p>You will be responsible for paying for your own shipping costs for returning your item. Shipping costs are non-refundable. If you receive a refund, the cost of return shipping will be deducted from your refund.</p>
2228 <!-- /wp:paragraph -->
2229
2230 <!-- wp:paragraph -->
2231 <p>Depending on where you live, the time it may take for your exchanged product to reach you may vary.</p>
2232 <!-- /wp:paragraph -->
2233
2234 <!-- wp:paragraph -->
2235 <p>If you are returning more expensive items, you may consider using a trackable shipping service or purchasing shipping insurance. We don’t guarantee that we will receive your returned item.</p>
2236 <!-- /wp:paragraph -->
2237
2238 <!-- wp:paragraph -->
2239 <h2>Need help?</h2>
2240 <!-- /wp:paragraph -->
2241
2242 <!-- wp:paragraph -->
2243 <p>Contact us at {email} for questions related to refunds and returns.</p>
2244 <!-- /wp:paragraph -->
2245 EOT;
2246 }
2247
2248 /**
2249 * Adds an admin inbox note after a page has been created to notify
2250 * user. For example to take action to edit the page such as the
2251 * Refund and returns page.
2252 *
2253 * @since 5.6.0
2254 * @return void
2255 */
2256 public static function add_admin_note_after_page_created() {
2257 if ( ! WC()->is_wc_admin_active() ) {
2258 return;
2259 }
2260
2261 $page_id = get_option( 'woocommerce_refund_returns_page_created', null );
2262
2263 if ( null === $page_id ) {
2264 return;
2265 }
2266
2267 WC_Notes_Refund_Returns::possibly_add_note( $page_id );
2268 }
2269
2270 /**
2271 * When pages are created, we might want to take some action.
2272 * In this case we want to set an option when refund and returns
2273 * page is created.
2274 *
2275 * @since 5.6.0
2276 * @param int $page_id ID of the page.
2277 * @param array $page_data The data of the page created.
2278 * @return void
2279 */
2280 public static function page_created( $page_id, $page_data ) {
2281 if ( 'refund_returns' === $page_data['post_name'] ) {
2282 delete_option( 'woocommerce_refund_returns_page_created' );
2283 add_option( 'woocommerce_refund_returns_page_created', $page_id, '', false );
2284 }
2285 }
2286 }
2287
2288 WC_Install::init();
2289