2019-02-08 19:27:39 +00:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Installation related functions and actions.
|
|
|
|
*
|
|
|
|
* @package WooCommerce Admin/Classes
|
|
|
|
*/
|
|
|
|
|
2019-08-12 17:54:04 +00:00
|
|
|
namespace Automattic\WooCommerce\Admin;
|
|
|
|
|
2019-02-08 19:27:39 +00:00
|
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
|
2019-11-28 20:55:23 +00:00
|
|
|
use Automattic\WooCommerce\Admin\API\Reports\Cache;
|
2019-08-02 18:05:38 +00:00
|
|
|
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Historical_Data;
|
|
|
|
use \Automattic\WooCommerce\Admin\Notes\WC_Admin_Notes_Welcome_Message;
|
|
|
|
|
2019-02-08 19:27:39 +00:00
|
|
|
/**
|
2019-08-12 21:52:09 +00:00
|
|
|
* Install Class.
|
2019-02-08 19:27:39 +00:00
|
|
|
*/
|
2019-08-12 21:52:09 +00:00
|
|
|
class Install {
|
2019-02-08 19:27:39 +00:00
|
|
|
/**
|
|
|
|
* Plugin version option name.
|
|
|
|
*/
|
|
|
|
const VERSION_OPTION = 'wc_admin_version';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* DB updates and callbacks that need to be run per version.
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
2019-10-10 20:54:44 +00:00
|
|
|
protected static $db_updates = array(
|
|
|
|
'0.20.1' => array(
|
|
|
|
'wc_admin_update_0201_order_status_index',
|
|
|
|
'wc_admin_update_0201_db_version',
|
|
|
|
),
|
2019-11-22 15:06:14 +00:00
|
|
|
'0.23.0' => array(
|
|
|
|
'wc_admin_update_0230_rename_gross_total',
|
|
|
|
'wc_admin_update_0230_db_version',
|
|
|
|
),
|
2019-10-10 20:54:44 +00:00
|
|
|
);
|
2019-02-08 19:27:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Hook in tabs.
|
|
|
|
*/
|
|
|
|
public static function init() {
|
2019-03-25 06:43:26 +00:00
|
|
|
add_action( 'admin_init', array( __CLASS__, 'check_version' ), 5 );
|
2019-02-08 19:27:39 +00:00
|
|
|
add_filter( 'wpmu_drop_tables', array( __CLASS__, 'wpmu_drop_tables' ) );
|
|
|
|
|
|
|
|
// Add wc-admin report tables to list of WooCommerce tables.
|
|
|
|
add_filter( 'woocommerce_install_get_tables', array( __CLASS__, 'add_tables' ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check WC Admin version and run the updater is required.
|
|
|
|
*
|
|
|
|
* This check is done on all requests and runs if the versions do not match.
|
|
|
|
*/
|
|
|
|
public static function check_version() {
|
2019-11-19 23:23:27 +00:00
|
|
|
if ( defined( 'IFRAME_REQUEST' ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$version_option = get_option( self::VERSION_OPTION );
|
|
|
|
$requires_update = version_compare( get_option( self::VERSION_OPTION ), WC_ADMIN_VERSION_NUMBER, '<' );
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When included as part of Core, no `on_activation` hook as been called
|
|
|
|
* so there is no version in options. Make sure install gets called in this
|
|
|
|
* case as well as a regular version update
|
|
|
|
*/
|
|
|
|
if ( ! $version_option || $requires_update ) {
|
2019-02-08 19:27:39 +00:00
|
|
|
self::install();
|
2019-12-05 23:06:11 +00:00
|
|
|
do_action( 'woocommerce_admin_updated' );
|
2019-02-08 19:27:39 +00:00
|
|
|
}
|
2019-11-19 23:23:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add the version option if none is found, as would be the case when
|
|
|
|
* initialized via Core for the first time.
|
|
|
|
*/
|
|
|
|
if ( ! $version_option ) {
|
|
|
|
add_option( self::VERSION_OPTION, WC_ADMIN_VERSION_NUMBER );
|
|
|
|
}
|
2019-02-08 19:27:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Install WC Admin.
|
|
|
|
*/
|
|
|
|
public static function install() {
|
|
|
|
if ( ! is_blog_installed() ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we are not already running this routine.
|
|
|
|
if ( 'yes' === get_transient( 'wc_admin_installing' ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we made it till here nothing is running yet, lets set the transient now.
|
|
|
|
set_transient( 'wc_admin_installing', 'yes', MINUTE_IN_SECONDS * 10 );
|
|
|
|
wc_maybe_define_constant( 'WC_ADMIN_INSTALLING', true );
|
|
|
|
|
|
|
|
self::create_tables();
|
2019-05-14 14:33:22 +00:00
|
|
|
self::create_events();
|
|
|
|
self::create_notes();
|
2019-10-29 16:12:10 +00:00
|
|
|
self::maybe_update_db_version();
|
2019-03-12 13:13:20 +00:00
|
|
|
|
2019-02-08 19:27:39 +00:00
|
|
|
delete_transient( 'wc_admin_installing' );
|
|
|
|
|
2019-11-07 16:29:36 +00:00
|
|
|
// Use add_option() here to avoid overwriting this value with each
|
|
|
|
// plugin version update. We base plugin age off of this value.
|
|
|
|
add_option( 'wc_admin_install_timestamp', time() );
|
2019-12-05 23:06:11 +00:00
|
|
|
do_action( 'woocommerce_admin_installed' );
|
2019-02-08 19:27:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get database schema.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
2019-05-14 14:33:22 +00:00
|
|
|
protected static function get_schema() {
|
2019-02-08 19:27:39 +00:00
|
|
|
global $wpdb;
|
|
|
|
|
|
|
|
if ( $wpdb->has_cap( 'collation' ) ) {
|
|
|
|
$collate = $wpdb->get_charset_collate();
|
|
|
|
}
|
|
|
|
|
2019-10-10 20:54:44 +00:00
|
|
|
// Max DB index length. See wp_get_db_schema().
|
|
|
|
$max_index_length = 191;
|
|
|
|
|
2019-02-08 19:27:39 +00:00
|
|
|
$tables = "
|
|
|
|
CREATE TABLE {$wpdb->prefix}wc_order_stats (
|
|
|
|
order_id bigint(20) unsigned NOT NULL,
|
2019-05-10 06:39:25 +00:00
|
|
|
parent_id bigint(20) unsigned DEFAULT 0 NOT NULL,
|
2019-02-15 16:13:12 +00:00
|
|
|
date_created datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
2019-06-12 09:21:56 +00:00
|
|
|
date_created_gmt datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
2019-05-16 05:04:37 +00:00
|
|
|
num_items_sold int(11) DEFAULT 0 NOT NULL,
|
2019-11-22 15:06:14 +00:00
|
|
|
total_sales double DEFAULT 0 NOT NULL,
|
2019-02-08 19:27:39 +00:00
|
|
|
tax_total double DEFAULT 0 NOT NULL,
|
|
|
|
shipping_total double DEFAULT 0 NOT NULL,
|
|
|
|
net_total double DEFAULT 0 NOT NULL,
|
2019-05-10 06:39:25 +00:00
|
|
|
returning_customer boolean DEFAULT NULL,
|
2019-02-08 19:27:39 +00:00
|
|
|
status varchar(200) NOT NULL,
|
|
|
|
customer_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
PRIMARY KEY (order_id),
|
|
|
|
KEY date_created (date_created),
|
|
|
|
KEY customer_id (customer_id),
|
2019-10-10 20:54:44 +00:00
|
|
|
KEY status (status({$max_index_length}))
|
2019-02-20 02:30:00 +00:00
|
|
|
) $collate;
|
|
|
|
CREATE TABLE {$wpdb->prefix}wc_order_product_lookup (
|
2019-02-08 19:27:39 +00:00
|
|
|
order_item_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
order_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
product_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
variation_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
customer_id BIGINT UNSIGNED NULL,
|
2019-02-15 16:13:12 +00:00
|
|
|
date_created datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
2019-05-10 06:39:25 +00:00
|
|
|
product_qty INT NOT NULL,
|
2019-02-08 19:27:39 +00:00
|
|
|
product_net_revenue double DEFAULT 0 NOT NULL,
|
|
|
|
product_gross_revenue double DEFAULT 0 NOT NULL,
|
|
|
|
coupon_amount double DEFAULT 0 NOT NULL,
|
|
|
|
tax_amount double DEFAULT 0 NOT NULL,
|
|
|
|
shipping_amount double DEFAULT 0 NOT NULL,
|
|
|
|
shipping_tax_amount double DEFAULT 0 NOT NULL,
|
|
|
|
PRIMARY KEY (order_item_id),
|
|
|
|
KEY order_id (order_id),
|
|
|
|
KEY product_id (product_id),
|
|
|
|
KEY customer_id (customer_id),
|
|
|
|
KEY date_created (date_created)
|
2019-02-20 02:30:00 +00:00
|
|
|
) $collate;
|
|
|
|
CREATE TABLE {$wpdb->prefix}wc_order_tax_lookup (
|
|
|
|
order_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
tax_rate_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
date_created datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
|
|
|
shipping_tax double DEFAULT 0 NOT NULL,
|
|
|
|
order_tax double DEFAULT 0 NOT NULL,
|
|
|
|
total_tax double DEFAULT 0 NOT NULL,
|
|
|
|
PRIMARY KEY (order_id, tax_rate_id),
|
|
|
|
KEY tax_rate_id (tax_rate_id),
|
|
|
|
KEY date_created (date_created)
|
|
|
|
) $collate;
|
|
|
|
CREATE TABLE {$wpdb->prefix}wc_order_coupon_lookup (
|
2019-02-08 19:27:39 +00:00
|
|
|
order_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
coupon_id BIGINT UNSIGNED NOT NULL,
|
2019-02-15 16:13:12 +00:00
|
|
|
date_created datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
2019-02-08 19:27:39 +00:00
|
|
|
discount_amount double DEFAULT 0 NOT NULL,
|
|
|
|
PRIMARY KEY (order_id, coupon_id),
|
|
|
|
KEY coupon_id (coupon_id),
|
|
|
|
KEY date_created (date_created)
|
2019-02-20 02:30:00 +00:00
|
|
|
) $collate;
|
|
|
|
CREATE TABLE {$wpdb->prefix}wc_admin_notes (
|
|
|
|
note_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
|
|
name varchar(255) NOT NULL,
|
|
|
|
type varchar(20) NOT NULL,
|
|
|
|
locale varchar(20) NOT NULL,
|
|
|
|
title longtext NOT NULL,
|
|
|
|
content longtext NOT NULL,
|
|
|
|
icon varchar(200) NOT NULL,
|
|
|
|
content_data longtext NULL default null,
|
|
|
|
status varchar(200) NOT NULL,
|
|
|
|
source varchar(200) NOT NULL,
|
|
|
|
date_created datetime NOT NULL default '0000-00-00 00:00:00',
|
|
|
|
date_reminder datetime NULL default null,
|
2019-03-16 00:43:06 +00:00
|
|
|
is_snoozable boolean DEFAULT 0 NOT NULL,
|
2019-02-20 02:30:00 +00:00
|
|
|
PRIMARY KEY (note_id)
|
|
|
|
) $collate;
|
|
|
|
CREATE TABLE {$wpdb->prefix}wc_admin_note_actions (
|
|
|
|
action_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
|
|
note_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
name varchar(255) NOT NULL,
|
|
|
|
label varchar(255) NOT NULL,
|
|
|
|
query longtext NOT NULL,
|
2019-03-12 13:13:20 +00:00
|
|
|
status varchar(255) NOT NULL,
|
2019-05-21 19:01:55 +00:00
|
|
|
is_primary boolean DEFAULT 0 NOT NULL,
|
2019-02-20 02:30:00 +00:00
|
|
|
PRIMARY KEY (action_id),
|
|
|
|
KEY note_id (note_id)
|
|
|
|
) $collate;
|
|
|
|
CREATE TABLE {$wpdb->prefix}wc_customer_lookup (
|
|
|
|
customer_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
|
|
user_id BIGINT UNSIGNED DEFAULT NULL,
|
|
|
|
username varchar(60) DEFAULT '' NOT NULL,
|
|
|
|
first_name varchar(255) NOT NULL,
|
|
|
|
last_name varchar(255) NOT NULL,
|
|
|
|
email varchar(100) NULL default NULL,
|
|
|
|
date_last_active timestamp NULL default null,
|
|
|
|
date_registered timestamp NULL default null,
|
|
|
|
country char(2) DEFAULT '' NOT NULL,
|
|
|
|
postcode varchar(20) DEFAULT '' NOT NULL,
|
|
|
|
city varchar(100) DEFAULT '' NOT NULL,
|
2019-06-19 22:12:17 +00:00
|
|
|
state varchar(100) DEFAULT '' NOT NULL,
|
2019-02-20 02:30:00 +00:00
|
|
|
PRIMARY KEY (customer_id),
|
|
|
|
UNIQUE KEY user_id (user_id),
|
|
|
|
KEY email (email)
|
|
|
|
) $collate;
|
2019-10-01 23:35:37 +00:00
|
|
|
CREATE TABLE {$wpdb->prefix}wc_category_lookup (
|
|
|
|
category_tree_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
category_id BIGINT UNSIGNED NOT NULL,
|
|
|
|
PRIMARY KEY (category_tree_id,category_id)
|
|
|
|
) $collate;
|
2019-02-20 02:30:00 +00:00
|
|
|
";
|
2019-02-08 19:27:39 +00:00
|
|
|
|
|
|
|
return $tables;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create database tables.
|
|
|
|
*/
|
|
|
|
public static function create_tables() {
|
|
|
|
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
|
|
|
|
|
|
|
dbDelta( self::get_schema() );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a list of tables. Used to make sure all WC Admin tables are dropped
|
|
|
|
* when uninstalling the plugin in a single site or multi site environment.
|
|
|
|
*
|
|
|
|
* @return array WC tables.
|
|
|
|
*/
|
|
|
|
public static function get_tables() {
|
|
|
|
global $wpdb;
|
|
|
|
|
|
|
|
return array(
|
|
|
|
"{$wpdb->prefix}wc_order_stats",
|
|
|
|
"{$wpdb->prefix}wc_order_product_lookup",
|
|
|
|
"{$wpdb->prefix}wc_order_tax_lookup",
|
|
|
|
"{$wpdb->prefix}wc_order_coupon_lookup",
|
|
|
|
"{$wpdb->prefix}wc_admin_notes",
|
|
|
|
"{$wpdb->prefix}wc_admin_note_actions",
|
|
|
|
"{$wpdb->prefix}wc_customer_lookup",
|
2019-10-01 23:35:37 +00:00
|
|
|
"{$wpdb->prefix}wc_category_lookup",
|
2019-02-08 19:27:39 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds new tables.
|
|
|
|
*
|
|
|
|
* @param array $wc_tables List of WooCommerce tables.
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public static function add_tables( $wc_tables ) {
|
|
|
|
return array_merge(
|
|
|
|
$wc_tables,
|
|
|
|
self::get_tables()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Uninstall tables when MU blog is deleted.
|
|
|
|
*
|
|
|
|
* @param array $tables List of tables that will be deleted by WP.
|
|
|
|
*
|
|
|
|
* @return string[]
|
|
|
|
*/
|
|
|
|
public static function wpmu_drop_tables( $tables ) {
|
|
|
|
return array_merge( $tables, self::get_tables() );
|
|
|
|
}
|
|
|
|
|
2019-10-10 20:54:44 +00:00
|
|
|
/**
|
|
|
|
* Get list of DB update callbacks.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public static function get_db_update_callbacks() {
|
|
|
|
return self::$db_updates;
|
|
|
|
}
|
|
|
|
|
2019-10-29 16:12:10 +00:00
|
|
|
/**
|
|
|
|
* Is a DB update needed?
|
|
|
|
*
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
public static function needs_db_update() {
|
2019-12-24 18:19:08 +00:00
|
|
|
$current_db_version = get_option( self::VERSION_OPTION, null );
|
2019-10-29 16:12:10 +00:00
|
|
|
$updates = self::get_db_update_callbacks();
|
|
|
|
$update_versions = array_keys( $updates );
|
|
|
|
usort( $update_versions, 'version_compare' );
|
|
|
|
|
|
|
|
return ! is_null( $current_db_version ) && version_compare( $current_db_version, end( $update_versions ), '<' );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* See if we need to show or run database updates during install.
|
|
|
|
*/
|
|
|
|
private static function maybe_update_db_version() {
|
|
|
|
if ( self::needs_db_update() ) {
|
|
|
|
self::update();
|
|
|
|
} else {
|
|
|
|
self::update_db_version();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-10 20:54:44 +00:00
|
|
|
/**
|
|
|
|
* Push all needed DB updates to the queue for processing.
|
|
|
|
*/
|
2019-10-29 16:12:10 +00:00
|
|
|
private static function update() {
|
2019-10-10 20:54:44 +00:00
|
|
|
$current_db_version = get_option( self::VERSION_OPTION );
|
|
|
|
$loop = 0;
|
|
|
|
|
|
|
|
foreach ( self::get_db_update_callbacks() as $version => $update_callbacks ) {
|
|
|
|
if ( version_compare( $current_db_version, $version, '<' ) ) {
|
|
|
|
foreach ( $update_callbacks as $update_callback ) {
|
|
|
|
$pending_jobs = WC()->queue()->search(
|
|
|
|
array(
|
|
|
|
'per_page' => 1,
|
|
|
|
'hook' => 'woocommerce_run_update_callback',
|
|
|
|
'search' => json_encode( array( $update_callback ) ),
|
|
|
|
'group' => 'woocommerce-db-updates',
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
if ( empty( $pending_jobs ) ) {
|
|
|
|
WC()->queue()->schedule_single(
|
|
|
|
time() + $loop,
|
|
|
|
'woocommerce_run_update_callback',
|
|
|
|
array( $update_callback ),
|
|
|
|
'woocommerce-db-updates'
|
|
|
|
);
|
2019-11-28 20:55:23 +00:00
|
|
|
Cache::invalidate();
|
2019-10-10 20:54:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$loop++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-08 19:27:39 +00:00
|
|
|
/**
|
|
|
|
* Update WC Admin version to current.
|
2019-10-10 20:54:44 +00:00
|
|
|
*
|
|
|
|
* @param string|null $version New WooCommerce Admin DB version or null.
|
2019-02-08 19:27:39 +00:00
|
|
|
*/
|
2019-10-10 20:54:44 +00:00
|
|
|
public static function update_db_version( $version = null ) {
|
2019-02-08 19:27:39 +00:00
|
|
|
delete_option( self::VERSION_OPTION );
|
2019-10-10 20:54:44 +00:00
|
|
|
add_option( self::VERSION_OPTION, is_null( $version ) ? WC_ADMIN_VERSION_NUMBER : $version );
|
2019-02-08 19:27:39 +00:00
|
|
|
}
|
2019-05-14 14:33:22 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Schedule cron events.
|
|
|
|
*/
|
|
|
|
public static function create_events() {
|
|
|
|
if ( ! wp_next_scheduled( 'wc_admin_daily' ) ) {
|
|
|
|
wp_schedule_event( time(), 'daily', 'wc_admin_daily' );
|
|
|
|
}
|
2019-10-01 23:35:37 +00:00
|
|
|
wp_schedule_single_event( time() + 10, 'generate_category_lookup_table' );
|
2019-05-14 14:33:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create notes.
|
|
|
|
*/
|
|
|
|
protected static function create_notes() {
|
|
|
|
WC_Admin_Notes_Historical_Data::add_note();
|
|
|
|
WC_Admin_Notes_Welcome_Message::add_welcome_note();
|
|
|
|
}
|
2019-06-12 16:16:08 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete all data from tables.
|
|
|
|
*/
|
|
|
|
public static function delete_table_data() {
|
|
|
|
global $wpdb;
|
|
|
|
|
|
|
|
$tables = self::get_tables();
|
|
|
|
|
|
|
|
foreach ( $tables as $table ) {
|
|
|
|
$wpdb->query( "TRUNCATE TABLE {$table}" ); // WPCS: unprepared SQL ok.
|
|
|
|
}
|
|
|
|
}
|
2019-02-08 19:27:39 +00:00
|
|
|
}
|