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