2013-07-25 15:29:25 +00:00
< ? php
/**
2016-06-06 17:20:10 +00:00
* Installation related functions and actions .
2013-07-25 15:29:25 +00:00
*
2018-03-21 03:06:47 +00:00
* @ package WooCommerce / Classes
* @ version 3.0 . 0
2013-07-25 15:29:25 +00:00
*/
2018-03-21 03:06:47 +00:00
defined ( 'ABSPATH' ) || exit ;
2013-07-25 15:29:25 +00:00
/**
2015-11-03 13:31:20 +00:00
* WC_Install Class .
2013-07-25 15:29:25 +00:00
*/
class WC_Install {
2017-09-05 10:54:17 +00:00
/**
* DB updates and callbacks that need to be run per version .
*
* @ var array
*/
2015-04-29 09:47:57 +00:00
private static $db_updates = array (
2016-05-11 11:44:23 +00:00
'2.0.0' => array (
'wc_update_200_file_paths' ,
'wc_update_200_permalinks' ,
'wc_update_200_subcat_display' ,
'wc_update_200_taxrates' ,
'wc_update_200_line_items' ,
'wc_update_200_images' ,
'wc_update_200_db_version' ,
),
'2.0.9' => array (
'wc_update_209_brazillian_state' ,
'wc_update_209_db_version' ,
),
'2.1.0' => array (
'wc_update_210_remove_pages' ,
'wc_update_210_file_paths' ,
'wc_update_210_db_version' ,
),
'2.2.0' => array (
'wc_update_220_shipping' ,
'wc_update_220_order_status' ,
'wc_update_220_variations' ,
'wc_update_220_attributes' ,
'wc_update_220_db_version' ,
),
'2.3.0' => array (
'wc_update_230_options' ,
'wc_update_230_db_version' ,
),
'2.4.0' => array (
'wc_update_240_options' ,
'wc_update_240_shipping_methods' ,
'wc_update_240_api_keys' ,
'wc_update_240_refunds' ,
'wc_update_240_db_version' ,
),
'2.4.1' => array (
'wc_update_241_variations' ,
'wc_update_241_db_version' ,
),
'2.5.0' => array (
'wc_update_250_currency' ,
'wc_update_250_db_version' ,
),
'2.6.0' => array (
'wc_update_260_options' ,
'wc_update_260_termmeta' ,
'wc_update_260_zones' ,
'wc_update_260_zone_methods' ,
'wc_update_260_refunds' ,
'wc_update_260_db_version' ,
),
2017-03-15 16:55:07 +00:00
'3.0.0' => array (
'wc_update_300_grouped_products' ,
'wc_update_300_settings' ,
'wc_update_300_product_visibility' ,
'wc_update_300_db_version' ,
2016-08-03 20:32:02 +00:00
),
2017-06-01 18:26:35 +00:00
'3.1.0' => array (
'wc_update_310_downloadable_products' ,
2017-06-08 11:18:07 +00:00
'wc_update_310_old_comments' ,
2017-06-01 18:26:35 +00:00
'wc_update_310_db_version' ,
),
2017-08-15 16:01:28 +00:00
'3.1.2' => array (
'wc_update_312_shop_manager_capabilities' ,
'wc_update_312_db_version' ,
),
2017-06-28 11:57:37 +00:00
'3.2.0' => array (
'wc_update_320_mexican_states' ,
'wc_update_320_db_version' ,
),
2017-11-07 19:16:44 +00:00
'3.3.0' => array (
'wc_update_330_image_options' ,
2017-11-16 15:44:01 +00:00
'wc_update_330_webhooks' ,
2017-11-20 22:21:08 +00:00
'wc_update_330_product_stock_status' ,
2017-11-23 15:44:17 +00:00
'wc_update_330_set_default_product_cat' ,
2017-12-05 17:23:29 +00:00
'wc_update_330_clear_transients' ,
2018-01-23 02:51:01 +00:00
'wc_update_330_set_paypal_sandbox_credentials' ,
2017-11-07 19:16:44 +00:00
'wc_update_330_db_version' ,
),
2018-04-09 21:24:26 +00:00
'3.4.0' => array (
2018-04-17 15:13:44 +00:00
'wc_update_340_states' ,
2018-05-25 13:18:19 +00:00
'wc_update_340_state' ,
2018-05-01 13:13:38 +00:00
'wc_update_340_last_active' ,
2018-04-09 21:24:26 +00:00
'wc_update_340_db_version' ,
),
2015-04-29 09:47:57 +00:00
);
2017-09-05 10:54:17 +00:00
/**
* Background update class .
*
* @ var object
*/
2016-05-11 11:44:23 +00:00
private static $background_updater ;
2013-07-25 15:29:25 +00:00
/**
* Hook in tabs .
*/
2014-11-25 17:09:19 +00:00
public static function init () {
2016-01-19 10:05:44 +00:00
add_action ( 'init' , array ( __CLASS__ , 'check_version' ), 5 );
2016-06-15 15:11:04 +00:00
add_action ( 'init' , array ( __CLASS__ , 'init_background_updater' ), 5 );
2014-11-25 17:09:19 +00:00
add_action ( 'admin_init' , array ( __CLASS__ , 'install_actions' ) );
add_filter ( 'plugin_action_links_' . WC_PLUGIN_BASENAME , array ( __CLASS__ , 'plugin_action_links' ) );
add_filter ( 'plugin_row_meta' , array ( __CLASS__ , 'plugin_row_meta' ), 10 , 2 );
add_filter ( 'wpmu_drop_tables' , array ( __CLASS__ , 'wpmu_drop_tables' ) );
2015-09-03 15:21:53 +00:00
add_filter ( 'cron_schedules' , array ( __CLASS__ , 'cron_schedules' ) );
2016-04-18 16:05:19 +00:00
add_action ( 'woocommerce_plugin_background_installer' , array ( __CLASS__ , 'background_installer' ), 10 , 2 );
2017-05-17 16:42:18 +00:00
add_action ( 'woocommerce_theme_background_installer' , array ( __CLASS__ , 'theme_background_installer' ), 10 , 1 );
2016-06-15 15:11:04 +00:00
}
2016-05-11 11:44:23 +00:00
2016-06-15 15:11:04 +00:00
/**
* Init background updates
*/
public static function init_background_updater () {
2017-11-23 12:41:31 +00:00
include_once dirname ( __FILE__ ) . '/class-wc-background-updater.php' ;
2016-05-11 11:44:23 +00:00
self :: $background_updater = new WC_Background_Updater ();
2013-07-25 15:29:25 +00:00
}
/**
2016-01-19 10:05:44 +00:00
* Check WooCommerce version and run the updater is required .
*
2017-04-29 06:52:14 +00:00
* This check is done on all requests and runs if the versions do not match .
2013-07-25 15:29:25 +00:00
*/
2014-11-25 17:09:19 +00:00
public static function check_version () {
2018-02-05 16:40:51 +00:00
if ( ! defined ( 'IFRAME_REQUEST' ) && version_compare ( get_option ( 'woocommerce_version' ), WC () -> version , '<' ) ) {
2014-11-25 17:09:19 +00:00
self :: install ();
2014-02-11 13:33:56 +00:00
do_action ( 'woocommerce_updated' );
2014-01-12 00:05:14 +00:00
}
2013-07-25 15:29:25 +00:00
}
/**
2016-01-19 10:05:44 +00:00
* Install actions when a update button is clicked within the admin area .
*
* This function is hooked into admin_init to affect admin only .
2013-07-25 15:29:25 +00:00
*/
2014-11-25 17:09:19 +00:00
public static function install_actions () {
2018-06-07 12:05:46 +00:00
if ( ! empty ( $_GET [ 'do_update_woocommerce' ] ) ) { // WPCS: input var ok.
check_admin_referer ( 'wc_db_update' , 'wc_db_update_nonce' );
2014-11-25 17:09:19 +00:00
self :: update ();
2016-06-13 11:44:16 +00:00
WC_Admin_Notices :: add_notice ( 'update' );
2013-07-25 15:29:25 +00:00
}
2018-06-07 12:50:14 +00:00
if ( ! empty ( $_GET [ 'force_update_woocommerce' ] ) ) { // WPCS: input var ok.
check_admin_referer ( 'wc_force_db_update' , 'wc_force_db_update_nonce' );
2018-05-02 13:28:53 +00:00
$blog_id = get_current_blog_id ();
2018-06-07 12:50:14 +00:00
// Used to fire an action added in WP_Background_Process::_construct() that calls WP_Background_Process::handle_cron_healthcheck().
// This method will make sure the database updates are executed even if cron is disabled. Nothing will happen if the updates are already running.
2018-05-02 13:28:53 +00:00
do_action ( 'wp_' . $blog_id . '_wc_updater_cron' );
2018-06-07 12:50:14 +00:00
2016-06-15 10:07:12 +00:00
wp_safe_redirect ( admin_url ( 'admin.php?page=wc-settings' ) );
2017-02-08 12:22:06 +00:00
exit ;
2016-06-15 10:07:12 +00:00
}
2013-07-25 15:29:25 +00:00
}
/**
2015-11-03 13:31:20 +00:00
* Install WC .
2013-07-25 15:29:25 +00:00
*/
2014-11-25 17:09:19 +00:00
public static function install () {
2016-11-09 11:53:39 +00:00
if ( ! is_blog_installed () ) {
return ;
}
2017-09-27 15:41:26 +00:00
// Check if we are not already running this routine.
if ( 'yes' === get_transient ( 'wc_installing' ) ) {
return ;
2015-01-23 13:29:23 +00:00
}
2015-01-23 13:05:35 +00:00
2017-09-27 15:41:26 +00:00
// If we made it till here nothing is running yet, lets set the transient now.
set_transient ( 'wc_installing' , 'yes' , MINUTE_IN_SECONDS * 10 );
2017-09-05 10:54:17 +00:00
wc_maybe_define_constant ( 'WC_INSTALLING' , true );
2015-01-28 17:50:58 +00:00
2017-09-05 10:54:17 +00:00
self :: remove_admin_notices ();
2014-11-25 17:09:19 +00:00
self :: create_options ();
self :: create_tables ();
self :: create_roles ();
2017-09-05 10:54:17 +00:00
self :: setup_environment ();
self :: create_terms ();
self :: create_cron_jobs ();
self :: create_files ();
self :: maybe_enable_setup_wizard ();
self :: update_wc_version ();
self :: maybe_update_db_version ();
2017-09-27 15:41:26 +00:00
delete_transient ( 'wc_installing' );
2017-09-05 10:54:17 +00:00
do_action ( 'woocommerce_flush_rewrite_rules' );
do_action ( 'woocommerce_installed' );
}
2013-07-25 15:29:25 +00:00
2017-09-05 10:54:17 +00:00
/**
* Reset any notices added to admin .
*
* @ since 3.2 . 0
*/
private static function remove_admin_notices () {
2017-11-23 12:41:31 +00:00
include_once dirname ( __FILE__ ) . '/admin/class-wc-admin-notices.php' ;
2017-09-05 10:54:17 +00:00
WC_Admin_Notices :: remove_all_notices ();
}
2013-07-25 15:29:25 +00:00
2017-09-05 10:54:17 +00:00
/**
* Setup WC environment - post types , taxonomies , endpoints .
*
* @ since 3.2 . 0
*/
private static function setup_environment () {
2014-02-11 00:29:29 +00:00
WC_Post_types :: register_post_types ();
2014-02-05 15:01:30 +00:00
WC_Post_types :: register_taxonomies ();
2014-02-11 00:29:29 +00:00
WC () -> query -> init_query_vars ();
WC () -> query -> add_endpoints ();
2015-03-20 14:20:12 +00:00
WC_API :: add_endpoint ();
2015-04-17 20:41:25 +00:00
WC_Auth :: add_endpoint ();
2017-09-05 10:54:17 +00:00
}
2014-02-11 00:29:29 +00:00
2017-09-05 10:54:17 +00:00
/**
* Is this a brand new WC install ?
*
* @ since 3.2 . 0
* @ return boolean
*/
private static function is_new_install () {
return is_null ( get_option ( 'woocommerce_version' , null ) ) && is_null ( get_option ( 'woocommerce_db_version' , null ) );
}
2013-07-25 15:29:25 +00:00
2017-09-05 10:54:17 +00:00
/**
* Is a DB update needed ?
*
* @ since 3.2 . 0
* @ return boolean
*/
private static function needs_db_update () {
$current_db_version = get_option ( 'woocommerce_db_version' , null );
$updates = self :: get_db_update_callbacks ();
2013-07-25 15:29:25 +00:00
2017-09-05 10:54:17 +00:00
return ! is_null ( $current_db_version ) && version_compare ( $current_db_version , max ( array_keys ( $updates ) ), '<' );
}
2013-07-25 15:29:25 +00:00
2017-09-05 10:54:17 +00:00
/**
* See if we need the wizard or not .
*
* @ since 3.2 . 0
*/
private static function maybe_enable_setup_wizard () {
if ( apply_filters ( 'woocommerce_enable_setup_wizard' , self :: is_new_install () ) ) {
2015-04-29 09:47:57 +00:00
WC_Admin_Notices :: add_notice ( 'install' );
2015-04-29 10:24:29 +00:00
set_transient ( '_wc_activation_redirect' , 1 , 30 );
2014-01-12 00:05:14 +00:00
}
2017-09-05 10:54:17 +00:00
}
2013-07-25 15:29:25 +00:00
2017-09-05 10:54:17 +00:00
/**
* See if we need to show or run database updates during install .
*
* @ since 3.2 . 0
*/
private static function maybe_update_db_version () {
if ( self :: needs_db_update () ) {
2017-09-06 09:49:03 +00:00
if ( apply_filters ( 'woocommerce_enable_auto_update_db' , false ) ) {
2017-09-05 10:54:17 +00:00
self :: init_background_updater ();
self :: update ();
} else {
WC_Admin_Notices :: add_notice ( 'update' );
}
2013-07-25 15:29:25 +00:00
} else {
2015-04-29 09:47:57 +00:00
self :: update_db_version ();
2013-07-25 15:29:25 +00:00
}
}
2015-04-29 09:47:57 +00:00
/**
2015-11-03 13:31:20 +00:00
* Update WC version to current .
2015-04-29 09:47:57 +00:00
*/
private static function update_wc_version () {
delete_option ( 'woocommerce_version' );
add_option ( 'woocommerce_version' , WC () -> version );
}
2016-12-13 13:38:20 +00:00
/**
* Get list of DB update callbacks .
*
2017-03-15 16:36:53 +00:00
* @ since 3.0 . 0
2016-12-13 13:38:20 +00:00
* @ return array
*/
public static function get_db_update_callbacks () {
return self :: $db_updates ;
}
2015-04-29 09:47:57 +00:00
/**
2016-05-11 11:44:23 +00:00
* Push all needed DB updates to the queue for processing .
2013-07-25 15:29:25 +00:00
*/
2014-11-25 17:09:19 +00:00
private static function update () {
2013-07-25 15:29:25 +00:00
$current_db_version = get_option ( 'woocommerce_db_version' );
2016-08-08 12:59:23 +00:00
$logger = wc_get_logger ();
2016-05-11 13:22:42 +00:00
$update_queued = false ;
2015-04-29 09:47:57 +00:00
2016-12-13 13:38:20 +00:00
foreach ( self :: get_db_update_callbacks () as $version => $update_callbacks ) {
2014-11-25 17:09:19 +00:00
if ( version_compare ( $current_db_version , $version , '<' ) ) {
2016-05-11 11:44:23 +00:00
foreach ( $update_callbacks as $update_callback ) {
2016-11-22 18:52:16 +00:00
$logger -> info (
sprintf ( 'Queuing %s - %s' , $version , $update_callback ),
2016-12-21 19:15:19 +00:00
array ( 'source' => 'wc_db_updates' )
2016-11-22 18:52:16 +00:00
);
2016-05-11 11:44:23 +00:00
self :: $background_updater -> push_to_queue ( $update_callback );
2016-05-11 13:22:42 +00:00
$update_queued = true ;
2016-05-11 11:44:23 +00:00
}
2014-01-12 00:05:14 +00:00
}
2014-05-30 17:27:41 +00:00
}
2016-05-11 13:22:42 +00:00
if ( $update_queued ) {
self :: $background_updater -> save () -> dispatch ();
}
2016-05-11 11:44:23 +00:00
}
/**
* Update DB version to current .
2017-11-23 12:41:31 +00:00
*
2017-11-23 13:55:25 +00:00
* @ param string | null $version New WooCommerce DB version or null .
2016-05-11 11:44:23 +00:00
*/
public static function update_db_version ( $version = null ) {
delete_option ( 'woocommerce_db_version' );
add_option ( 'woocommerce_db_version' , is_null ( $version ) ? WC () -> version : $version );
2013-07-25 15:29:25 +00:00
}
2015-09-03 15:21:53 +00:00
/**
2015-11-03 13:31:20 +00:00
* Add more cron schedules .
2017-11-23 12:41:31 +00:00
*
2017-11-23 13:55:25 +00:00
* @ param array $schedules List of WP scheduled cron jobs .
2015-09-03 15:21:53 +00:00
* @ return array
*/
public static function cron_schedules ( $schedules ) {
$schedules [ 'monthly' ] = array (
'interval' => 2635200 ,
2016-08-27 01:46:45 +00:00
'display' => __ ( 'Monthly' , 'woocommerce' ),
2015-09-03 15:21:53 +00:00
);
return $schedules ;
}
2013-07-25 15:29:25 +00:00
/**
2015-11-03 13:31:20 +00:00
* Create cron jobs ( clear them first ) .
2013-07-25 15:29:25 +00:00
*/
2014-11-25 17:09:19 +00:00
private static function create_cron_jobs () {
2013-07-25 15:29:25 +00:00
wp_clear_scheduled_hook ( 'woocommerce_scheduled_sales' );
wp_clear_scheduled_hook ( 'woocommerce_cancel_unpaid_orders' );
wp_clear_scheduled_hook ( 'woocommerce_cleanup_sessions' );
2018-04-30 14:38:45 +00:00
wp_clear_scheduled_hook ( 'woocommerce_cleanup_personal_data' );
2018-05-01 15:37:14 +00:00
wp_clear_scheduled_hook ( 'woocommerce_cleanup_logs' );
2014-12-23 18:49:43 +00:00
wp_clear_scheduled_hook ( 'woocommerce_geoip_updater' );
2015-01-23 16:36:52 +00:00
wp_clear_scheduled_hook ( 'woocommerce_tracker_send_event' );
2013-07-25 15:29:25 +00:00
2017-02-08 12:08:49 +00:00
$ve = get_option ( 'gmt_offset' ) > 0 ? '-' : '+' ;
2013-07-25 15:29:25 +00:00
2017-08-28 19:35:11 +00:00
wp_schedule_event ( strtotime ( '00:00 tomorrow ' . $ve . absint ( get_option ( 'gmt_offset' ) ) . ' HOURS' ), 'daily' , 'woocommerce_scheduled_sales' );
2013-07-25 15:29:25 +00:00
2014-11-25 17:09:19 +00:00
$held_duration = get_option ( 'woocommerce_hold_stock_minutes' , '60' );
2013-07-25 15:29:25 +00:00
2018-03-21 03:06:47 +00:00
if ( '' !== $held_duration ) {
2013-07-25 15:29:25 +00:00
wp_schedule_single_event ( time () + ( absint ( $held_duration ) * 60 ), 'woocommerce_cancel_unpaid_orders' );
2014-01-12 00:05:14 +00:00
}
2013-07-25 15:29:25 +00:00
2018-04-30 14:38:45 +00:00
wp_schedule_event ( time (), 'daily' , 'woocommerce_cleanup_personal_data' );
2018-05-01 15:37:14 +00:00
wp_schedule_event ( time () + ( 3 * HOUR_IN_SECONDS ), 'daily' , 'woocommerce_cleanup_logs' );
wp_schedule_event ( time () + ( 6 * HOUR_IN_SECONDS ), 'twicedaily' , 'woocommerce_cleanup_sessions' );
2014-12-23 18:49:43 +00:00
wp_schedule_event ( strtotime ( 'first tuesday of next month' ), 'monthly' , 'woocommerce_geoip_updater' );
2018-04-24 10:42:06 +00:00
wp_schedule_event ( time () + 10 , apply_filters ( 'woocommerce_tracker_event_recurrence' , 'daily' ), 'woocommerce_tracker_send_event' );
2018-04-24 18:32:27 +00:00
// Trigger GeoLite2 database download after 5 minutes.
wp_schedule_single_event ( time () + ( MINUTE_IN_SECONDS * 5 ), 'woocommerce_geoip_updater' );
2013-07-25 15:29:25 +00:00
}
/**
2017-03-20 15:47:51 +00:00
* Create pages that the plugin relies on , storing page IDs in variables .
2013-07-25 15:29:25 +00:00
*/
2013-11-18 15:56:04 +00:00
public static function create_pages () {
2017-11-23 12:41:31 +00:00
include_once dirname ( __FILE__ ) . '/admin/wc-admin-functions.php' ;
$pages = apply_filters (
'woocommerce_create_pages' , array (
'shop' => array (
'name' => _x ( 'shop' , 'Page slug' , 'woocommerce' ),
'title' => _x ( 'Shop' , 'Page title' , 'woocommerce' ),
'content' => '' ,
),
'cart' => array (
'name' => _x ( 'cart' , 'Page slug' , 'woocommerce' ),
'title' => _x ( 'Cart' , 'Page title' , 'woocommerce' ),
'content' => '[' . apply_filters ( 'woocommerce_cart_shortcode_tag' , 'woocommerce_cart' ) . ']' ,
),
'checkout' => array (
'name' => _x ( 'checkout' , 'Page slug' , 'woocommerce' ),
'title' => _x ( 'Checkout' , 'Page title' , 'woocommerce' ),
'content' => '[' . apply_filters ( 'woocommerce_checkout_shortcode_tag' , 'woocommerce_checkout' ) . ']' ,
),
'myaccount' => array (
'name' => _x ( 'my-account' , 'Page slug' , 'woocommerce' ),
'title' => _x ( 'My account' , 'Page title' , 'woocommerce' ),
'content' => '[' . apply_filters ( 'woocommerce_my_account_shortcode_tag' , 'woocommerce_my_account' ) . ']' ,
),
)
);
2013-07-25 15:29:25 +00:00
2014-01-12 00:05:14 +00:00
foreach ( $pages as $key => $page ) {
2013-11-25 14:07:22 +00:00
wc_create_page ( esc_sql ( $page [ 'name' ] ), 'woocommerce_' . $key . '_page_id' , $page [ 'title' ], $page [ 'content' ], ! empty ( $page [ 'parent' ] ) ? wc_get_page_id ( $page [ 'parent' ] ) : '' );
2014-01-12 00:05:14 +00:00
}
2013-07-25 15:29:25 +00:00
}
/**
2015-11-03 13:31:20 +00:00
* Default options .
2013-07-25 15:29:25 +00:00
*
2015-11-03 13:31:20 +00:00
* Sets up the default options used on the settings page .
2013-07-25 15:29:25 +00:00
*/
2014-11-25 17:09:19 +00:00
private static function create_options () {
2017-11-23 13:55:25 +00:00
// Include settings so that we can run through defaults.
2017-11-23 12:41:31 +00:00
include_once dirname ( __FILE__ ) . '/admin/class-wc-admin-settings.php' ;
2013-07-26 14:36:28 +00:00
$settings = WC_Admin_Settings :: get_settings_pages ();
2013-07-25 15:29:25 +00:00
2013-07-26 14:36:28 +00:00
foreach ( $settings as $section ) {
2014-09-10 16:35:46 +00:00
if ( ! method_exists ( $section , 'get_settings' ) ) {
continue ;
}
2015-01-23 12:36:22 +00:00
$subsections = array_unique ( array_merge ( array ( '' ), array_keys ( $section -> get_sections () ) ) );
2014-09-10 16:35:46 +00:00
2015-01-23 12:36:22 +00:00
foreach ( $subsections as $subsection ) {
foreach ( $section -> get_settings ( $subsection ) as $value ) {
2014-01-11 23:56:29 +00:00
if ( isset ( $value [ 'default' ] ) && isset ( $value [ 'id' ] ) ) {
$autoload = isset ( $value [ 'autoload' ] ) ? ( bool ) $value [ 'autoload' ] : true ;
add_option ( $value [ 'id' ], $value [ 'default' ], '' , ( $autoload ? 'yes' : 'no' ) );
}
}
}
}
2018-05-01 11:15:57 +00:00
// Define other defaults if not in setting screens.
add_option ( 'woocommerce_single_image_width' , '600' , '' , 'yes' );
add_option ( 'woocommerce_thumbnail_image_width' , '300' , '' , 'yes' );
2018-05-03 15:50:26 +00:00
add_option ( 'woocommerce_checkout_highlight_required_fields' , 'yes' , '' , 'yes' );
2018-05-01 11:15:57 +00:00
add_option ( 'woocommerce_demo_store' , 'no' , '' , 'no' );
2013-07-25 15:29:25 +00:00
}
2014-11-25 17:09:19 +00:00
/**
* Add the default terms for WC taxonomies - product types and order statuses . Modify this at your own risk .
*/
2017-03-27 10:55:36 +00:00
public static function create_terms () {
2014-11-25 17:09:19 +00:00
$taxonomies = array (
2017-11-23 12:41:31 +00:00
'product_type' => array (
2014-11-25 17:09:19 +00:00
'simple' ,
'grouped' ,
'variable' ,
2016-08-27 02:08:49 +00:00
'external' ,
2016-08-27 01:46:45 +00:00
),
2016-12-08 10:56:45 +00:00
'product_visibility' => array (
'exclude-from-search' ,
'exclude-from-catalog' ,
'featured' ,
'outofstock' ,
2016-12-09 15:43:25 +00:00
'rated-1' ,
'rated-2' ,
'rated-3' ,
'rated-4' ,
'rated-5' ,
2016-12-08 10:56:45 +00:00
),
2014-11-25 17:09:19 +00:00
);
foreach ( $taxonomies as $taxonomy => $terms ) {
foreach ( $terms as $term ) {
2017-11-23 14:26:34 +00:00
if ( ! get_term_by ( 'name' , $term , $taxonomy ) ) { // @codingStandardsIgnoreLine.
2014-11-25 17:09:19 +00:00
wp_insert_term ( $term , $taxonomy );
}
}
}
2017-11-23 14:26:34 +00:00
2018-03-13 13:12:01 +00:00
$woocommerce_default_category = ( int ) get_option ( 'default_product_cat' , 0 );
2017-11-23 14:26:34 +00:00
2017-11-23 14:38:40 +00:00
if ( ! $woocommerce_default_category || ! term_exists ( $woocommerce_default_category , 'product_cat' ) ) {
$default_product_cat_id = 0 ;
$default_product_cat_slug = sanitize_title ( _x ( 'Uncategorized' , 'Default category slug' , 'woocommerce' ) );
$default_product_cat = get_term_by ( 'slug' , $default_product_cat_slug , 'product_cat' ); // @codingStandardsIgnoreLine.
2017-11-23 14:26:34 +00:00
2017-11-23 14:38:40 +00:00
if ( $default_product_cat ) {
2017-11-23 15:44:17 +00:00
$default_product_cat_id = absint ( $default_product_cat -> term_taxonomy_id );
2017-11-23 14:38:40 +00:00
} else {
$result = wp_insert_term ( _x ( 'Uncategorized' , 'Default category slug' , 'woocommerce' ), 'product_cat' , array ( 'slug' => $default_product_cat_slug ) );
2018-03-13 14:02:55 +00:00
if ( ! is_wp_error ( $result ) && ! empty ( $result [ 'term_taxonomy_id' ] ) ) {
2017-11-23 15:44:17 +00:00
$default_product_cat_id = absint ( $result [ 'term_taxonomy_id' ] );
2017-11-23 14:38:40 +00:00
}
}
if ( $default_product_cat_id ) {
2017-11-23 14:41:17 +00:00
update_option ( 'default_product_cat' , $default_product_cat_id );
2017-11-23 14:26:34 +00:00
}
}
2014-11-25 17:09:19 +00:00
}
2013-07-25 15:29:25 +00:00
/**
* Set up the database tables which the plugin needs to function .
*
* Tables :
2017-11-23 12:41:31 +00:00
* woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined
* woocommerce_termmeta - Term meta table - sadly WordPress does not have termmeta so we need our own
* woocommerce_downloadable_product_permissions - Table for storing user and guest download permissions .
* KEY ( order_id , product_id , download_id ) used for organizing downloads on the My Account page
* woocommerce_order_items - Order line items are stored in a table to make them easily queryable for reports
* woocommerce_order_itemmeta - Order line item meta is stored in a table for storing extra data .
* woocommerce_tax_rates - Tax Rates are stored inside 2 tables making tax queries simple and efficient .
* woocommerce_tax_rate_locations - Each rate can be applied to more than one postcode / city hence the second table .
2013-07-25 15:29:25 +00:00
*/
2014-11-25 17:09:19 +00:00
private static function create_tables () {
2014-06-08 20:33:11 +00:00
global $wpdb ;
2013-07-25 15:29:25 +00:00
$wpdb -> hide_errors ();
2017-11-23 12:41:31 +00:00
require_once ABSPATH . 'wp-admin/includes/upgrade.php' ;
2013-07-25 15:29:25 +00:00
2014-02-13 13:29:55 +00:00
/**
2016-03-11 12:32:43 +00:00
* Before updating with DBDELTA , remove any primary keys which could be
* modified due to schema updates .
2014-02-13 13:29:55 +00:00
*/
if ( $wpdb -> get_var ( " SHOW TABLES LIKE ' { $wpdb -> prefix } woocommerce_downloadable_product_permissions'; " ) ) {
if ( ! $wpdb -> get_var ( " SHOW COLUMNS FROM ` { $wpdb -> prefix } woocommerce_downloadable_product_permissions` LIKE 'permission_id'; " ) ) {
2017-02-13 11:49:30 +00:00
$wpdb -> query ( " ALTER TABLE { $wpdb -> prefix } woocommerce_downloadable_product_permissions DROP PRIMARY KEY, ADD `permission_id` BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT; " );
2014-02-13 13:29:55 +00:00
}
}
2014-11-25 17:09:19 +00:00
dbDelta ( self :: get_schema () );
2016-08-09 08:00:51 +00:00
2017-02-16 16:45:50 +00:00
$index_exists = $wpdb -> get_row ( " SHOW INDEX FROM { $wpdb -> comments } WHERE column_name = 'comment_type' and key_name = 'woo_idx_comment_type' " );
2016-08-09 12:28:41 +00:00
if ( is_null ( $index_exists ) ) {
// Add an index to the field comment_type to improve the response time of the query
// used by WC_Comments::wp_count_comments() to get the number of comments by type.
$wpdb -> query ( " ALTER TABLE { $wpdb -> comments } ADD INDEX woo_idx_comment_type (comment_type) " );
}
2018-04-13 17:03:02 +00:00
2018-06-04 11:21:01 +00:00
// Get tables data types and check it matches before adding constraint.
2018-06-04 11:31:03 +00:00
$download_log_columns = $wpdb -> get_results ( " SHOW COLUMNS FROM { $wpdb -> prefix } wc_download_log WHERE Field = 'permission_id' " , ARRAY_A );
2018-06-04 11:21:01 +00:00
$download_log_column_type = '' ;
if ( isset ( $download_log_columns [ 0 ][ 'Type' ] ) ) {
$download_log_column_type = $download_log_columns [ 0 ][ 'Type' ];
}
2018-06-04 11:10:05 +00:00
2018-06-04 11:31:03 +00:00
$download_permissions_columns = $wpdb -> get_results ( " SHOW COLUMNS FROM { $wpdb -> prefix } woocommerce_downloadable_product_permissions WHERE Field = 'permission_id' " , ARRAY_A );
2018-06-04 11:21:01 +00:00
$download_permissions_column_type = '' ;
if ( isset ( $download_permissions_columns [ 0 ][ 'Type' ] ) ) {
$download_permissions_column_type = $download_permissions_columns [ 0 ][ 'Type' ];
}
2018-06-04 11:10:05 +00:00
2018-06-04 11:21:01 +00:00
// Add constraint to download logs if the columns matches.
if ( ! empty ( $download_permissions_column_type ) && ! empty ( $download_log_column_type ) && $download_permissions_column_type === $download_log_column_type ) {
$wpdb -> query ( " ALTER TABLE { $wpdb -> prefix } wc_download_log ADD FOREIGN KEY (permission_id) REFERENCES { $wpdb -> prefix } woocommerce_downloadable_product_permissions(permission_id) ON DELETE CASCADE " );
2018-06-04 11:10:05 +00:00
}
2014-11-25 17:09:19 +00:00
}
/**
2015-11-03 13:31:20 +00:00
* Get Table schema .
2017-02-15 11:36:41 +00:00
*
2017-11-23 13:55:25 +00:00
* See https :// github . com / woocommerce / woocommerce / wiki / Database - Description /
2017-02-15 11:36:41 +00:00
*
* A note on indexes ; Indexes have a maximum size of 767 bytes . Historically , we haven ' t need to be concerned about that .
* As of WordPress 4.2 , however , we moved to utf8mb4 , which uses 4 bytes per character . This means that an index which
* used to have room for floor ( 767 / 3 ) = 255 characters , now only has room for floor ( 767 / 4 ) = 191 characters .
*
* Changing indexes may cause duplicate index notices in logs due to https :// core . trac . wordpress . org / ticket / 34870 but dropping
* indexes first causes too much load on some servers / larger DB .
*
2018-02-06 13:19:40 +00:00
* When adding or removing a table , make sure to update the list of tables in WC_Install :: get_tables () .
*
2014-11-25 17:09:19 +00:00
* @ return string
*/
private static function get_schema () {
global $wpdb ;
$collate = '' ;
if ( $wpdb -> has_cap ( 'collation' ) ) {
2016-01-27 10:10:56 +00:00
$collate = $wpdb -> get_charset_collate ();
2014-11-25 17:09:19 +00:00
}
2015-11-06 15:33:12 +00:00
$tables = "
2015-10-07 13:47:29 +00:00
CREATE TABLE { $wpdb -> prefix } woocommerce_sessions (
2017-02-13 11:49:30 +00:00
session_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
2015-10-07 13:47:29 +00:00
session_key char ( 32 ) NOT NULL ,
session_value longtext NOT NULL ,
2017-02-13 11:49:30 +00:00
session_expiry BIGINT UNSIGNED NOT NULL ,
2016-10-04 15:26:57 +00:00
PRIMARY KEY ( session_key ),
UNIQUE KEY session_id ( session_id )
2015-10-07 13:47:29 +00:00
) $collate ;
2015-05-15 21:20:49 +00:00
CREATE TABLE { $wpdb -> prefix } woocommerce_api_keys (
2017-02-13 11:49:30 +00:00
key_id BIGINT UNSIGNED NOT NULL auto_increment ,
user_id BIGINT UNSIGNED NOT NULL ,
2017-02-13 14:04:33 +00:00
description varchar ( 200 ) NULL ,
2015-05-16 01:52:00 +00:00
permissions varchar ( 10 ) NOT NULL ,
2015-06-08 23:04:29 +00:00
consumer_key char ( 64 ) NOT NULL ,
consumer_secret char ( 43 ) NOT NULL ,
2015-05-15 21:25:41 +00:00
nonces longtext NULL ,
2015-07-16 18:42:00 +00:00
truncated_key char ( 7 ) NOT NULL ,
last_access datetime NULL default null ,
2015-05-28 13:36:25 +00:00
PRIMARY KEY ( key_id ),
2015-05-15 20:57:18 +00:00
KEY consumer_key ( consumer_key ),
KEY consumer_secret ( consumer_secret )
) $collate ;
2014-11-25 17:09:19 +00:00
CREATE TABLE { $wpdb -> prefix } woocommerce_attribute_taxonomies (
2017-02-13 11:49:30 +00:00
attribute_id BIGINT UNSIGNED NOT NULL auto_increment ,
2014-11-25 17:09:19 +00:00
attribute_name varchar ( 200 ) NOT NULL ,
2017-02-13 14:04:33 +00:00
attribute_label varchar ( 200 ) NULL ,
attribute_type varchar ( 20 ) NOT NULL ,
attribute_orderby varchar ( 20 ) NOT NULL ,
2014-12-19 17:58:49 +00:00
attribute_public int ( 1 ) NOT NULL DEFAULT 1 ,
2014-11-25 17:09:19 +00:00
PRIMARY KEY ( attribute_id ),
2017-02-15 11:36:41 +00:00
KEY attribute_name ( attribute_name ( 20 ))
2014-11-25 17:09:19 +00:00
) $collate ;
CREATE TABLE { $wpdb -> prefix } woocommerce_downloadable_product_permissions (
2017-02-13 11:49:30 +00:00
permission_id BIGINT UNSIGNED NOT NULL auto_increment ,
2017-08-05 04:42:31 +00:00
download_id varchar ( 36 ) NOT NULL ,
2017-02-13 11:49:30 +00:00
product_id BIGINT UNSIGNED NOT NULL ,
order_id BIGINT UNSIGNED NOT NULL DEFAULT 0 ,
2014-11-25 17:09:19 +00:00
order_key varchar ( 200 ) NOT NULL ,
user_email varchar ( 200 ) NOT NULL ,
2017-02-13 11:49:30 +00:00
user_id BIGINT UNSIGNED NULL ,
2014-11-25 17:09:19 +00:00
downloads_remaining varchar ( 9 ) NULL ,
access_granted datetime NOT NULL default '0000-00-00 00:00:00' ,
access_expires datetime NULL default null ,
2017-02-13 11:49:30 +00:00
download_count BIGINT UNSIGNED NOT NULL DEFAULT 0 ,
2014-11-25 17:09:19 +00:00
PRIMARY KEY ( permission_id ),
2017-02-15 11:36:41 +00:00
KEY download_order_key_product ( product_id , order_id , order_key ( 16 ), download_id ),
2017-06-01 18:26:35 +00:00
KEY download_order_product ( download_id , order_id , product_id ),
KEY order_id ( order_id )
2014-11-25 17:09:19 +00:00
) $collate ;
CREATE TABLE { $wpdb -> prefix } woocommerce_order_items (
2017-02-13 11:49:30 +00:00
order_item_id BIGINT UNSIGNED NOT NULL auto_increment ,
2017-02-13 14:04:33 +00:00
order_item_name TEXT NOT NULL ,
2017-03-22 17:09:37 +00:00
order_item_type varchar ( 200 ) NOT NULL DEFAULT '' ,
2017-02-13 11:49:30 +00:00
order_id BIGINT UNSIGNED NOT NULL ,
2014-11-25 17:09:19 +00:00
PRIMARY KEY ( order_item_id ),
KEY order_id ( order_id )
) $collate ;
CREATE TABLE { $wpdb -> prefix } woocommerce_order_itemmeta (
2017-02-13 11:49:30 +00:00
meta_id BIGINT UNSIGNED NOT NULL auto_increment ,
order_item_id BIGINT UNSIGNED NOT NULL ,
2016-03-02 01:28:04 +00:00
meta_key varchar ( 255 ) default NULL ,
2014-11-25 17:09:19 +00:00
meta_value longtext NULL ,
PRIMARY KEY ( meta_id ),
KEY order_item_id ( order_item_id ),
2017-02-15 11:36:41 +00:00
KEY meta_key ( meta_key ( 32 ))
2014-11-25 17:09:19 +00:00
) $collate ;
CREATE TABLE { $wpdb -> prefix } woocommerce_tax_rates (
2017-02-13 11:49:30 +00:00
tax_rate_id BIGINT UNSIGNED NOT NULL auto_increment ,
2017-02-13 14:04:33 +00:00
tax_rate_country varchar ( 2 ) NOT NULL DEFAULT '' ,
2014-11-25 17:09:19 +00:00
tax_rate_state varchar ( 200 ) NOT NULL DEFAULT '' ,
2017-02-13 14:04:33 +00:00
tax_rate varchar ( 8 ) NOT NULL DEFAULT '' ,
2014-11-25 17:09:19 +00:00
tax_rate_name varchar ( 200 ) NOT NULL DEFAULT '' ,
2017-02-13 11:49:30 +00:00
tax_rate_priority BIGINT UNSIGNED NOT NULL ,
2014-11-25 17:09:19 +00:00
tax_rate_compound int ( 1 ) NOT NULL DEFAULT 0 ,
tax_rate_shipping int ( 1 ) NOT NULL DEFAULT 1 ,
2017-02-13 11:49:30 +00:00
tax_rate_order BIGINT UNSIGNED NOT NULL ,
2014-11-25 17:09:19 +00:00
tax_rate_class varchar ( 200 ) NOT NULL DEFAULT '' ,
PRIMARY KEY ( tax_rate_id ),
2017-02-15 11:17:33 +00:00
KEY tax_rate_country ( tax_rate_country ),
2017-02-15 11:36:41 +00:00
KEY tax_rate_state ( tax_rate_state ( 2 )),
KEY tax_rate_class ( tax_rate_class ( 10 )),
2014-11-25 17:09:19 +00:00
KEY tax_rate_priority ( tax_rate_priority )
) $collate ;
CREATE TABLE { $wpdb -> prefix } woocommerce_tax_rate_locations (
2017-02-13 11:49:30 +00:00
location_id BIGINT UNSIGNED NOT NULL auto_increment ,
2017-02-13 14:04:33 +00:00
location_code varchar ( 200 ) NOT NULL ,
2017-02-13 11:49:30 +00:00
tax_rate_id BIGINT UNSIGNED NOT NULL ,
2014-11-25 17:09:19 +00:00
location_type varchar ( 40 ) NOT NULL ,
PRIMARY KEY ( location_id ),
KEY tax_rate_id ( tax_rate_id ),
2017-02-15 11:36:41 +00:00
KEY location_type_code ( location_type ( 10 ), location_code ( 20 ))
2015-12-10 11:55:03 +00:00
) $collate ;
CREATE TABLE { $wpdb -> prefix } woocommerce_shipping_zones (
2017-02-13 11:49:30 +00:00
zone_id BIGINT UNSIGNED NOT NULL auto_increment ,
2017-02-13 14:04:33 +00:00
zone_name varchar ( 200 ) NOT NULL ,
2017-02-13 11:49:30 +00:00
zone_order BIGINT UNSIGNED NOT NULL ,
2015-12-10 11:55:03 +00:00
PRIMARY KEY ( zone_id )
) $collate ;
CREATE TABLE { $wpdb -> prefix } woocommerce_shipping_zone_locations (
2017-02-13 11:49:30 +00:00
location_id BIGINT UNSIGNED NOT NULL auto_increment ,
zone_id BIGINT UNSIGNED NOT NULL ,
2017-02-13 14:04:33 +00:00
location_code varchar ( 200 ) NOT NULL ,
2015-12-10 11:55:03 +00:00
location_type varchar ( 40 ) NOT NULL ,
2016-01-08 13:17:13 +00:00
PRIMARY KEY ( location_id ),
2015-12-11 14:11:12 +00:00
KEY location_id ( location_id ),
2017-02-15 11:36:41 +00:00
KEY location_type_code ( location_type ( 10 ), location_code ( 20 ))
2015-12-11 14:11:12 +00:00
) $collate ;
CREATE TABLE { $wpdb -> prefix } woocommerce_shipping_zone_methods (
2017-02-13 11:49:30 +00:00
zone_id BIGINT UNSIGNED NOT NULL ,
instance_id BIGINT UNSIGNED NOT NULL auto_increment ,
2017-02-13 14:04:33 +00:00
method_id varchar ( 200 ) NOT NULL ,
2017-02-13 11:49:30 +00:00
method_order BIGINT UNSIGNED NOT NULL ,
2016-03-15 17:23:06 +00:00
is_enabled tinyint ( 1 ) NOT NULL DEFAULT '1' ,
2016-01-08 13:17:13 +00:00
PRIMARY KEY ( instance_id )
2016-02-02 17:08:32 +00:00
) $collate ;
2016-02-04 20:11:38 +00:00
CREATE TABLE { $wpdb -> prefix } woocommerce_payment_tokens (
2017-02-13 11:49:30 +00:00
token_id BIGINT UNSIGNED NOT NULL auto_increment ,
2017-02-13 14:04:33 +00:00
gateway_id varchar ( 200 ) NOT NULL ,
2016-02-04 20:11:38 +00:00
token text NOT NULL ,
2017-02-13 11:49:30 +00:00
user_id BIGINT UNSIGNED NOT NULL DEFAULT '0' ,
2017-02-13 14:04:33 +00:00
type varchar ( 200 ) NOT NULL ,
2016-02-04 20:11:38 +00:00
is_default tinyint ( 1 ) NOT NULL DEFAULT '0' ,
PRIMARY KEY ( token_id ),
2016-02-04 20:56:29 +00:00
KEY user_id ( user_id )
2016-02-02 17:08:32 +00:00
) $collate ;
2016-02-04 20:11:38 +00:00
CREATE TABLE { $wpdb -> prefix } woocommerce_payment_tokenmeta (
2017-02-13 11:49:30 +00:00
meta_id BIGINT UNSIGNED NOT NULL auto_increment ,
payment_token_id BIGINT UNSIGNED NOT NULL ,
2016-02-04 20:11:38 +00:00
meta_key varchar ( 255 ) NULL ,
meta_value longtext NULL ,
PRIMARY KEY ( meta_id ),
KEY payment_token_id ( payment_token_id ),
2017-02-15 11:36:41 +00:00
KEY meta_key ( meta_key ( 32 ))
2016-11-20 13:32:46 +00:00
) $collate ;
CREATE TABLE { $wpdb -> prefix } woocommerce_log (
2017-02-13 11:49:30 +00:00
log_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
2016-11-20 13:32:46 +00:00
timestamp datetime NOT NULL ,
2016-12-11 17:59:12 +00:00
level smallint ( 4 ) NOT NULL ,
2017-02-13 14:04:33 +00:00
source varchar ( 200 ) NOT NULL ,
2016-11-20 13:32:46 +00:00
message longtext NOT NULL ,
context longtext NULL ,
PRIMARY KEY ( log_id ),
KEY level ( level )
2017-08-16 18:37:22 +00:00
) $collate ;
2017-08-18 16:41:02 +00:00
CREATE TABLE { $wpdb -> prefix } wc_webhooks (
2017-08-16 18:37:22 +00:00
webhook_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
status varchar ( 200 ) NOT NULL ,
name text NOT NULL ,
user_id BIGINT UNSIGNED NOT NULL ,
delivery_url text NOT NULL ,
secret text NOT NULL ,
topic varchar ( 200 ) NOT NULL ,
2017-08-17 00:48:09 +00:00
date_created datetime NOT NULL DEFAULT '0000-00-00 00:00:00' ,
date_created_gmt datetime NOT NULL DEFAULT '0000-00-00 00:00:00' ,
date_modified datetime NOT NULL DEFAULT '0000-00-00 00:00:00' ,
date_modified_gmt datetime NOT NULL DEFAULT '0000-00-00 00:00:00' ,
2017-08-16 18:37:22 +00:00
api_version smallint ( 4 ) NOT NULL ,
2017-08-17 00:48:09 +00:00
failure_count smallint ( 10 ) NOT NULL DEFAULT '0' ,
2017-08-16 18:37:22 +00:00
pending_delivery tinyint ( 1 ) NOT NULL DEFAULT '0' ,
PRIMARY KEY ( webhook_id ),
KEY user_id ( user_id )
2017-11-15 12:28:14 +00:00
) $collate ;
2017-11-13 19:03:08 +00:00
CREATE TABLE { $wpdb -> prefix } wc_download_log (
2017-07-30 22:38:17 +00:00
download_log_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT ,
timestamp datetime NOT NULL ,
permission_id BIGINT UNSIGNED NOT NULL ,
user_id BIGINT UNSIGNED NULL ,
user_ip_address VARCHAR ( 100 ) NULL DEFAULT '' ,
PRIMARY KEY ( download_log_id ),
KEY permission_id ( permission_id ),
KEY timestamp ( timestamp )
2014-11-25 17:09:19 +00:00
) $collate ;
" ;
2015-11-06 15:33:12 +00:00
2017-02-13 14:04:33 +00:00
/**
* Term meta is only needed for old installs and is now @ deprecated by WordPress term meta .
*/
2016-03-02 18:24:49 +00:00
if ( ! function_exists ( 'get_term_meta' ) ) {
2015-11-06 15:33:12 +00:00
$tables .= "
CREATE TABLE { $wpdb -> prefix } woocommerce_termmeta (
2017-02-13 11:49:30 +00:00
meta_id BIGINT UNSIGNED NOT NULL auto_increment ,
woocommerce_term_id BIGINT UNSIGNED NOT NULL ,
2016-03-02 18:38:39 +00:00
meta_key varchar ( 255 ) default NULL ,
2015-11-06 15:33:12 +00:00
meta_value longtext NULL ,
PRIMARY KEY ( meta_id ),
KEY woocommerce_term_id ( woocommerce_term_id ),
2017-02-15 11:36:41 +00:00
KEY meta_key ( meta_key ( 32 ))
2015-11-06 15:33:12 +00:00
) $collate ;
" ;
}
return $tables ;
2013-07-25 15:29:25 +00:00
}
2018-02-06 13:19:40 +00:00
/**
* Return a list of WooCommerce tables . Used to make sure all WC 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 ;
$tables = array (
" { $wpdb -> prefix } wc_download_log " ,
" { $wpdb -> prefix } wc_webhooks " ,
" { $wpdb -> prefix } woocommerce_api_keys " ,
" { $wpdb -> prefix } woocommerce_attribute_taxonomies " ,
" { $wpdb -> prefix } woocommerce_downloadable_product_permissions " ,
" { $wpdb -> prefix } woocommerce_log " ,
" { $wpdb -> prefix } woocommerce_order_itemmeta " ,
" { $wpdb -> prefix } woocommerce_order_items " ,
" { $wpdb -> prefix } woocommerce_payment_tokenmeta " ,
" { $wpdb -> prefix } woocommerce_payment_tokens " ,
" { $wpdb -> prefix } woocommerce_sessions " ,
" { $wpdb -> prefix } woocommerce_shipping_zone_locations " ,
" { $wpdb -> prefix } woocommerce_shipping_zone_methods " ,
" { $wpdb -> prefix } woocommerce_shipping_zones " ,
" { $wpdb -> prefix } woocommerce_tax_rate_locations " ,
" { $wpdb -> prefix } woocommerce_tax_rates " ,
);
if ( ! function_exists ( 'get_term_meta' ) ) {
// This table is only needed for old installs and is now @deprecated by WordPress term meta.
$tables [] = " { $wpdb -> prefix } woocommerce_termmeta " ;
}
2018-03-16 18:54:17 +00:00
/**
* Filter the list of known WooCommerce tables .
*
* If WooCommerce plugins need to add new tables , they can inject them here .
*
* @ param array $tables An array of WooCommerce - specific database table names .
*/
$tables = apply_filters ( 'woocommerce_install_get_tables' , $tables );
2018-02-06 13:19:40 +00:00
return $tables ;
}
/**
* Drop WooCommerce tables .
*
* @ return void
*/
public static function drop_tables () {
global $wpdb ;
$tables = self :: get_tables ();
foreach ( $tables as $table ) {
$wpdb -> query ( " DROP TABLE IF EXISTS { $table } " ); // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared
}
}
/**
* 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 () );
}
2013-07-25 15:29:25 +00:00
/**
2015-11-03 13:31:20 +00:00
* Create roles and capabilities .
2013-07-25 15:29:25 +00:00
*/
2014-11-25 17:09:19 +00:00
public static function create_roles () {
2013-07-25 15:29:25 +00:00
global $wp_roles ;
2014-11-25 17:09:19 +00:00
if ( ! class_exists ( 'WP_Roles' ) ) {
return ;
2014-01-12 00:05:14 +00:00
}
2013-07-25 15:29:25 +00:00
2014-11-25 17:09:19 +00:00
if ( ! isset ( $wp_roles ) ) {
2017-11-23 13:55:25 +00:00
$wp_roles = new WP_Roles (); // @codingStandardsIgnoreLine
2014-11-25 17:09:19 +00:00
}
2018-04-30 14:38:45 +00:00
// Dummy gettext calls to get strings in the catalog.
/* translators: user role */
_x ( 'Customer' , 'User role' , 'woocommerce' );
/* translators: user role */
_x ( 'Shop manager' , 'User role' , 'woocommerce' );
2017-11-23 13:55:25 +00:00
// Customer role.
2017-11-23 12:41:31 +00:00
add_role (
'customer' ,
2018-04-30 14:38:45 +00:00
'Customer' ,
2017-11-23 12:41:31 +00:00
array (
'read' => true ,
)
);
2014-11-25 17:09:19 +00:00
2017-11-23 13:55:25 +00:00
// Shop manager role.
2017-11-23 12:41:31 +00:00
add_role (
'shop_manager' ,
2018-04-30 14:38:45 +00:00
'Shop manager' ,
2017-11-23 12:41:31 +00:00
array (
'level_9' => true ,
'level_8' => true ,
'level_7' => true ,
'level_6' => true ,
'level_5' => true ,
'level_4' => true ,
'level_3' => true ,
'level_2' => true ,
'level_1' => true ,
'level_0' => true ,
'read' => true ,
'read_private_pages' => true ,
'read_private_posts' => true ,
'edit_users' => true ,
'edit_posts' => true ,
'edit_pages' => true ,
'edit_published_posts' => true ,
'edit_published_pages' => true ,
'edit_private_pages' => true ,
'edit_private_posts' => true ,
'edit_others_posts' => true ,
'edit_others_pages' => true ,
'publish_posts' => true ,
'publish_pages' => true ,
'delete_posts' => true ,
'delete_pages' => true ,
'delete_private_pages' => true ,
'delete_private_posts' => true ,
'delete_published_pages' => true ,
'delete_published_posts' => true ,
'delete_others_posts' => true ,
'delete_others_pages' => true ,
'manage_categories' => true ,
'manage_links' => true ,
'moderate_comments' => true ,
'upload_files' => true ,
'export' => true ,
'import' => true ,
'list_users' => true ,
)
);
2014-11-25 17:09:19 +00:00
$capabilities = self :: get_core_capabilities ();
foreach ( $capabilities as $cap_group ) {
foreach ( $cap_group as $cap ) {
$wp_roles -> add_cap ( 'shop_manager' , $cap );
$wp_roles -> add_cap ( 'administrator' , $cap );
2013-07-25 15:29:25 +00:00
}
}
}
2013-08-09 16:11:15 +00:00
/**
2015-11-03 13:31:20 +00:00
* Get capabilities for WooCommerce - these are assigned to admin / shop manager during installation or reset .
2013-08-09 16:11:15 +00:00
*
2013-11-27 09:03:47 +00:00
* @ return array
2013-08-09 16:11:15 +00:00
*/
2017-11-23 12:41:31 +00:00
private static function get_core_capabilities () {
2013-08-09 16:11:15 +00:00
$capabilities = array ();
$capabilities [ 'core' ] = array (
2014-01-12 00:05:14 +00:00
'manage_woocommerce' ,
2016-08-27 02:08:49 +00:00
'view_woocommerce_reports' ,
2013-08-09 16:11:15 +00:00
);
2017-08-17 14:37:57 +00:00
$capability_types = array ( 'product' , 'shop_order' , 'shop_coupon' );
2013-08-09 16:11:15 +00:00
2014-01-12 00:05:14 +00:00
foreach ( $capability_types as $capability_type ) {
2013-08-09 16:11:15 +00:00
$capabilities [ $capability_type ] = array (
2017-11-23 13:55:25 +00:00
// Post type.
2013-08-09 16:11:15 +00:00
" edit_ { $capability_type } " ,
" read_ { $capability_type } " ,
" delete_ { $capability_type } " ,
" edit_ { $capability_type } s " ,
" edit_others_ { $capability_type } s " ,
" publish_ { $capability_type } s " ,
" read_private_ { $capability_type } s " ,
" delete_ { $capability_type } s " ,
" delete_private_ { $capability_type } s " ,
" delete_published_ { $capability_type } s " ,
" delete_others_ { $capability_type } s " ,
" edit_private_ { $capability_type } s " ,
" edit_published_ { $capability_type } s " ,
2017-11-23 13:55:25 +00:00
// Terms.
2013-08-09 16:11:15 +00:00
" manage_ { $capability_type } _terms " ,
" edit_ { $capability_type } _terms " ,
" delete_ { $capability_type } _terms " ,
2016-08-27 02:08:49 +00:00
" assign_ { $capability_type } _terms " ,
2013-08-09 16:11:15 +00:00
);
}
return $capabilities ;
}
/**
2017-11-23 13:55:25 +00:00
* Remove WooCommerce roles .
2013-08-09 16:11:15 +00:00
*/
2014-11-25 17:09:19 +00:00
public static function remove_roles () {
2013-08-09 16:11:15 +00:00
global $wp_roles ;
2014-11-25 17:09:19 +00:00
if ( ! class_exists ( 'WP_Roles' ) ) {
return ;
2014-01-12 00:05:14 +00:00
}
2013-08-09 16:11:15 +00:00
2014-11-25 17:09:19 +00:00
if ( ! isset ( $wp_roles ) ) {
2017-11-23 13:55:25 +00:00
$wp_roles = new WP_Roles (); // @codingStandardsIgnoreLine
2014-11-25 17:09:19 +00:00
}
2013-08-09 16:11:15 +00:00
2014-11-25 17:09:19 +00:00
$capabilities = self :: get_core_capabilities ();
2013-08-09 16:11:15 +00:00
2014-11-25 17:09:19 +00:00
foreach ( $capabilities as $cap_group ) {
foreach ( $cap_group as $cap ) {
$wp_roles -> remove_cap ( 'shop_manager' , $cap );
$wp_roles -> remove_cap ( 'administrator' , $cap );
2013-08-09 16:11:15 +00:00
}
}
2014-11-25 17:09:19 +00:00
remove_role ( 'customer' );
remove_role ( 'shop_manager' );
2013-08-09 16:11:15 +00:00
}
2013-07-25 15:29:25 +00:00
/**
2015-11-03 13:31:20 +00:00
* Create files / directories .
2013-07-25 15:29:25 +00:00
*/
2014-11-25 17:09:19 +00:00
private static function create_files () {
2017-11-23 13:55:25 +00:00
// Bypass if filesystem is read-only and/or non-standard upload system is used.
2017-08-25 04:16:32 +00:00
if ( apply_filters ( 'woocommerce_install_skip_create_files' , false ) ) {
return ;
}
2017-11-23 13:55:25 +00:00
// Install files and folders for uploading files and prevent hotlinking.
2015-08-24 12:50:14 +00:00
$upload_dir = wp_upload_dir ();
$download_method = get_option ( 'woocommerce_file_download_method' , 'force' );
2013-07-25 15:29:25 +00:00
$files = array (
array (
2017-11-23 12:41:31 +00:00
'base' => $upload_dir [ 'basedir' ] . '/woocommerce_uploads' ,
'file' => 'index.html' ,
'content' => '' ,
2013-07-25 15:29:25 +00:00
),
array (
2017-11-23 12:41:31 +00:00
'base' => WC_LOG_DIR ,
'file' => '.htaccess' ,
'content' => 'deny from all' ,
2013-07-25 15:29:25 +00:00
),
array (
2017-11-23 12:41:31 +00:00
'base' => WC_LOG_DIR ,
'file' => 'index.html' ,
'content' => '' ,
2016-08-27 02:08:49 +00:00
),
2013-07-25 15:29:25 +00:00
);
2015-08-24 12:50:14 +00:00
if ( 'redirect' !== $download_method ) {
$files [] = array (
2017-11-23 12:41:31 +00:00
'base' => $upload_dir [ 'basedir' ] . '/woocommerce_uploads' ,
'file' => '.htaccess' ,
'content' => 'deny from all' ,
2015-08-24 12:50:14 +00:00
);
}
2013-07-25 15:29:25 +00:00
foreach ( $files as $file ) {
if ( wp_mkdir_p ( $file [ 'base' ] ) && ! file_exists ( trailingslashit ( $file [ 'base' ] ) . $file [ 'file' ] ) ) {
2018-03-21 03:06:47 +00:00
$file_handle = @ fopen ( trailingslashit ( $file [ 'base' ] ) . $file [ 'file' ], 'w' ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen
2017-11-23 13:55:25 +00:00
if ( $file_handle ) {
2018-03-21 03:06:47 +00:00
fwrite ( $file_handle , $file [ 'content' ] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fwrite
fclose ( $file_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose
2013-07-25 15:29:25 +00:00
}
}
}
}
2014-08-29 17:34:01 +00:00
/**
2014-08-29 17:43:06 +00:00
* Show action links on the plugin screen .
2014-08-29 17:34:01 +00:00
*
2017-11-23 13:55:25 +00:00
* @ param mixed $links Plugin Action links .
2017-11-23 12:41:31 +00:00
* @ return array
2014-08-29 17:34:01 +00:00
*/
2014-11-25 17:09:19 +00:00
public static function plugin_action_links ( $links ) {
2014-08-29 19:05:09 +00:00
$action_links = array (
2017-03-13 05:39:46 +00:00
'settings' => '<a href="' . admin_url ( 'admin.php?page=wc-settings' ) . '" aria-label="' . esc_attr__ ( 'View WooCommerce settings' , 'woocommerce' ) . '">' . esc_html__ ( 'Settings' , 'woocommerce' ) . '</a>' ,
2014-08-29 19:05:09 +00:00
);
2014-08-29 17:43:06 +00:00
return array_merge ( $action_links , $links );
2014-08-29 17:34:01 +00:00
}
2014-08-29 17:54:17 +00:00
/**
* Show row meta on the plugin screen .
*
2017-11-23 13:55:25 +00:00
* @ param mixed $links Plugin Row Meta .
* @ param mixed $file Plugin Base file .
2017-11-23 12:41:31 +00:00
* @ return array
2014-08-29 17:54:17 +00:00
*/
2014-11-25 17:09:19 +00:00
public static function plugin_row_meta ( $links , $file ) {
2018-03-21 03:06:47 +00:00
if ( WC_PLUGIN_BASENAME === $file ) {
2014-08-29 19:04:25 +00:00
$row_meta = array (
2017-03-13 05:39:46 +00:00
'docs' => '<a href="' . esc_url ( apply_filters ( 'woocommerce_docs_url' , 'https://docs.woocommerce.com/documentation/plugins/woocommerce/' ) ) . '" aria-label="' . esc_attr__ ( 'View WooCommerce documentation' , 'woocommerce' ) . '">' . esc_html__ ( 'Docs' , 'woocommerce' ) . '</a>' ,
'apidocs' => '<a href="' . esc_url ( apply_filters ( 'woocommerce_apidocs_url' , 'https://docs.woocommerce.com/wc-apidocs/' ) ) . '" aria-label="' . esc_attr__ ( 'View WooCommerce API docs' , 'woocommerce' ) . '">' . esc_html__ ( 'API docs' , 'woocommerce' ) . '</a>' ,
'support' => '<a href="' . esc_url ( apply_filters ( 'woocommerce_support_url' , 'https://woocommerce.com/my-account/tickets/' ) ) . '" aria-label="' . esc_attr__ ( 'Visit premium customer support' , 'woocommerce' ) . '">' . esc_html__ ( 'Premium support' , 'woocommerce' ) . '</a>' ,
2014-08-29 19:04:25 +00:00
);
2014-08-29 17:54:17 +00:00
return array_merge ( $links , $row_meta );
}
return ( array ) $links ;
}
2014-10-10 13:48:08 +00:00
2016-04-18 16:05:19 +00:00
/**
2018-02-16 20:01:05 +00:00
* Get slug from path and associate it with the path .
2017-11-23 12:41:31 +00:00
*
2018-04-16 11:16:59 +00:00
* @ param array $plugins Associative array of plugin files to paths .
2018-02-16 20:01:05 +00:00
* @ param string $key Plugin relative path . Example : woocommerce / woocommerce . php .
2016-04-18 16:05:19 +00:00
*/
2018-04-16 11:16:59 +00:00
private static function associate_plugin_file ( $plugins , $key ) {
2018-05-07 12:27:22 +00:00
$path = explode ( '/' , $key );
2018-05-07 18:48:18 +00:00
$filename = end ( $path );
2018-05-07 12:27:22 +00:00
$plugins [ $filename ] = $key ;
2018-02-16 20:01:05 +00:00
return $plugins ;
2016-04-18 16:05:19 +00:00
}
/**
* Install a plugin from . org in the background via a cron job ( used by
* installer - opt in ) .
2017-11-23 12:41:31 +00:00
*
2017-11-23 13:55:25 +00:00
* @ param string $plugin_to_install_id Plugin ID .
* @ param array $plugin_to_install Plugin information .
* @ throws Exception If unable to proceed with plugin installation .
2016-04-18 16:05:19 +00:00
* @ since 2.6 . 0
*/
public static function background_installer ( $plugin_to_install_id , $plugin_to_install ) {
2016-12-12 12:02:03 +00:00
// Explicitly clear the event.
wp_clear_scheduled_hook ( 'woocommerce_plugin_background_installer' , func_get_args () );
2016-04-18 16:05:19 +00:00
if ( ! empty ( $plugin_to_install [ 'repo-slug' ] ) ) {
2017-11-23 12:41:31 +00:00
require_once ABSPATH . 'wp-admin/includes/file.php' ;
require_once ABSPATH . 'wp-admin/includes/plugin-install.php' ;
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ;
require_once ABSPATH . 'wp-admin/includes/plugin.php' ;
2016-04-18 16:05:19 +00:00
WP_Filesystem ();
2017-11-23 12:41:31 +00:00
$skin = new Automatic_Upgrader_Skin ();
2016-04-18 16:05:19 +00:00
$upgrader = new WP_Upgrader ( $skin );
2018-04-16 11:16:59 +00:00
$installed_plugins = array_reduce ( array_keys ( get_plugins () ), array ( __CLASS__ , 'associate_plugin_file' ), array () );
2016-04-18 16:05:19 +00:00
$plugin_slug = $plugin_to_install [ 'repo-slug' ];
2018-04-16 11:16:59 +00:00
$plugin_file = isset ( $plugin_to_install [ 'file' ] ) ? $plugin_to_install [ 'file' ] : $plugin_slug . '.php' ;
2016-04-18 16:05:19 +00:00
$installed = false ;
$activate = false ;
2017-11-23 13:55:25 +00:00
// See if the plugin is installed already.
2018-04-16 11:16:59 +00:00
if ( isset ( $installed_plugins [ $plugin_file ] ) ) {
2016-04-18 16:05:19 +00:00
$installed = true ;
2018-04-16 11:16:59 +00:00
$activate = ! is_plugin_active ( $installed_plugins [ $plugin_file ] );
2016-04-18 16:05:19 +00:00
}
// Install this thing!
if ( ! $installed ) {
2017-11-23 13:55:25 +00:00
// Suppress feedback.
2016-04-18 16:05:19 +00:00
ob_start ();
try {
2017-11-23 12:41:31 +00:00
$plugin_information = plugins_api (
'plugin_information' ,
array (
2018-04-16 11:16:59 +00:00
'slug' => $plugin_slug ,
2017-11-23 12:41:31 +00:00
'fields' => array (
'short_description' => false ,
'sections' => false ,
'requires' => false ,
'rating' => false ,
'ratings' => false ,
'downloaded' => false ,
'last_updated' => false ,
'added' => false ,
'tags' => false ,
'homepage' => false ,
'donate_link' => false ,
'author_profile' => false ,
'author' => false ,
),
)
);
2016-04-18 16:05:19 +00:00
if ( is_wp_error ( $plugin_information ) ) {
throw new Exception ( $plugin_information -> get_error_message () );
}
$package = $plugin_information -> download_link ;
$download = $upgrader -> download_package ( $package );
if ( is_wp_error ( $download ) ) {
throw new Exception ( $download -> get_error_message () );
}
$working_dir = $upgrader -> unpack_package ( $download , true );
if ( is_wp_error ( $working_dir ) ) {
throw new Exception ( $working_dir -> get_error_message () );
}
2017-11-23 12:41:31 +00:00
$result = $upgrader -> install_package (
array (
'source' => $working_dir ,
'destination' => WP_PLUGIN_DIR ,
'clear_destination' => false ,
'abort_if_destination_exists' => false ,
'clear_working' => true ,
'hook_extra' => array (
'type' => 'plugin' ,
'action' => 'install' ,
),
)
);
2016-04-18 16:05:19 +00:00
if ( is_wp_error ( $result ) ) {
throw new Exception ( $result -> get_error_message () );
}
$activate = true ;
} catch ( Exception $e ) {
WC_Admin_Notices :: add_custom_notice (
$plugin_to_install_id . '_install_error' ,
sprintf (
2017-11-23 13:55:25 +00:00
// translators: 1: plugin name, 2: error message, 3: URL to install plugin manually.
2016-10-27 17:36:24 +00:00
__ ( '%1$s could not be installed (%2$s). <a href="%3$s">Please install it manually by clicking here.</a>' , 'woocommerce' ),
2016-04-18 16:05:19 +00:00
$plugin_to_install [ 'name' ],
$e -> getMessage (),
2018-04-16 11:16:59 +00:00
esc_url ( admin_url ( 'index.php?wc-install-plugin-redirect=' . $plugin_slug ) )
2016-04-18 16:05:19 +00:00
)
);
}
2017-11-23 13:55:25 +00:00
// Discard feedback.
2016-04-18 16:05:19 +00:00
ob_end_clean ();
}
wp_clean_plugins_cache ();
2017-11-23 13:55:25 +00:00
// Activate this thing.
2016-04-18 16:05:19 +00:00
if ( $activate ) {
try {
2018-04-16 11:22:15 +00:00
$result = activate_plugin ( $installed ? $installed_plugins [ $plugin_file ] : $plugin_slug . '/' . $plugin_file );
2016-04-18 16:05:19 +00:00
if ( is_wp_error ( $result ) ) {
throw new Exception ( $result -> get_error_message () );
}
} catch ( Exception $e ) {
WC_Admin_Notices :: add_custom_notice (
$plugin_to_install_id . '_install_error' ,
sprintf (
2017-11-23 13:55:25 +00:00
// translators: 1: plugin name, 2: URL to WP plugin page.
2016-10-27 17:36:24 +00:00
__ ( '%1$s was installed but could not be activated. <a href="%2$s">Please activate it manually by clicking here.</a>' , 'woocommerce' ),
2016-04-18 16:05:19 +00:00
$plugin_to_install [ 'name' ],
2016-10-27 17:36:24 +00:00
admin_url ( 'plugins.php' )
2016-04-18 16:05:19 +00:00
)
);
}
}
}
}
2017-05-17 16:42:18 +00:00
/**
* Install a theme from . org in the background via a cron job ( used by installer - opt in ) .
*
2017-11-23 13:55:25 +00:00
* @ param string $theme_slug Theme slug .
* @ throws Exception If unable to proceed with theme installation .
2017-05-17 16:42:18 +00:00
* @ since 3.1 . 0
*/
public static function theme_background_installer ( $theme_slug ) {
// Explicitly clear the event.
wp_clear_scheduled_hook ( 'woocommerce_theme_background_installer' , func_get_args () );
if ( ! empty ( $theme_slug ) ) {
2017-11-23 13:55:25 +00:00
// Suppress feedback.
2017-05-17 16:42:18 +00:00
ob_start ();
try {
$theme = wp_get_theme ( $theme_slug );
if ( ! $theme -> exists () ) {
2017-11-23 12:41:31 +00:00
require_once ABSPATH . 'wp-admin/includes/file.php' ;
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ;
include_once ABSPATH . 'wp-admin/includes/theme.php' ;
2017-05-17 16:42:18 +00:00
WP_Filesystem ();
2017-11-23 12:41:31 +00:00
$skin = new Automatic_Upgrader_Skin ();
2017-05-17 16:42:18 +00:00
$upgrader = new Theme_Upgrader ( $skin );
2017-11-23 12:41:31 +00:00
$api = themes_api (
'theme_information' , array (
'slug' => $theme_slug ,
'fields' => array ( 'sections' => false ),
)
);
2017-05-17 16:42:18 +00:00
$result = $upgrader -> install ( $api -> download_link );
if ( is_wp_error ( $result ) ) {
throw new Exception ( $result -> get_error_message () );
} elseif ( is_wp_error ( $skin -> result ) ) {
throw new Exception ( $skin -> result -> get_error_message () );
} elseif ( is_null ( $result ) ) {
throw new Exception ( 'Unable to connect to the filesystem. Please confirm your credentials.' );
}
}
switch_theme ( $theme_slug );
} catch ( Exception $e ) {
WC_Admin_Notices :: add_custom_notice (
$theme_slug . '_install_error' ,
sprintf (
2017-11-23 13:55:25 +00:00
// translators: 1: theme slug, 2: error message, 3: URL to install theme manually.
2017-05-17 16:42:18 +00:00
__ ( '%1$s could not be installed (%2$s). <a href="%3$s">Please install it manually by clicking here.</a>' , 'woocommerce' ),
$theme_slug ,
$e -> getMessage (),
2017-05-23 15:35:17 +00:00
esc_url ( admin_url ( 'update.php?action=install-theme&theme=' . $theme_slug . '&_wpnonce=' . wp_create_nonce ( 'install-theme_' . $theme_slug ) ) )
2017-05-17 16:42:18 +00:00
)
);
}
2017-11-23 13:55:25 +00:00
// Discard feedback.
2017-05-17 16:42:18 +00:00
ob_end_clean ();
}
}
2013-07-25 15:29:25 +00:00
}
2014-11-25 17:09:19 +00:00
WC_Install :: init ();