<?php
/**
* Provides plugin activate functionality.
*
* @package Stripe\StripeTaxForWooCommerce\WordPress
*/
namespace Stripe\StripeTaxForWooCommerce\WordPress;
// Exit if script started not from WordPress.
defined( 'ABSPATH' ) || exit;
use Stripe\StripeTaxForWooCommerce\Stripe\StripeTaxLogger;
/**
* Class for each function needs to be called on plugin activate event
*/
class PluginActivate {
/**
* Activate triggered.
*
* @var bool $activate_triggered Property to keep functions called on plugin activate event only once
*/
protected static $activate_triggered;
/**
* Checks if table exists in database
*
* @param string $table_name Table name.
*
* @return bool
*/
protected static function table_exists( string $table_name ): bool {
global $wpdb;
return (bool) (
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->get_var(
$wpdb->prepare(
'SHOW TABLES LIKE %s',
array(
$table_name,
)
)
)
);
}
/**
* Creates table to store plugin options
*
* @return void
*/
protected static function maybe_create_options_table() {
global $wpdb;
$table_name = STRIPE_TAX_FOR_WOOCOMMERCE_DB_PREFIX . 'options';
if ( static::table_exists( $table_name ) ) {
return;
}
// This part is responsible to create the most recent plugin's version of database table schema.
// When database table schema be changed in any future versions, this part needs to be changed too.
// This means, only most recent table creation queries must persist here.
// Migrator logic for updating from one version to another one to be implemented later.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query(
$wpdb->prepare(
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
'CREATE TABLE %i (%i VARCHAR(191) NOT NULL PRIMARY KEY, %i LONGTEXT NOT NULL)',
array(
$table_name,
'option_name',
'option_value',
)
)
);
}
/**
* Creates table to store tax calculations cache
*
* @return void
*/
protected static function maybe_create_tax_calculate_table() {
global $wpdb;
$table_name = STRIPE_TAX_FOR_WOOCOMMERCE_DB_PREFIX . 'calculate_tax';
if ( static::table_exists( $table_name ) ) {
return;
}
// This part is responsible to create the most recent plugin's version of database table schema.
// When database table schema be changed in any future versions, this part needs to be changed too.
// This means, only most recent table creation queries must persist here.
// Migrator logic for updating from one version to another one to be implemented later.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query(
$wpdb->prepare(
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
'CREATE TABLE %i ( %i BIGINT AUTO_INCREMENT PRIMARY KEY, %i BIGINT NOT NULL, %i CHAR(32) NOT NULL, %i CHAR(32) NOT NULL, %i CHAR(32) NOT NULL, %i CHAR(32) NOT NULL, %i LONGTEXT NOT NULL, %i LONGTEXT NOT NULL, CONSTRAINT %i UNIQUE ( %i, %i, %i ), INDEX %i ( %i ) )',
array(
$table_name,
'id',
'time',
'calculate_tax_md5',
'tax_registrations_md5',
'tax_settings_md5',
'api_key_md5',
'request',
'response',
'calculate_tax_uindex',
'calculate_tax_md5',
'tax_registrations_md5',
'tax_settings_md5',
'idx_time',
'time',
)
)
);
}
/**
* Creates table to store tax codes cache
*
* @return void
*/
protected static function maybe_create_tax_codes_table() {
global $wpdb;
$table_name = STRIPE_TAX_FOR_WOOCOMMERCE_DB_PREFIX . 'tax_codes';
if ( static::table_exists( $table_name ) ) {
return;
}
// This part is responsible to create the most recent plugin's version of database table schema.
// When database table schema be changed in any future versions, this part needs to be changed too.
// This means, only most recent table creation queries must persist here.
// Migrator logic for updating from one version to another one to be implemented later.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query(
$wpdb->prepare(
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
'CREATE TABLE %i (%i CHAR(13) NOT NULL PRIMARY KEY, %i TEXT NOT NULL, %i LONGTEXT NOT NULL)',
array(
$table_name,
'id',
'name',
'description',
)
)
);
}
/**
* Creates table to store additional product properties
*
* @return void
*/
protected static function maybe_create_products_table() {
global $wpdb;
$table_name = STRIPE_TAX_FOR_WOOCOMMERCE_DB_PREFIX . 'products';
if ( static::table_exists( $table_name ) ) {
return;
}
// This part is responsible to create the most recent plugin's version of database table schema.
// When database table schema be changed in any future versions, this part needs to be changed too.
// This means, only most recent table creation queries must persist here.
// Migrator logic for updating from one version to another one to be implemented later.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query(
$wpdb->prepare(
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
'CREATE TABLE %i (%i BIGINT UNSIGNED NOT NULL PRIMARY KEY, %i CHAR(13) DEFAULT \'\' NOT NULL, %i ENUM (\'\', \'exclusive\', \'inclusive\') default \'\' NOT NULL)',
array(
$table_name,
'product_id',
'tax_code',
'tax_behavior',
)
)
);
}
/**
* Creates tax transactions table if not exist
*
* @return void
*/
protected static function maybe_create_tax_transactions_table() {
global $wpdb;
$table_name = STRIPE_TAX_FOR_WOOCOMMERCE_DB_PREFIX . 'tax_transactions';
if ( static::table_exists( $table_name ) ) {
return;
}
// This part is responsible to create the most recent plugin's version of database table schema.
// When database table schema be changed in any future versions, this part needs to be changed too.
// This means, only most recent table creation queries must persist here.
// Migrator logic for updating from one version to another one to be implemented later.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query(
$wpdb->prepare(
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
'CREATE TABLE %i (%i BIGINT UNSIGNED NOT NULL, %i LONGTEXT NOT NULL, %i LONGTEXT NOT NULL, INDEX idx_order_id (%i))',
array(
$table_name,
'order_id',
'tax_calculation',
'tax_transaction',
'order_id',
)
)
);
}
/**
* Add time index to calculate_tax table for existing installations.
*
* @return void
*/
public static function maybe_add_time_index_to_calculate_tax_table() {
global $wpdb;
if ( ! $wpdb ) {
return;
}
$table_name = STRIPE_TAX_FOR_WOOCOMMERCE_DB_PREFIX . 'calculate_tax';
if ( ! static::table_exists( $table_name ) ) {
return;
}
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$index_exists = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s AND INDEX_NAME = 'idx_time'",
array( $table_name )
)
);
if ( intval( $index_exists ) > 0 ) {
return;
}
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange
$res = $wpdb->query(
$wpdb->prepare(
'ALTER TABLE %i ADD INDEX `idx_time` (`time`)',
array( $table_name )
)
);
// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange
if ( false === $res ) {
StripeTaxLogger::log_error( $wpdb->last_error );
}
}
/**
* `tax_transactions` table migration check.
*/
public static function maybe_migrate_tax_transactions_table() {
global $wpdb;
if ( ! $wpdb ) {
return;
}
$table_name = STRIPE_TAX_FOR_WOOCOMMERCE_DB_PREFIX . 'tax_transactions';
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$pk_exists = $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = %s
AND INDEX_NAME = 'PRIMARY'
AND COLUMN_NAME = 'order_id'",
array( $table_name )
)
);
if ( intval( $pk_exists ) === 0 ) {
return;
}
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange
$res = $wpdb->query(
$wpdb->prepare(
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange
'ALTER TABLE %i DROP PRIMARY KEY, ADD INDEX `idx_order_id` (`order_id`)',
array( $table_name )
)
);
if ( false === $res ) {
StripeTaxLogger::log_error( $wpdb->last_error );
}
}
/**
* Calls each function to create each needed database table
*
* @return void
*/
protected static function create_necessary_tables() {
static::maybe_create_options_table();
static::maybe_create_tax_calculate_table();
static::maybe_create_tax_codes_table();
static::maybe_create_products_table();
static::maybe_create_tax_transactions_table();
}
/**
* Add plugin activate notices.
*
* @return void
*/
protected static function add_plugin_activate_notices() {
set_transient( 'stripe_tax_for_woocommerce_activate', true );
}
/**
* Function called on plugin activate event.
* Does nothing if function already called once and $force equals false (default).
*
* @param bool $force If true - skips check this function already called once, and does everything that it must do during the first call.
*
* @return void
*/
public static function trigger_activate( bool $force = false ) {
if ( ! empty( static::$activate_triggered ) && ! $force ) {
return;
}
static::$activate_triggered = true;
static::create_necessary_tables();
static::add_plugin_activate_notices();
}
}