* 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:
Mike Jolley 2020-04-28 16:36:37 +01:00 committed by GitHub
parent ad93ddd891
commit a58420a60e
5 changed files with 174 additions and 50 deletions

View File

@ -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();
}
);
}
/**

View File

@ -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' );
}
}
}

View File

@ -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.
*/

View File

@ -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,
[

View File

@ -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();
}
/**