Table creation validation for install routine (https://github.com/woocommerce/woocommerce-blocks/pull/2287)
* Bump package version for testing * New install routine and db version * Revert "Bump package version for testing" This reverts commit c3fee55a34e75429b731cd7a2cc07e841010df6d. * Update bootstrap to ensure blocks is installed properly before tests are ran * Restore errors after install * Use enabled method instead of comparing db version * Moved installer code to admin_init * Tweak test bootstrap
This commit is contained in:
parent
ad93ddd891
commit
a58420a60e
|
@ -12,6 +12,7 @@ use Automattic\WooCommerce\Blocks\Assets\Api as AssetApi;
|
|||
use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry;
|
||||
use Automattic\WooCommerce\Blocks\Assets\BackCompatAssetDataRegistry;
|
||||
use Automattic\WooCommerce\Blocks\Library;
|
||||
use Automattic\WooCommerce\Blocks\Installer;
|
||||
use Automattic\WooCommerce\Blocks\Registry\Container;
|
||||
use Automattic\WooCommerce\Blocks\RestApi;
|
||||
use Automattic\WooCommerce\Blocks\Payments\Api as PaymentsApi;
|
||||
|
@ -73,6 +74,7 @@ class Bootstrap {
|
|||
$this->add_build_notice();
|
||||
$this->define_feature_flag();
|
||||
$this->container->get( AssetDataRegistry::class );
|
||||
$this->container->get( Installer::class );
|
||||
BlockAssets::init();
|
||||
}
|
||||
|
||||
|
@ -182,6 +184,12 @@ class Bootstrap {
|
|||
return new RestApi();
|
||||
}
|
||||
);
|
||||
$this->container->register(
|
||||
Installer::class,
|
||||
function ( Container $container ) {
|
||||
return new Installer();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
/**
|
||||
* Handles installation of Blocks plugin dependencies.
|
||||
*
|
||||
* @package WooCommerce/Blocks
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Blocks;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Installer class.
|
||||
*/
|
||||
class Installer {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Installation tasks ran on admin_init callback.
|
||||
*/
|
||||
public function install() {
|
||||
$this->maybe_create_tables();
|
||||
$this->maybe_create_cronjobs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize class features.
|
||||
*/
|
||||
protected function init() {
|
||||
add_action( 'admin_init', array( $this, 'install' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the database tables which the plugin needs to function.
|
||||
*/
|
||||
public function maybe_create_tables() {
|
||||
global $wpdb;
|
||||
|
||||
$schema_version = 260;
|
||||
$db_schema_version = (int) get_option( 'wc_blocks_db_schema_version', 0 );
|
||||
|
||||
if ( $db_schema_version > $schema_version ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$show_errors = $wpdb->hide_errors();
|
||||
$table_name = $wpdb->prefix . 'wc_reserved_stock';
|
||||
$collate = $wpdb->has_cap( 'collation' ) ? $wpdb->get_charset_collate() : '';
|
||||
$exists = $this->maybe_create_table(
|
||||
$wpdb->prefix . 'wc_reserved_stock',
|
||||
"
|
||||
CREATE TABLE {$wpdb->prefix}wc_reserved_stock (
|
||||
`order_id` bigint(20) NOT NULL,
|
||||
`product_id` bigint(20) NOT NULL,
|
||||
`stock_quantity` double NOT NULL DEFAULT 0,
|
||||
`timestamp` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`expires` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`order_id`, `product_id`)
|
||||
) $collate;
|
||||
"
|
||||
);
|
||||
|
||||
if ( $show_errors ) {
|
||||
$wpdb->show_errors();
|
||||
}
|
||||
|
||||
if ( ! $exists ) {
|
||||
return $this->add_create_table_notice( $table_name );
|
||||
}
|
||||
|
||||
// Update succeeded. This is only updated when successful and validated.
|
||||
// $schema_version should be incremented when changes to schema are made within this method.
|
||||
update_option( 'wc_blocks_db_schema_version', $schema_version );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create database table, if it doesn't already exist.
|
||||
*
|
||||
* Based on admin/install-helper.php maybe_create_table function.
|
||||
*
|
||||
* @param string $table_name Database table name.
|
||||
* @param string $create_sql Create database table SQL.
|
||||
* @return bool False on error, true if already exists or success.
|
||||
*/
|
||||
protected function maybe_create_table( $table_name, $create_sql ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( in_array( $table_name, $wpdb->get_col( 'SHOW TABLES', 0 ), true ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$wpdb->query( $create_sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
|
||||
return in_array( $table_name, $wpdb->get_col( 'SHOW TABLES', 0 ), true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a notice if table creation fails.
|
||||
*
|
||||
* @param string $table_name Name of the missing table.
|
||||
*/
|
||||
protected function add_create_table_notice( $table_name ) {
|
||||
add_action(
|
||||
'admin_notices',
|
||||
function() use ( $table_name ) {
|
||||
echo '<div class="error"><p>';
|
||||
printf(
|
||||
/* Translators: %1$s table name, %2$s database user, %3$s database name. */
|
||||
esc_html__( 'WooCommerce %1$s table creation failed. Does the %2$s user have CREATE privileges on the %3$s database?', 'woo-gutenberg-products-block' ),
|
||||
'<code>' . esc_html( $table_name ) . '</code>',
|
||||
'<code>' . esc_html( DB_USER ) . '</code>',
|
||||
'<code>' . esc_html( DB_NAME ) . '</code>'
|
||||
);
|
||||
echo '</p></div>';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe create cron events.
|
||||
*/
|
||||
protected function maybe_create_cronjobs() {
|
||||
if ( function_exists( 'as_next_scheduled_action' ) && false === as_next_scheduled_action( 'woocommerce_cleanup_draft_orders' ) ) {
|
||||
as_schedule_recurring_action( strtotime( 'midnight tonight' ), DAY_IN_SECONDS, 'woocommerce_cleanup_draft_orders' );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,8 +20,6 @@ class Library {
|
|||
public static function init() {
|
||||
add_action( 'init', array( __CLASS__, 'register_blocks' ) );
|
||||
add_action( 'init', array( __CLASS__, 'define_tables' ) );
|
||||
add_action( 'init', array( __CLASS__, 'maybe_create_tables' ) );
|
||||
add_action( 'init', array( __CLASS__, 'maybe_create_cronjobs' ) );
|
||||
add_filter( 'wc_order_statuses', array( __CLASS__, 'register_draft_order_status' ) );
|
||||
add_filter( 'woocommerce_register_shop_order_post_statuses', array( __CLASS__, 'register_draft_order_post_status' ) );
|
||||
add_filter( 'woocommerce_valid_order_statuses_for_payment', array( __CLASS__, 'append_draft_order_post_status' ) );
|
||||
|
@ -45,52 +43,6 @@ class Library {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the database tables which the plugin needs to function.
|
||||
*/
|
||||
public static function maybe_create_tables() {
|
||||
$db_version = get_option( 'wc_blocks_db_version', 0 );
|
||||
|
||||
if ( version_compare( $db_version, \Automattic\WooCommerce\Blocks\Package::get_version(), '>=' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
||||
|
||||
$wpdb->hide_errors();
|
||||
$collate = '';
|
||||
|
||||
if ( $wpdb->has_cap( 'collation' ) ) {
|
||||
$collate = $wpdb->get_charset_collate();
|
||||
}
|
||||
|
||||
dbDelta(
|
||||
"
|
||||
CREATE TABLE {$wpdb->prefix}wc_reserved_stock (
|
||||
`order_id` bigint(20) NOT NULL,
|
||||
`product_id` bigint(20) NOT NULL,
|
||||
`stock_quantity` double NOT NULL DEFAULT 0,
|
||||
`timestamp` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`expires` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`order_id`, `product_id`)
|
||||
) $collate;
|
||||
"
|
||||
);
|
||||
|
||||
update_option( 'wc_blocks_db_version', \Automattic\WooCommerce\Blocks\Package::get_version() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe create cron events.
|
||||
*/
|
||||
public static function maybe_create_cronjobs() {
|
||||
if ( function_exists( 'as_next_scheduled_action' ) && false === as_next_scheduled_action( 'woocommerce_cleanup_draft_orders' ) ) {
|
||||
as_schedule_recurring_action( strtotime( 'midnight tonight' ), DAY_IN_SECONDS, 'woocommerce_cleanup_draft_orders' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register blocks, hooking up assets and render functions as needed.
|
||||
*/
|
||||
|
|
|
@ -13,6 +13,29 @@ defined( 'ABSPATH' ) || exit;
|
|||
* Stock Reservation class.
|
||||
*/
|
||||
final class ReserveStock {
|
||||
/**
|
||||
* Is stock reservation enabled?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $enabled = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->enabled = get_option( 'wc_blocks_db_schema_version', 0 ) >= 260;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is stock reservation enabled?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function is_enabled() {
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query for any existing holds on stock for this item.
|
||||
*
|
||||
|
@ -24,6 +47,10 @@ final class ReserveStock {
|
|||
public function get_reserved_stock( \WC_Product $product, $exclude_order_id = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( ! $this->is_enabled() ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared
|
||||
return (int) $wpdb->get_var( $this->get_query_for_reserved_stock( $product->get_stock_managed_by_id(), $exclude_order_id ) );
|
||||
}
|
||||
|
@ -39,7 +66,7 @@ final class ReserveStock {
|
|||
public function reserve_stock_for_order( \WC_Order $order, $minutes = 0 ) {
|
||||
$minutes = $minutes ? $minutes : (int) get_option( 'woocommerce_hold_stock_minutes', 60 );
|
||||
|
||||
if ( ! $minutes ) {
|
||||
if ( ! $minutes || ! $this->is_enabled() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -95,6 +122,10 @@ final class ReserveStock {
|
|||
public function release_stock_for_order( \WC_Order $order ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( ! $this->is_enabled() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$wpdb->delete(
|
||||
$wpdb->wc_reserved_stock,
|
||||
[
|
||||
|
|
|
@ -97,7 +97,8 @@ function wc_install_core() {
|
|||
include wc_dir() . '/uninstall.php';
|
||||
$GLOBALS['wp_roles'] = null; // WPCS: override ok.
|
||||
wp_roles();
|
||||
echo esc_html( 'Installing WooCommerce...' . PHP_EOL );
|
||||
echo esc_html( 'Installing WooCommerce Blocks...' . PHP_EOL );
|
||||
\Automattic\WooCommerce\Blocks\Package::container()->get( \Automattic\WooCommerce\Blocks\Installer::class )->maybe_create_tables();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue