Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,139 @@
<?php
/**
* Customer Query Class.
*
* @package RCP
* @subpackage Database\Queries
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database\Queries;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Query;
/**
* Class used for querying customers.
*
* @since 3.0
*
* @see \RCP\Database\Queries\Customer::__construct() for accepted arguments.
*/
class Customer extends Query {
/** Table Properties ******************************************************/
/**
* Name of the database table to query.
*
* @since 3.0
* @access public
* @var string
*/
protected $table_name = 'customers';
/**
* String used to alias the database table in MySQL statement.
*
* @since 3.0
* @access public
* @var string
*/
protected $table_alias = 'c';
/**
* Name of class used to setup the database schema
*
* @since 3.0
* @access public
* @var string
*/
protected $table_schema = '\\RCP\\Database\\Schemas\\Customers';
/** Item ******************************************************************/
/**
* Name for a single item
*
* @since 3.0
* @access public
* @var string
*/
protected $item_name = 'customer';
/**
* Plural version for a group of items.
*
* @since 3.0
* @access public
* @var string
*/
protected $item_name_plural = 'customers';
/**
* Callback function for turning IDs into objects
*
* @since 3.0
* @access public
* @var mixed
*/
protected $item_shape = '\\RCP_Customer';
/**
* Group to cache queries and queried items in.
*
* @since 3.0
* @access public
* @var string
*/
protected $cache_group = 'customers';
/**
* Sets up the customer query, based on the query vars passed.
*
* @since 3.0
* @access public
*
* @param string|array $query {
* Optional. Array or query string of membership query parameters.
* Default empty.
*
* @type int $id A customer ID to only return that customer. Default empty.
* @type array $id__in Array of customer IDs to include. Default empty.
* @type array $id__not_in Array of customer IDs to exclude. Default empty.
* @type int $user_id A user ID to filter by. Default empty.
* @type array $user_id_in Array of user IDs to include. Default empty.
* @type array $user_id__not_in Array of user IDs to exclude. Default empty.
* @type string $email_verification An email verification status to filter by. Accepts: `verified`,
* `pending`, and `none`. Default null.
* @type array $date_query Query all datetime columns together. See WP_Date_Query.
* @type array $date_registered_query Date query clauses to limit customers by. See WP_Date_Query.
* Default null.
* @type array $last_login_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type bool $has_trialed Filter by whether or not the customer has trialed. Default null.
* @type bool $count Whether to return a customer count (true) or array of customer
* objects. Default false.
* @type string $fields Item fields to return. Accepts any column known names
* or empty (returns an array of complete customer objects). Default
* empty.
* @type int $number Limit number of customers to retrieve. Default 100.
* @type int $offset Number of customers to offset the query. Used to build LIMIT
* clause. Default 0.
* @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true.
* @type string|array $orderby Accepts 'id', 'date_registered', and 'last_login'. Also accepts
* false, an empty array, or 'none' to disable `ORDER BY` clause.
* Default 'id'.
* @type string $order How to order results. Accepts 'ASC', 'DESC'. Default 'DESC'.
* @type string $search Search term(s) to retrieve matching customers for. Default empty.
* @type bool $update_cache Whether to prime the cache for found customers. Default false.
* }
*/
public function __construct( $query = array() ) {
parent::__construct( $query );
}
}

View File

@@ -0,0 +1,116 @@
<?php
/**
* Customers Schema Class.
*
* @package RCP
* @subpackage Database\Schemas
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database\Schemas;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Schema;
/**
* Customers Schema Class.
*
* @since 3.0
*/
class Customers extends Schema {
/**
* Array of database column objects
*
* @since 3.0
* @access public
* @var array
*/
public $columns = array(
// id
array(
'name' => 'id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'extra' => 'auto_increment',
'primary' => true,
'sortable' => true
),
// user_id
array(
'name' => 'user_id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'default' => '0'
),
// date_registered
array(
'name' => 'date_registered',
'type' => 'datetime',
'default' => '',
'created' => true,
'date_query' => true,
'sortable' => true,
),
// email_verification
array(
'name' => 'email_verification',
'type' => 'enum(\'verified\', \'pending\', \'none\')',
'default' => 'none',
'transition' => true
),
// last_login
array(
'name' => 'last_login',
'type' => 'datetime',
'default' => null,
'allow_null' => true,
'date_query' => true,
'sortable' => true,
),
// has_trialed
array(
'name' => 'has_trialed',
'type' => 'smallint',
'length' => '',
'unsigned' => true,
'default' => null,
'allow_null' => true,
'transition' => true
),
// ips
array(
'name' => 'ips',
'type' => 'longtext',
'default' => '',
'searchable' => true
),
// notes
array(
'name' => 'notes',
'type' => 'longtext',
'default' => ''
),
// uuid
array(
'uuid' => true,
)
);
}

View File

@@ -0,0 +1,124 @@
<?php
/**
* Customers Table.
*
* @package RCP
* @subpackage Database\Tables
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database\Tables;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Table;
/**
* Setup the "rcp_customers" database table
*
* @since 3.0
*/
final class Customers extends Table {
/**
* @var string Table name
*/
protected $name = 'customers';
/**
* @var string Database version
*/
protected $version = 202003311;
/**
* @var array Upgrades to perform
*/
protected $upgrades = array(
'201908151' => 201908151,
'202003311' => 202003311
);
/**
* Customers constructor.
*
* @access public
* @since 3.0
* @return void
*/
public function __construct() {
parent::__construct();
}
/**
* Setup the database schema
*
* @access protected
* @since 3.0
* @return void
*/
protected function set_schema() {
$this->schema = "id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
user_id bigint(20) unsigned NOT NULL DEFAULT '0',
date_registered datetime NOT NULL,
email_verification enum('verified', 'pending', 'none') DEFAULT 'none',
last_login datetime DEFAULT NULL,
has_trialed smallint unsigned DEFAULT NULL,
ips longtext NOT NULL DEFAULT '',
notes longtext NOT NULL DEFAULT '',
uuid varchar(100) NOT NULL default '',
PRIMARY KEY (id),
KEY user_id (user_id)";
}
/**
* Upgrade to version 201908151
* - Add `has_trialed` column.
*
* @since 3.1.2
* @return bool
*/
protected function __201908151() {
// Look for column
$result = $this->column_exists( 'has_trialed' );
// Maybe add column
if ( false === $result ) {
$result = $this->get_db()->query( "
ALTER TABLE {$this->table_name} ADD COLUMN `has_trialed` smallint unsigned DEFAULT NULL AFTER `last_login`;
" );
}
// Return success/fail
$success = $this->is_success( $result );
rcp_log( sprintf( 'Upgrading customers table to version 201908151. Result: %s', var_export( $success, true ) ), true );
return $success;
}
/**
* Upgrade to version 202003311
* - Change default `last_login` value to `null`
*/
protected function __202003311() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY last_login datetime DEFAULT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003311 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003311 failure.', $this->get_table_name() ), true );
}
return $success;
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,141 @@
<?php
/**
* Discount Query Class.
*
* @package RCP
* @subpackage Database\Queries
* @copyright Copyright (c) 2019, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.3
*/
namespace RCP\Database\Queries;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Query;
/**
* Class used for querying discounts.
*
* @since 3.3
*
* @see \RCP\Database\Queries\Discount::__construct() for accepted arguments.
*/
class Discount extends Query {
/** Table Properties ******************************************************/
/**
* Name of the database table to query.
*
* @since 3.3
* @access public
* @var string
*/
protected $table_name = 'discounts';
/**
* String used to alias the database table in MySQL statement.
*
* @since 3.3
* @access public
* @var string
*/
protected $table_alias = 'd';
/**
* Name of class used to setup the database schema
*
* @since 3.3
* @access public
* @var string
*/
protected $table_schema = '\\RCP\\Database\\Schemas\\Discounts';
/** Item ******************************************************************/
/**
* Name for a single item
*
* @since 3.3
* @access public
* @var string
*/
protected $item_name = 'discount';
/**
* Plural version for a group of items.
*
* @since 3.3
* @access public
* @var string
*/
protected $item_name_plural = 'discounts';
/**
* Callback function for turning IDs into objects
*
* @since 3.3
* @access public
* @var mixed
*/
protected $item_shape = '\\RCP_Discount';
/**
* Group to cache queries and queried items in.
*
* @since 3.3
* @access public
* @var string
*/
protected $cache_group = 'discounts';
/**
* Sets up the discount query, based on the query vars passed.
*
* @since 3.3
* @access public
*
* @param string|array $query {
* Optional. Array or query string of discount query parameters.
* Default empty.
*
* @type int $id A discount ID to only return that discount. Default empty.
* @type array $id__in Array of discount IDs to include. Default empty.
* @type array $id__not_in Array of discount IDs to exclude. Default empty.
* @type string $name Specific discount name to retrieve. Default empty.
* @type string $amount Retrieve discounts for this amount. Default empty.
* @type string $unit Retrieve discounts with this unit. Default empty.
* @type string $code Specific discount code to retrieve. Default empty.
* @type string $status Status to filter by. Default empty.
* @type int $one_time Set to `1` to only retrieve one-time discounts. Set to `0` to only
* retrieve recurring discounts. Omit to retrieve all. Default empty.
* @type array $date_query Query all datetime columns together. See WP_Date_Query.
* @type array $expiration_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type array $date_created_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type array $date_modified_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type bool $count Whether to return a discount count (true) or array of discount
* objects. Default false.
* @type string $fields Item fields to return. Accepts any column known names
* or empty (returns an array of complete discount objects). Default
* empty.
* @type int $number Limit number of discount to retrieve. Default 100.
* @type int $offset Number of discount to offset the query. Used to build LIMIT
* clause. Default 0.
* @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true.
* @type string|array $orderby Accepts 'id', 'name', 'code', 'use_count', 'max_uses', 'status',
* 'expiration', 'date_created', and 'date_modified'. Also accepts
* false, an empty array, or 'none' to disable `ORDER BY` clause.
* Default 'id'.
* @type string $order How to order results. Accepts 'ASC', 'DESC'. Default 'DESC'.
* @type string $search Search term(s) to retrieve matching discounts for. Default empty.
* @type bool $update_cache Whether to prime the cache for found discounts. Default false.
* }
*/
public function __construct( $query = array() ) {
parent::__construct( $query );
}
}

View File

@@ -0,0 +1,163 @@
<?php
/**
* Discounts Schema Class.
*
* @package RCP
* @subpackage Database\Schemas
* @copyright Copyright (c) 2019, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.3
*/
namespace RCP\Database\Schemas;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Schema;
/**
* Discounts Schema Class.
*
* @since 3.3
*/
class Discounts extends Schema {
/**
* Array of database column objects
*
* @since 3.3
* @access public
* @var array
*/
public $columns = array(
// id
array(
'name' => 'id',
'type' => 'bigint',
'length' => '9',
'unsigned' => false,
'extra' => 'auto_increment',
'primary' => true,
'sortable' => true
),
// name
array(
'name' => 'name',
'type' => 'tinytext',
'default' => '',
'sortable' => true,
'searchable' => true
),
// description
array(
'name' => 'description',
'type' => 'longtext',
'default' => '',
'searchable' => true
),
// amount
array(
'name' => 'amount',
'type' => 'tinytext',
'default' => ''
),
// unit
array(
'name' => 'unit',
'type' => 'tinytext',
'default' => '%'
),
// code
array(
'name' => 'code',
'type' => 'tinytext',
'default' => '',
'sortable' => true,
'searchable' => true
),
// use_count
array(
'name' => 'use_count',
'type' => 'mediumint',
'default' => '0',
'sortable' => true,
'transition' => true
),
// max_uses
array(
'name' => 'max_uses',
'type' => 'mediumint',
'default' => '0',
'sortable' => true
),
// status
array(
'name' => 'status',
'type' => 'tinytext',
'default' => 'disabled',
'sortable' => true,
'transition' => true
),
// expiration
array(
'name' => 'expiration',
'type' => 'datetime',
'default' => null,
'allow_null' => true,
'date_query' => true,
'sortable' => true,
),
// membership_level_ids
array(
'name' => 'membership_level_ids',
'type' => 'text',
'default' => ''
),
// one_time
array(
'name' => 'one_time',
'type' => 'smallint',
'default' => '0'
),
// date_created
array(
'name' => 'date_created',
'type' => 'datetime',
'default' => '',
'created' => true,
'date_query' => true,
'sortable' => true,
),
// date_modified
array(
'name' => 'date_modified',
'type' => 'datetime',
'default' => '',
'modified' => true,
'date_query' => true,
'sortable' => true,
),
// uuid
array(
'uuid' => true,
)
);
}

View File

@@ -0,0 +1,370 @@
<?php
/**
* Discounts Table.
*
* @package RCP
* @subpackage Database\Tables
* @copyright Copyright (c) 2019, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.3
*/
namespace RCP\Database\Tables;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Table;
/**
* Setup the "rcp_discounts" database table
*
* @since 3.3
*/
final class Discounts extends Table {
/**
* @var string Table name
*/
protected $name = 'discounts';
/**
* @var string Database version
*/
protected $version = 202003313;
/**
* @var array Array of upgrade versions and methods
*/
protected $upgrades = array(
'201907101' => 201907101,
'201907102' => 201907102,
'201907103' => 201907103,
'201907104' => 201907104,
'202002101' => 202002101,
'202003311' => 202003311,
'202003312' => 202003312,
'202003313' => 202003313
);
/**
* Discounts constructor.
*
* @access public
* @since 3.3
* @return void
*/
public function __construct() {
parent::__construct();
}
/**
* Setup the database schema
*
* @access protected
* @since 3.3
* @return void
*/
protected function set_schema() {
$this->schema = "id bigint(9) NOT NULL AUTO_INCREMENT,
name tinytext NOT NULL DEFAULT '',
description longtext NOT NULL default '',
amount tinytext NOT NULL,
unit tinytext NOT NULL DEFAULT '',
code tinytext NOT NULL DEFAULT '',
use_count mediumint NOT NULL DEFAULT '0',
max_uses mediumint NOT NULL DEFAULT '0',
status tinytext NOT NULL,
expiration datetime DEFAULT NULL,
membership_level_ids text NOT NULL DEFAULT '',
one_time smallint NOT NULL DEFAULT 0,
date_created datetime NOT NULL,
date_modified datetime NOT NULL,
uuid varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY (id)";
}
/**
* If the old `rcp_discounts_db_version` option exists, copy that value to our new version key.
* This will ensure new upgrades are processed on old installs.
*
* @since 3.3
*/
public function maybe_upgrade() {
if ( false !== get_option( 'rcp_discounts_db_version' ) ) {
update_option( $this->db_version_key, get_option( 'rcp_discounts_db_version' ) );
delete_option( 'rcp_discounts_db_version' );
}
return parent::maybe_upgrade();
}
/**
* Upgrade to 201907101
* - Update `expiration` type to `datetime`.
*
* @since 3.3
* @return bool
*/
protected function __201907101() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY expiration datetime DEFAULT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 201907101 successful.', $this->get_table_name() ) );
} else {
rcp_log( sprintf( '%s table upgrade to 201907101 failure.', $this->get_table_name() ) );
}
return $success;
}
/**
* Upgrade to 201907102
* - Add `date_created` column.
*
* @since 3.3
* @return bool
*/
protected function __201907102() {
// Look for column
$result = $this->column_exists( 'date_created' );
// Add column if it doesn't exist.
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN date_created datetime NOT NULL;" );
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 201907102 successful.', $this->get_table_name() ) );
} else {
rcp_log( sprintf( '%s table upgrade to 201907102 failure.', $this->get_table_name() ) );
}
return $success;
}
/**
* Upgrade to 201907103
* - Add `date_modified` column.
*
* @since 3.3
* @return bool
*/
protected function __201907103() {
// Look for column
$result = $this->column_exists( 'date_modified' );
// Add column if it doesn't exist.
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN date_modified datetime NOT NULL;" );
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 201907103 successful.', $this->get_table_name() ) );
} else {
rcp_log( sprintf( '%s table upgrade to 201907103 failure.', $this->get_table_name() ) );
}
return $success;
}
/**
* Upgrade to 201907104
* - Add `uuid` column.
*
* @since 3.3
* @return bool
*/
protected function __201907104() {
// Look for column
$result = $this->column_exists( 'uuid' );
// Add column if it doesn't exist.
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN uuid varchar(100) NOT NULL DEFAULT '';" );
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 201907104 successful.', $this->get_table_name() ) );
} else {
rcp_log( sprintf( '%s table upgrade to 201907104 failure.', $this->get_table_name() ) );
}
return $success;
}
/**
* Upgrade to 202002101
* - Add `membership_level_ids` column if it doesn't already exist. Then migrate data from old
* `subscription_id` column to new column. This change used to exist in RCP_Upgrades::v30_upgrades()
* but was moved here.
*
* - Add `one_time` column if it doesn't already exist. This column was actually added in a previous
* version of RCP, but there appear to be some issues with customers missing it.
*
* @link https://github.com/restrictcontentpro/restrict-content-pro/issues/2698
*
* @since 3.3.7
* @return bool
*/
protected function __202002101() {
/**
* membership_level_ids
*/
// Look for column
$result = $this->column_exists( 'membership_level_ids' );
$has_subscription_id_col = $this->column_exists( 'subscription_id' );
// Add column if it doesn't exist.
if ( false === $result ) {
$after = $has_subscription_id_col ? 'subscription_id' : 'expiration';
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN membership_level_ids TEXT NOT NULL AFTER {$after};" );
}
$success = $this->is_success( $result );
if ( ! $success ) {
rcp_log( sprintf( '%s table upgrade to 202002101 failure - error while adding `membership_level_ids` column.', $this->get_table_name() ) );
return $success;
}
if ( $has_subscription_id_col ) {
rcp_log( sprintf( 'Adding membership_level_ids column in %s was successful. Now migrating data.', $this->get_table_name() ), true );
// Doing a direct query here to ensure we can get `subscription_id`.
$discounts = $this->get_db()->get_results( "SELECT id, subscription_id FROM {$this->get_table_name()} WHERE subscription_id != ''" );
if ( ! empty( $discounts ) ) {
// Prevent discount sync with Stripe - we don't need it here.
remove_action( 'rcp_edit_discount', 'rcp_stripe_update_discount', 10 );
foreach ( $discounts as $discount ) {
$membership_level_ids = empty( $discount->subscription_id ) ? array() : array( absint( $discount->subscription_id ) );
rcp_update_discount( absint( $discount->id ), array(
'membership_level_ids' => $membership_level_ids
) );
}
rcp_log( sprintf( 'Successfully updated membership_level_ids column for %d discount codes.', count( $discounts ) ), true );
} else {
rcp_log( 'No discount codes to upgrade.', true );
}
// Delete old `subscription_id` column.
rcp_log( sprintf( 'Dropping old subscription_id column from %s.', $this->get_table_name() ), true );
$this->get_db()->query( "ALTER TABLE {$this->get_table_name()} DROP COLUMN subscription_id" );
}
/**
* one_time
*/
// Look for column
$result = $this->column_exists( 'one_time' );
// Add column if it doesn't exist.
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN one_time smallint NOT NULL DEFAULT 0 AFTER membership_level_ids;" );
global $rcp_options;
if ( $this->is_success( $result ) && ! empty( $rcp_options['one_time_discounts'] ) ) {
rcp_log( 'Setting all discounts to one time.', true );
$this->get_db()->query( "UPDATE {$this->table_name} SET one_time = 1" );
}
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202002101 successful.', $this->get_table_name() ) );
} else {
rcp_log( sprintf( '%s table upgrade to 202002101 failure - error while adding `one_time` column.', $this->get_table_name() ) );
}
return $success;
}
/**
* Upgrade to version 202003311
* - Change default `expiration` value to `null`
*/
protected function __202003311() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY expiration datetime DEFAULT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003311 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003311 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to version 202003312
* - Remove default `date_created` value
*/
protected function __202003312() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY date_created datetime NOT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003312 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003312 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to version 202003313
* - Remove default `date_modified` value
*/
protected function __202003313() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY date_modified datetime NOT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003313 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003313 failure.', $this->get_table_name() ), true );
}
return $success;
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,322 @@
<?php
/**
* Base Custom Table Class.
*
* @package RCP
* @subpackage Database
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* The base class that all other database base classes extend.
*
* This class attempts to provide some universal immutability to all other
* database interfaces, starting with a magic getter, but likely expanding into
* a magic call handler and others.
*
* @since 3.0
*/
class Base {
/** Global Properties *****************************************************/
/**
* Global prefix used for tables/hooks/cache-groups/etc...
*
* @since 3.0.0
* @var string
*/
protected $prefix = 'rcp';
/**
* The last database error, if any.
*
* @since 3.0.0
* @var mixed
*/
protected $last_error = false;
/** Public ****************************************************************/
/**
* Magic isset'ter for immutability.
*
* @since 3.0
*
* @param string $key
*
* @return mixed
*/
public function __isset( $key = '' ) {
// No more uppercase ID properties ever
if ( 'ID' === $key ) {
$key = 'id';
}
// Class method to try and call
$method = "get_{$key}";
// Return property if exists
if ( method_exists( $this, $method ) ) {
return true;
// Return get method results if exists
} elseif ( property_exists( $this, $key ) ) {
return true;
}
// Return false if not exists
return false;
}
/**
* Magic getter for immutability.
*
* @since 3.0
*
* @param string $key
*
* @return mixed
*/
public function __get( $key = '' ) {
// No more uppercase ID properties ever
if ( 'ID' === $key ) {
$key = 'id';
}
// Class method to try and call
$method = "get_{$key}";
// Return property if exists
if ( method_exists( $this, $method ) ) {
return call_user_func( array( $this, $method ) );
// Return get method results if exists
} elseif ( property_exists( $this, $key ) ) {
return $this->{$key};
}
// Return null if not exists
return null;
}
/**
* Converts the given object to an array.
*
* @since 3.0
*
* @return array Array version of the given object.
*/
public function to_array() {
return get_object_vars( $this );
}
/** Protected *************************************************************/
/**
* Maybe append the prefix to string.
*
* @since 3.0
*
* @param string $string
* @param string $sep
* @return string
*/
protected function apply_prefix( $string = '', $sep = '_' ) {
return ! empty( $this->prefix )
? "{$this->prefix}{$sep}{$string}"
: $string;
}
/**
* Return the first letters of a string of words with a separator.
*
* Used primarily to guess at table aliases when none is manually set.
*
* Applies the following formatting to a string:
* - Trim whitespace
* - No accents
* - No trailing underscores
*
* @since 3.0
*
* @param string $string
* @param string $sep
* @return string
*/
protected function first_letters( $string = '', $sep = '_' ) {
// Set empty default return value
$retval = '';
// Bail if empty or not a string
if ( empty( $string ) || ! is_string( $string ) ) {
return $retval;
}
// Trim spaces off the ends
$unspace = trim( $string );
$accents = remove_accents( $unspace );
$lower = strtolower( $accents );
$parts = explode( $sep, $lower );
// Loop through parts and concatenate the first letters together
foreach ( $parts as $part ) {
$retval .= substr( $part, 0, 1 );
}
// Return the result
return $retval;
}
/**
* Sanitize a table name string.
*
* Used to make sure that a table name value meets MySQL expectations.
*
* Applies the following formatting to a string:
* - Trim whitespace
* - No accents
* - No special characters
* - No hyphens
* - No double underscores
* - No trailing underscores
*
* @since 3.0
*
* @param string $name The name of the database table
*
* @return string Sanitized database table name
*/
protected function sanitize_table_name( $name = '' ) {
// Bail if empty or not a string
if ( empty( $name ) || ! is_string( $name ) ) {
return false;
}
// Trim spaces off the ends
$unspace = trim( $name );
// Only non-accented table names (avoid truncation)
$accents = remove_accents( $unspace );
// Only lowercase characters, hyphens, and dashes (avoid index corruption)
$lower = sanitize_key( $accents );
// Replace hyphens with single underscores
$under = str_replace( '-', '_', $lower );
// Single underscores only
$single = str_replace( '__', '_', $under );
// Remove trailing underscores
$clean = trim( $single, '_' );
// Bail if table name was garbaged
if ( empty( $clean ) ) {
return false;
}
// Return the cleaned table name
return $clean;
}
/**
* Set class variables from arguments.
*
* @since 3.0
*
* @param array $args
*/
protected function set_vars( $args = array() ) {
// Bail if empty or not an array
if ( empty( $args ) ) {
return;
}
// Cast to an array
if ( ! is_array( $args ) ) {
$args = (array) $args;
}
// Set all properties
foreach ( $args as $key => $value ) {
$this->{$key} = $value;
}
}
/**
* Return the global database interface.
*
* See: https://core.trac.wordpress.org/ticket/31556
*
* @since 3.0
*
* @return \wpdb Database interface, or False if not set
*/
protected function get_db() {
// Default database return value (might change)
$retval = false;
// Look for the WordPress global database interface
if ( isset( $GLOBALS['wpdb'] ) ) {
$retval = $GLOBALS['wpdb'];
}
/*
* Developer note:
*
* It should be impossible for a database table to be interacted with
* before the primary database interface it is setup.
*
* However, because applications are complicated, it is unsafe to assume
* anything, so this silently returns false instead of halting everything.
*
* If you are here because this method is returning false for you, that
* means the database table is being invoked too early in the lifecycle
* of the application. In WordPress, that means before the $wpdb global
* is created; in other environments, you will need to adjust accordingly.
*/
// Return the database interface
return $retval;
}
/**
* Check if an operation succeeded
*
* @since 3.0
*
* @param mixed $result
* @return boolean
*/
protected function is_success( $result = false ) {
// Bail if no row exists
if ( empty( $result ) ) {
$retval = false;
// Bail if an error occurred
} elseif ( is_wp_error( $result ) ) {
$this->last_error = $result;
$retval = false;
// No errors
} else {
$retval = true;
}
// Return the result
return (bool) $retval;
}
}

View File

@@ -0,0 +1,856 @@
<?php
/**
* Base Schema Column Class.
*
* @package RCP
* @subpackage Database\Schemas
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Base class used for each column for a custom table.
*
* @since 3.0
*
* @see Column::__construct() for accepted arguments.
*/
class Column extends Base {
/** Table Attributes ******************************************************/
/**
* Name for the database column
*
* Required. Must contain lowercase alphabetical characters only. Use of any
* other character (number, ascii, unicode, emoji, etc...) will result in
* fatal application errors.
*
* @since 3.0
* @access public
* @var string
*/
public $name = '';
/**
* Type of database column
*
* See: https://dev.mysql.com/doc/en/data-types.html
*
* @since 3.0
* @access public
* @var string
*/
public $type = '';
/**
* Length of database column
*
* See: https://dev.mysql.com/doc/en/storage-requirements.html
*
* @since 3.0
* @access public
* @var string
*/
public $length = false;
/**
* Is integer unsigned?
*
* See: https://dev.mysql.com/doc/en/numeric-type-overview.html
*
* @since 3.0
* @access public
* @var bool
*/
public $unsigned = true;
/**
* Is integer filled with zeroes?
*
* See: https://dev.mysql.com/doc/en/numeric-type-overview.html
*
* @since 3.0
* @access public
* @var bool
*/
public $zerofill = false;
/**
* Is data in a binary format?
*
* See: https://dev.mysql.com/doc/en/binary-varbinary.html
*
* @since 3.0
* @access public
* @var bool
*/
public $binary = false;
/**
* Is null an allowed value?
*
* See: https://dev.mysql.com/doc/en/data-type-defaults.html
*
* @since 3.0
* @access public
* @var bool
*/
public $allow_null = false;
/**
* Typically empty/null, or date value
*
* See: https://dev.mysql.com/doc/en/data-type-defaults.html
*
* @since 3.0
* @access public
* @var string
*/
public $default = '';
/**
* auto_increment, etc...
*
* See: https://dev.mysql.com/doc/en/data-type-defaults.html
*
* @since 3.0
* @access public
* @var string
*/
public $extra = '';
/**
* Typically inherited from the database interface (wpdb).
*
* By default, this will use the globally available database encoding. You
* most likely do not want to change this; if you do, you already know what
* to do.
*
* See: https://dev.mysql.com/doc/mysql/en/charset-column.html
*
* @since 3.0
* @access public
* @var string
*/
public $encoding = '';
/**
* Typically inherited from the database interface (wpdb).
*
* By default, this will use the globally available database collation. You
* most likely do not want to change this; if you do, you already know what
* to do.
*
* See: https://dev.mysql.com/doc/mysql/en/charset-column.html
*
* @since 3.0
* @access public
* @var string
*/
public $collation = '';
/**
* Typically empty; probably ignore.
*
* By default, columns do not have comments. This is unused by any other
* relative code, but you can include less than 1024 characters here.
*
* @since 3.0
* @access public
* @var string
*/
public $comment = '';
/** Special Attributes ****************************************************/
/**
* Is this the primary column?
*
* By default, columns are not the primary column. This is used by the Query
* class for several critical functions, including (but not limited to) the
* cache key, meta-key relationships, auto-incrementing, etc...
*
* @since 3.0
* @access public
* @var bool
*/
public $primary = false;
/**
* Is this the column used as a created date?
*
* By default, columns do not represent the date a value was first entered.
* This is used by the Query class to set its value automatically to the
* current datetime value immediately before insert.
*
* @since 3.0
* @access public
* @var bool
*/
public $created = false;
/**
* Is this the column used as a modified date?
*
* By default, columns do not represent the date a value was last changed.
* This is used by the Query class to update its value automatically to the
* current datetime value immediately before insert|update.
*
* @since 3.0
* @access public
* @var bool
*/
public $modified = false;
/**
* Is this the column used as a unique universal identifier?
*
* By default, columns are not UUIDs. This is used by the Query class to
* generate a unique string that can be used to identify a row in a database
* table, typically in such a way that is unrelated to the row data itself.
*
* @since 3.0
* @access public
* @var bool
*/
public $uuid = false;
/** Query Attributes ******************************************************/
/**
* What is the string-replace pattern?
*
* By default, column patterns will be guessed based on their type. Set this
* manually to `%s|%d|%f` only if you are doing something weird, or are
* explicitly storing numeric values in text-based column types.
*
* @since 3.0
* @access public
* @var string
*/
public $pattern = '';
/**
* Is this column searchable?
*
* By default, columns are not searchable. When `true`, the Query class will
* add this column to the results of search queries.
*
* Avoid setting to `true` on large blobs of text, unless you've optimized
* your database server to accommodate these kinds of queries.
*
* @since 3.0
* @access public
* @var bool
*/
public $searchable = false;
/**
* Is this column a date (that uses WP_Date_Query?)
*
* By default, columns do not support date queries. When `true`, the Query
* class will accept complex statements to help narrow results down to
* specific periods of time for values in this column.
*
* @since 3.0
* @access public
* @var bool
*/
public $date_query = false;
/**
* Is this column used in orderby?
*
* By default, columns are not sortable. This ensures that the database
* table does not perform costly operations on unindexed columns or columns
* of an inefficient type.
*
* You can safely turn this on for most numeric columns, indexed columns,
* and text columns with intentionally limited lengths.
*
* @since 3.0
* @access public
* @var bool
*/
public $sortable = false;
/**
* Is __in supported?
*
* By default, columns support being queried using an `IN` statement. This
* allows the Query class to retrieve rows that match your array of values.
*
* Consider setting this to `false` for longer text columns.
*
* @since 3.0
* @access public
* @var bool
*/
public $in = true;
/**
* Is __not_in supported?
*
* By default, columns support being queried using a `NOT IN` statement.
* This allows the Query class to retrieve rows that do not match your array
* of values.
*
* Consider setting this to `false` for longer text columns.
*
* @since 3.0
* @access public
* @var bool
*/
public $not_in = true;
/** Cache Attributes ******************************************************/
/**
* Does this column have its own cache key?
*
* By default, only primary columns are used as cache keys. If this column
* is unique, or is frequently used to get database results, you may want to
* consider setting this to true.
*
* Use in conjunction with a database index for speedy queries.
*
* @since 3.0
* @access public
* @var string
*/
public $cache_key = false;
/** Action Attributes *****************************************************/
/**
* Does this column fire a transition action when it's value changes?
*
* By default, columns do not fire transition actions. In some cases, it may
* be desirable to know when a database value changes, and what the old and
* new values are when that happens.
*
* The Query class is responsible for triggering the event action.
*
* @since 3.0
* @access public
* @var bool
*/
public $transition = false;
/** Callback Attributes ***************************************************/
/**
* Maybe validate this data before it is written to the database.
*
* By default, column data is validated based on the type of column that it
* is. You can set this to a callback function of your choice to override
* the default validation behavior.
*
* @since 3.0.0
* @access public
* @var string
*/
public $validate = '';
/**
* Array of capabilities used to interface with this column.
*
* These are used by the Query class to allow and disallow CRUD access to
* column data, typically based on roles or capabilities.
*
* @since 3.0.0
* @access public
* @var array
*/
public $caps = array();
/**
* Array of possible aliases this column can be referred to as.
*
* These are used by the Query class to allow for columns to be renamed
* without requiring complex architectural backwards compatability support.
*
* @since 3.0
* @access public
* @var array
*/
public $aliases = array();
/**
* Array of possible relationships this column has with columns in other
* database tables.
*
* These are typically unenforced foreign keys, and are used by the Query
* class to help prime related items.
*
* @since 3.0
* @access public
* @var array
*/
public $relationships = array();
/** Methods ***************************************************************/
/**
* Sets up the order query, based on the query vars passed.
*
* @since 3.0
* @access public
*
* @param string|array $args {
* Optional. Array or query string of order query parameters. Default empty.
*
* @type string $name Name of database column
* @type string $type Type of database column
* @type integer $length Length of database column
* @type boolean $unsigned Is integer unsigned?
* @type boolean $zerofill Is integer filled with zeroes?
* @type boolean $binary Is data in a binary format?
* @type boolean $allow_null Is null an allowed value?
* @type mixed $default Typically empty/null, or date value
* @type string $extra auto_increment, etc...
* @type string $encoding Typically inherited from wpdb
* @type string $collation Typically inherited from wpdb
* @type string $comment Typically empty
* @type boolean $pattern What is the string-replace pattern?
* @type boolean $primary Is this the primary column?
* @type boolean $created Is this the column used as a created date?
* @type boolean $modified Is this the column used as a modified date?
* @type boolean $uuid Is this the column used as a universally unique identifier?
* @type boolean $searchable Is this column searchable?
* @type boolean $sortable Is this column used in orderby?
* @type boolean $date_query Is this column a datetime?
* @type boolean $in Is __in supported?
* @type boolean $not_in Is __not_in supported?
* @type boolean $cache_key Is this column queried independently?
* @type boolean $transition Does this column transition between changes?
* @type string $validate A callback function used to validate on save.
* @type array $caps Array of capabilities to check.
* @type array $aliases Array of possible column name aliases.
* @type array $relationships Array of columns in other tables this column relates to.
* }
*/
public function __construct( $args = array() ) {
// Parse arguments
$r = $this->parse_args( $args );
// Maybe set variables from arguments
if ( ! empty( $r ) ) {
$this->set_vars( $r );
}
}
/** Argument Handlers *****************************************************/
/**
* Parse column arguments
*
* @since 3.0
* @access public
*
* @param array $args
*
* @return array
*/
private function parse_args( $args = array() ) {
// Parse arguments
$r = wp_parse_args( $args, array(
// Table
'name' => '',
'type' => '',
'length' => '',
'unsigned' => false,
'zerofill' => false,
'binary' => false,
'allow_null' => false,
'default' => '',
'extra' => '',
'encoding' => $GLOBALS['wpdb']->charset,
'collation' => $GLOBALS['wpdb']->collate,
'comment' => '',
// Query
'pattern' => false,
'searchable' => false,
'sortable' => false,
'date_query' => false,
'transition' => false,
'in' => true,
'not_in' => true,
// Special
'primary' => false,
'created' => false,
'modified' => false,
'uuid' => false,
// Cache
'cache_key' => false,
// Validation
'validate' => '',
// Capabilities
'caps' => array(),
// Backwards Compatibility
'aliases' => array(),
// Column Relationships
'relationships' => array()
) );
// Force some arguments for special column types
$r = $this->special_args( $r );
// Set the args before they are sanitized
$this->set_vars( $r );
// Return array
return $this->validate_args( $r );
}
/**
* Validate arguments after they are parsed.
*
* @since 3.0
* @access private
*
* @param array $args
*
* @return array
*/
private function validate_args( $args = array() ) {
// Sanitization callbacks
$callbacks = array(
'name' => 'sanitize_key',
'type' => 'strtoupper',
'length' => 'intval',
'unsigned' => 'wp_validate_boolean',
'zerofill' => 'wp_validate_boolean',
'binary' => 'wp_validate_boolean',
'allow_null' => 'wp_validate_boolean',
'default' => array( $this, 'sanitize_default' ),
'extra' => 'wp_kses_data',
'encoding' => 'wp_kses_data',
'collation' => 'wp_kses_data',
'comment' => 'wp_kses_data',
'primary' => 'wp_validate_boolean',
'created' => 'wp_validate_boolean',
'modified' => 'wp_validate_boolean',
'uuid' => 'wp_validate_boolean',
'searchable' => 'wp_validate_boolean',
'sortable' => 'wp_validate_boolean',
'date_query' => 'wp_validate_boolean',
'transition' => 'wp_validate_boolean',
'in' => 'wp_validate_boolean',
'not_in' => 'wp_validate_boolean',
'cache_key' => 'wp_validate_boolean',
'pattern' => array( $this, 'sanitize_pattern' ),
'validate' => array( $this, 'sanitize_validation' ),
'caps' => array( $this, 'sanitize_capabilities' ),
'aliases' => array( $this, 'sanitize_aliases' ),
'relationships' => array( $this, 'sanitize_relationships' )
);
// Default args array
$r = array();
// Loop through and try to execute callbacks
foreach ( $args as $key => $value ) {
// Callback is callable
if ( isset( $callbacks[$key] ) && is_callable( $callbacks[$key] ) ) {
$r[$key] = call_user_func( $callbacks[$key], $value );
// Callback is malformed so just let it through to avoid breakage
} else {
$r[$key] = $value;
}
}
// Return sanitized arguments
return $r;
}
/**
* Force column arguments for special column types
*
* @since 3.0
*
* @param array $args
*
* @return array
*/
private function special_args( $args = array() ) {
// Primary key columns are always used as cache keys
if ( ! empty( $args['primary'] ) ) {
$args['cache_key'] = true;
// All UUID columns need to follow a very specific pattern
} elseif ( ! empty( $args['uuid'] ) ) {
$args['name'] = 'uuid';
$args['type'] = 'varchar';
$args['length'] = '100';
$args['in'] = false;
$args['not_in'] = false;
$args['searchable'] = false;
$args['sortable'] = false;
}
// Return args
return (array) $args;
}
/** Public Helpers ********************************************************/
/**
* Return if a column type is numeric or not.
*
* @since 3.0
* @access public
* @return boolean
*/
public function is_numeric() {
return $this->is_type( array(
'tinyint',
'int',
'mediumint',
'bigint'
) );
}
/** Private Helpers *******************************************************/
/**
* Return if this column is of a certain type.
*
* @since 3.0
*
* @param mixed $type The type to check. Accepts an array.
*
* @return boolean True if of type, False if not
*/
private function is_type( $type = '' ) {
// If string, cast to array
if ( is_string( $type ) ) {
$type = (array) $type;
}
// Make them lowercase
$types = array_map( 'strtolower', $type );
// Return if match or not
return (bool) in_array( strtolower( $this->type ), $types, true );
}
/** Private Sanitizers ****************************************************/
/**
* Sanitize capabilities array
*
* @since 3.0
*
* @param array $caps
*
* @return array
*/
private function sanitize_capabilities( $caps = array() ) {
return wp_parse_args( $caps, array(
'select' => 'exist',
'insert' => 'exist',
'update' => 'exist',
'delete' => 'exist'
) );
}
/**
* Sanitize aliases array using `sanitize_key()`
*
* @since 3.0.0
*
* @param array $aliases
*
* @return array
*/
private function sanitize_aliases( $aliases = array() ) {
return array_map( 'sanitize_key', $aliases );
}
/**
* Sanitize relationships array
*
* @since 3.0.0
*
* @param array $relationships
*
* @return array
*/
private function sanitize_relationships( $relationships = array() ) {
return array_filter( $relationships );
}
/**
* Sanitize default
*
* @since 3.4
*
* @param string $default
*
* @return string|null
*/
private function sanitize_default( $default = '' ) {
return is_null( $default ) ? null : wp_kses_data( $default );
}
/**
* Sanitize the pattern
*
* @since 3.0
*
* @param mixed $pattern
*
* @return string
*/
private function sanitize_pattern( $pattern = false ) {
// Allowed patterns
$allowed_patterns = array( '%s', '%d', '%f' );
// Return pattern if allowed
if ( in_array( $pattern, $allowed_patterns, true ) ) {
return $pattern;
}
// Fallback to digit or string
return $this->is_numeric()
? '%d'
: '%s';
}
/**
* Sanitize the validation callback
*
* @since 3.0
*
* @param string $callback A callable PHP function name or method
*
* @return string The most appropriate callback function for the value
*/
private function sanitize_validation( $callback = '' ) {
// Return callback if it's callable
if ( is_callable( $callback ) ) {
return $callback;
}
// UUID special column
if ( true === $this->uuid ) {
$callback = array( $this, 'validate_uuid' );
// Intval fallback
} elseif ( $this->is_type( array( 'tinyint', 'int' ) ) ) {
$callback = 'intval';
// Datetime fallback
} elseif ( $this->is_type( 'datetime' ) ) {
$callback = array( $this, 'validate_datetime' );
}
// Return the callback
return $callback;
}
/** Public Validators *****************************************************/
/**
* Fallback to validate a datetime value if no other is set.
*
* @since 3.0
*
* @param string $value A datetime value that needs validating
*
* @return string A valid datetime value
*/
public function validate_datetime( $value = '0000-00-00 00:00:00' ) {
// Fallback for empty values
if ( empty( $value ) || ( '0000-00-00 00:00:00' === $value ) ) {
$value = $this->default;
// Fallback if WordPress function exists
} elseif ( function_exists( 'date' ) ) {
$value = date( 'Y-m-d H:i:s', strtotime( $value ) );
}
// Return the validated value
return $value;
}
/**
* Validate a UUID
*
* This uses the v4 algorithm to generate a UUID that is used to uniquely
* and universally identify a given database row without any direct
* connection or correlation to the data in that row.
*
* From http://php.net/manual/en/function.uniqid.php#94959
*
* @since 3.0
*
* @param string $uuid The UUID value (empty on insert, string on update)
*
* @return string Generated UUID.
*/
public function validate_uuid( $uuid = '' ) {
// Bail if not empty (UUIDs should never change once they are set)
if ( ! empty( $uuid ) ) {
return $uuid;
}
// Default URN UUID prefix
$prefix = 'urn:uuid:';
// Put the pieces together
$uuid = sprintf( "{$prefix}%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
// 32 bits for "time_low"
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
// 16 bits for "time_mid"
mt_rand( 0, 0xffff ),
// 16 bits for "time_hi_and_version",
// four most significant bits holds version number 4
mt_rand( 0, 0x0fff ) | 0x4000,
// 16 bits, 8 bits for "clk_seq_hi_res",
// 8 bits for "clk_seq_low",
// two most significant bits holds zero and one for variant DCE1.1
mt_rand( 0, 0x3fff ) | 0x8000,
// 48 bits for "node"
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
);
// Return the new UUID
return $uuid;
}
}

View File

@@ -0,0 +1,157 @@
<?php
/**
* Base Custom Database Table Date Query Class.
*
* @package RCP
* @subpackage Database\Queries\Date
* @copyright Copyright (c) 2020
* @license https://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.0.0
*/
namespace RCP\Database\Queries;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Class used for generating SQL for compare clauses.
*
* This class is used to generate the SQL when a `compare` argument is passed to
* the `Base` query class. It extends `WP_Meta_Query` so the `compare` key accepts
* the same parameters as the ones passed to `WP_Meta_Query`.
*
* @since 1.0.0
*/
class Compare extends \WP_Meta_Query {
/**
* Generate SQL WHERE clauses for a first-order query clause.
*
* "First-order" means that it's an array with a 'key' or 'value'.
*
* @since 1.0.0
*
* @param array $clause Query clause (passed by reference).
* @param array $parent_query Parent query array.
* @param string $clause_key Optional. The array key used to name the clause in the original `$meta_query`
* parameters. If not provided, a key will be generated automatically.
* @return array {
* Array containing WHERE SQL clauses to append to a first-order query.
*
* @type string $where SQL fragment to append to the main WHERE clause.
* }
*/
public function get_sql_for_clause( &$clause, $parent_query, $clause_key = '' ) {
global $wpdb;
$sql_chunks = array(
'where' => array(),
'join' => array(),
);
if ( isset( $clause['compare'] ) ) {
$clause['compare'] = strtoupper( $clause['compare'] );
} else {
$clause['compare'] = isset( $clause['value'] ) && is_array( $clause['value'] ) ? 'IN' : '=';
}
if ( ! in_array(
$clause['compare'], array(
'=',
'!=',
'>',
'>=',
'<',
'<=',
'LIKE',
'NOT LIKE',
'IN',
'NOT IN',
'BETWEEN',
'NOT BETWEEN',
'EXISTS',
'NOT EXISTS',
'REGEXP',
'NOT REGEXP',
'RLIKE',
), true
) ) {
$clause['compare'] = '=';
}
if ( isset( $clause['compare_key'] ) && 'LIKE' === strtoupper( $clause['compare_key'] ) ) {
$clause['compare_key'] = strtoupper( $clause['compare_key'] );
} else {
$clause['compare_key'] = '=';
}
$compare = $clause['compare'];
$compare_key = $clause['compare_key'];
// Build the WHERE clause.
// Column name and value.
if ( array_key_exists( 'key', $clause ) && array_key_exists( 'value', $clause ) ) {
$column = sanitize_key( $clause['key'] );
$value = $clause['value'];
if ( in_array( $compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ), true ) ) {
if ( ! is_array( $value ) ) {
$value = preg_split( '/[,\s]+/', $value );
}
} else {
$value = trim( $value );
}
switch ( $compare ) {
case 'IN':
case 'NOT IN':
$compare_string = '(' . substr( str_repeat( ',%s', count( $value ) ), 1 ) . ')';
$where = $wpdb->prepare( $compare_string, $value );
break;
case 'BETWEEN':
case 'NOT BETWEEN':
$value = array_slice( $value, 0, 2 );
$where = $wpdb->prepare( '%s AND %s', $value );
break;
case 'LIKE':
case 'NOT LIKE':
$value = '%' . $wpdb->esc_like( $value ) . '%';
$where = $wpdb->prepare( '%s', $value );
break;
// EXISTS with a value is interpreted as '='.
case 'EXISTS':
$compare = '=';
$where = $wpdb->prepare( '%s', $value );
break;
// 'value' is ignored for NOT EXISTS.
case 'NOT EXISTS':
$where = '';
break;
default:
$where = $wpdb->prepare( '%s', $value );
break;
}
if ( $where ) {
$sql_chunks['where'][] = "{$column} {$compare} {$where}";
}
}
/*
* Multiple WHERE clauses (for meta_key and meta_value) should
* be joined in parentheses.
*/
if ( 1 < count( $sql_chunks['where'] ) ) {
$sql_chunks['where'] = array( '( ' . implode( ' AND ', $sql_chunks['where'] ) . ' )' );
}
return $sql_chunks;
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* Base Database Row Class.
*
* @package RCP
* @subpackage Database\Rows
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Base database row class.
*
* This class exists solely for other classes to extend (and to encapsulate
* database schema changes for those objects) to help separate the needs of the
* application layer from the requirements of the database layer.
*
* For example, if a database column is renamed or a return value needs to be
* formatted differently, this class will make sure old values are still
* supported and new values do not conflict.
*
* @since 3.0
*/
class Row extends Base {
/**
* Construct a database object
*
* @since 3.0
*
* @param mixed Null by default, Array/Object if not
*/
public function __construct( $item = null ) {
if ( ! empty( $item ) ) {
$this->init( $item );
}
}
/**
* Initialize class properties based on data array
*
* @since 3.0
*
* @param array $data
*/
private function init( $data = array() ) {
$this->set_vars( $data );
}
/**
* Determines whether the current row exists.
*
* @since 3.0
*
* @return boolean
*/
public function exists() {
return ! empty( $this->id );
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* Base Schema Class.
*
* @package RCP
* @subpackage Database\Schemas
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( '\\RCP\\Database\\Schema' ) ) :
/**
* A base WordPress database table class, which facilitates the creation of
* and schema changes to individual database tables.
*
* This class is intended to be extended for each unique database table,
* including global multisite tables and users tables.
*
* It exists to make managing database tables in WordPress as easy as possible.
*
* Extending this class comes with several automatic benefits:
* - Activation hook makes it great for plugins
* - Tables store their versions in the database independently
* - Tables upgrade via independent upgrade abstract methods
* - Multisite friendly - site tables switch on "switch_blog" action
*
* @since 3.0
*/
class Schema extends Base {
/**
* Array of database column objects to turn into Column
*
* @since 3.0
* @access public
* @var array
*/
protected $columns = array();
/**
* Invoke new column objects based on array of column data
*
* @since 3.0
* @access public
*/
public function __construct() {
// Bail if no columns
if ( empty( $this->columns ) || ! is_array( $this->columns ) ) {
return;
}
// Juggle original columns array
$columns = $this->columns;
$this->columns = array();
// Loop through columns and create objects from them
foreach ( $columns as $column ) {
if ( is_array( $column ) ) {
$this->columns[] = new Column( $column );
} elseif ( $column instanceof Column ) {
$this->columns[] = $column;
}
}
}
}
endif;

View File

@@ -0,0 +1,798 @@
<?php
/**
* Base Custom Database Table Class.
*
* @package RCP
* @subpackage Database\Tables
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( '\\RCP\\Database\\Tables\\Base' ) ) :
/**
* A base WordPress database table class, which facilitates the creation of
* and schema changes to individual database tables.
*
* This class is intended to be extended for each unique database table,
* including global multisite tables and users tables.
*
* It exists to make managing database tables in WordPress as easy as possible.
*
* Extending this class comes with several automatic benefits:
* - Activation hook makes it great for plugins
* - Tables store their versions in the database independently
* - Tables upgrade via independent upgrade abstract methods
* - Multisite friendly - site tables switch on "switch_blog" action
*
* @since 3.0
*/
abstract class Table extends Base {
/**
* @var string Table name, without the global table prefix
*/
protected $name = '';
/**
* @var string Optional description.
*/
protected $description = '';
/**
* @var mixed Database version in format YYYYMMDDX, where X starts at 1 each day and increments accordingly.
*/
protected $version = '';
/**
* @var boolean Is this table for a site, or global
*/
protected $global = false;
/**
* @var string Passed directly into register_activation_hook()
*/
protected $file = RCP_PLUGIN_FILE;
/**
* @var string Database version key (saved in _options or _sitemeta)
*/
protected $db_version_key = '';
/**
* @var mixed Current database version
*/
protected $db_version = 0;
/**
* @var string Table prefix, including the site prefix
*/
protected $table_prefix = '';
/**
* @var string Table name
*/
protected $table_name = '';
/**
* @var string Table name, prefixed from the base
*/
protected $prefixed_name = '';
/**
* @var string Table schema
*/
protected $schema = '';
/**
* @var string Database character-set & collation for table
*/
protected $charset_collation = '';
/**
* @var string The last error, if any.
*/
protected $last_error = '';
/**
* @var array Key => value array of versions => methods
*/
protected $upgrades = array();
/** Methods ***************************************************************/
/**
* Hook into queries, admin screens, and more!
*
* @since 3.0
*/
public function __construct() {
$this->global = (
is_plugin_active_for_network( plugin_basename( RCP_PLUGIN_FILE ) ) &&
(
! defined( 'RCP_NETWORK_SEPARATE_SITES') ||
! RCP_NETWORK_SEPARATE_SITES
)
);
// Setup the database table
$this->setup();
// Bail if setup failed
if ( empty( $this->name ) || empty( $this->db_version_key ) ) {
return;
}
// Add the table to the database interface
$this->set_db_interface();
// Set the database schema
$this->set_schema();
// Add hooks to WordPress actions
$this->add_hooks();
// Maybe force upgrade if testing
if ( $this->is_testing() ) {
$this->maybe_upgrade();
}
}
/** Abstract **************************************************************/
/**
* Setup this database table
*
* @since 3.0
*/
protected abstract function set_schema();
/** Multisite *************************************************************/
/**
* Update table version & references.
*
* Hooked to the "switch_blog" action.
*
* @since 3.0
*
* @param int $site_id The site being switched to
*/
public function switch_blog( $site_id = 0 ) {
remove_action( 'switch_blog', array( $this, 'switch_blog' ) );
/*
* Bail if the new site's database tables haven't been installed yet.
* This prevents errors when using `get_blog_option` below.
*/
if ( function_exists( 'wp_is_site_initialized' ) && ! wp_is_site_initialized( $site_id ) ) {
return;
}
add_action( 'switch_blog', array( $this, 'switch_blog' ) );
// Update DB version based on the current site
if ( ! $this->is_global() ) {
$this->db_version = get_blog_option( $site_id, $this->db_version_key, false );
}
// Update interface for switched site
$this->set_db_interface();
}
/** Public Helpers ********************************************************/
/**
* Maybe upgrade the database table. Handles creation & schema changes.
*
* Hooked to the `admin_init` action.
*
* @since 3.0
*/
public function maybe_upgrade() {
// Bail if not upgradeable
if ( ! $this->is_upgradeable() ) {
return;
}
// Bail if upgrade not needed
if ( ! $this->needs_upgrade() ) {
return;
}
// Upgrade
if ( $this->exists() ) {
$this->upgrade();
// Install
} else {
$this->install();
}
}
/**
* Return whether this table needs an upgrade.
*
* @since 3.0
*
* @param mixed $version Database version to check if upgrade is needed
*
* @return boolean True if table needs upgrading. False if not.
*/
public function needs_upgrade( $version = false ) {
// Use the current table version if none was passed
if ( empty( $version ) ) {
$version = $this->version;
}
// Get the current database version
$this->get_db_version();
// Is the database table up to date?
$is_current = version_compare( $this->db_version, $version, '>=' );
// Return false if current, true if out of date
return ( true === $is_current )
? false
: true;
}
/**
* Return whether this table can be upgraded.
*
* @since 3.0
*
* @return boolean True if table can be upgraded. False if not.
*/
public function is_upgradeable() {
if ( ! function_exists( 'wp_should_upgrade_global_tables' ) ) {
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
}
// Bail if global and upgrading global tables is not allowed
if ( $this->is_global() && ! wp_should_upgrade_global_tables() ) {
return false;
}
// Kinda weird, but assume it is
return true;
}
/**
* Return the current table version from the database.
*
* This is public method for accessing a private variable so that it cannot
* be externally modified.
*
* @since 3.0
*
* @return string
*/
public function get_version() {
$this->get_db_version();
return $this->db_version;
}
/**
* Returns the name of the table.
*
* @return string
*/
public function get_table_name() {
return $this->table_name;
}
/**
* Install a database table by creating the table and setting the version.
*
* @since 3.0
*/
public function install() {
$created = $this->create();
// Set the DB version if create was successful
if ( true === $created ) {
$this->set_db_version();
}
}
/**
* Destroy a database table by dropping the table and deleting the version.
*
* @since 3.0
*/
public function uninstall() {
$dropped = $this->drop();
// Delete the DB version if drop was successful
if ( true === $dropped ) {
$this->delete_db_version();
}
}
/** Public Management *****************************************************/
/**
* Check if table already exists
*
* @since 3.0
*
* @return bool
*/
public function exists() {
// Get the database interface
$db = $this->get_db();
// Bail if no database interface is available
if ( empty( $db ) ) {
return;
}
// Query statement
$query = "SHOW TABLES LIKE %s";
$like = $db->esc_like( $this->table_name );
$prepared = $db->prepare( $query, $like );
$result = $db->get_var( $prepared );
// Does the table exist?
return $this->is_success( $result );
}
/**
* Check if table already exists
*
* @since 3.0
*
* @return bool
*/
public function column_exists( $name = '' ) {
// Get the database interface
$db = $this->get_db();
// Bail if no database interface is available
if ( empty( $db ) ) {
return;
}
// Query statement
$query = "SHOW COLUMNS FROM {$this->table_name} LIKE %s";
$like = $db->esc_like( $name );
$prepared = $db->prepare( $query, $like );
$result = $db->query( $prepared );
// Does the table exist?
return $this->is_success( $result );
}
/**
* Create the table
*
* @since 3.0
*
* @return bool
*/
public function create() {
// Get the database interface
$db = $this->get_db();
// Bail if no database interface is available
if ( empty( $db ) ) {
return;
}
// Query statement
$query = "CREATE TABLE {$this->table_name} ( {$this->schema} ) {$this->charset_collation};";
$result = $db->query( $query );
// Was the table created?
return $this->is_success( $result );
}
/**
* Drop the database table
*
* @since 3.0
*
* @return mixed
*/
public function drop() {
// Get the database interface
$db = $this->get_db();
// Bail if no database interface is available
if ( empty( $db ) ) {
return;
}
// Query statement
$query = "DROP TABLE {$this->table_name}";
$result = $db->query( $query );
// Query success/fail
return $this->is_success( $result );
}
/**
* Truncate the database table
*
* @since 3.0
*
* @return mixed
*/
public function truncate() {
// Get the database interface
$db = $this->get_db();
// Bail if no database interface is available
if ( empty( $db ) ) {
return;
}
// Query statement
$query = "TRUNCATE TABLE {$this->table_name}";
$result = $db->query( $query );
// Query success/fail
return $this->is_success( $result );
}
/**
* Delete all items from the database table
*
* @since 3.0
*
* @return mixed
*/
public function delete_all() {
// Get the database interface
$db = $this->get_db();
// Bail if no database interface is available
if ( empty( $db ) ) {
return;
}
// Query statement
$query = "DELETE FROM {$this->table_name}";
$deleted = $db->query( $query );
// Query success/fail
return $deleted;
}
/**
* Count the number of items in the database table
*
* @since 3.0
*
* @return mixed
*/
public function count() {
// Get the database interface
$db = $this->get_db();
// Bail if no database interface is available
if ( empty( $db ) ) {
return;
}
// Query statement
$query = "SELECT COUNT(*) FROM {$this->table_name}";
$count = $db->get_var( $query );
// Query success/fail
return $count;
}
/** Upgrades **************************************************************/
/**
* Upgrade this database table
*
* @since 3.0
*
* return boolean
*/
public function upgrade() {
$result = false;
// Remove all upgrades that have already been completed
$upgrades = array_filter( (array) $this->upgrades, function( $value ) {
return version_compare( $value, $this->db_version, '>' );
} );
// Bail if no upgrades or database version is missing
if ( empty( $upgrades ) || empty( $this->db_version ) ) {
$this->set_db_version();
return true;
}
// Try to do all known upgrades
foreach ( $upgrades as $version => $method ) {
$result = $this->upgrade_to( $version, $method );
// Bail if an error occurs, to avoid skipping ahead
if ( ! $this->is_success( $result ) ) {
return false;
}
}
// Success/fail
return $this->is_success( $result );
}
/**
* Upgrade to a specific database version
*
* @since 3.0
*
* @param mixed $version Database version to check if upgrade is needed
* @param string $method
*
* @return boolean
*/
public function upgrade_to( $version = '', $method = '' ) {
// Bail if no upgrade is needed
if ( ! $this->needs_upgrade( $version ) ) {
return false;
}
// Allow self-named upgrade methods
if ( empty( $method ) ) {
$method = $version;
}
// Is the method callable?
$callable = $this->get_callable( $method );
// Bail if no callable upgrade method was found
if ( empty( $callable ) ) {
return false;
}
// Do the upgrade
$result = call_user_func( $callable );
$success = $this->is_success( $result );
// Bail if upgrade failed
if ( true !== $success ) {
return false;
}
// Set the database version to this successful version
$this->set_db_version( $version );
// Return success
return true;
}
/** Private ***************************************************************/
/**
* Setup the necessary table variables
*
* @since 3.0
*/
private function setup() {
// Bail if no database interface is available
if ( ! $this->get_db() ) {
return;
}
// Sanitize the database table name
$this->name = $this->sanitize_table_name( $this->name );
// Bail if database table name was garbage
if ( false === $this->name ) {
return;
}
// Setup the prefixed name
$this->prefixed_name = $this->apply_prefix( $this->name );
// Maybe create database key
if ( empty( $this->db_version_key ) ) {
$this->db_version_key = "wpdb_{$this->prefixed_name}_version";
}
}
/**
* Set this table up in the database interface, usually the $wpdb global.
*
* This must be done directly because WordPress does not have a mechanism
* for manipulating them safely
*
* @since 3.0
*/
protected function set_db_interface() {
// Get the database once, to avoid duplicate function calls
$db = $this->get_db();
// Bail if no database
if ( empty( $db ) ) {
return;
}
// Set variables for global tables
if ( $this->is_global() ) {
$site_id = 0;
$tables = 'ms_global_tables';
// Set variables for per-site tables
} else {
$site_id = null;
$tables = 'tables';
}
// Set the table prefix and prefix the table name
$this->table_prefix = $db->get_blog_prefix( $site_id );
// Get the prefixed table name
$prefixed_table_name = "{$this->table_prefix}{$this->prefixed_name}";
// Set the database interface
$db->{$this->prefixed_name} = $this->table_name = $prefixed_table_name;
// Create the array if it does not exist
if ( ! isset( $db->{$tables} ) ) {
$db->{$tables} = array();
}
// Add the table to the global table array
$db->{$tables}[] = $this->prefixed_name;
// Charset
if ( ! empty( $db->charset ) ) {
$this->charset_collation = "DEFAULT CHARACTER SET {$db->charset}";
}
// Collation
if ( ! empty( $db->collate ) ) {
$this->charset_collation .= " COLLATE {$db->collate}";
}
}
/**
* Set the database version for the table
*
* @since 3.0
*
* @param mixed $version Database version to set when upgrading/creating
*/
private function set_db_version( $version = '' ) {
// If no version is passed during an upgrade, use the current version
if ( empty( $version ) ) {
$version = $this->version;
}
// Update the DB version
$this->is_global()
? update_network_option( get_main_network_id(), $this->db_version_key, $version )
: update_option( $this->db_version_key, $version );
// Set the DB version
$this->db_version = $version;
}
/**
* Get the table version from the database
*
* @since 3.0
*/
private function get_db_version() {
$this->db_version = $this->is_global()
? get_network_option( get_main_network_id(), $this->db_version_key, false )
: get_option( $this->db_version_key, false );
}
/**
* Delete the table version from the database
*
* @since 3.0
*/
private function delete_db_version() {
$this->db_version = $this->is_global()
? delete_network_option( get_main_network_id(), $this->db_version_key, false )
: delete_option( $this->db_version_key, false );
}
/**
* Add class hooks to WordPress actions
*
* @since 3.0
*/
private function add_hooks() {
// Activation hook
register_activation_hook( $this->file, array( $this, 'maybe_upgrade' ) );
// Add table to the global database object
add_action( 'switch_blog', array( $this, 'switch_blog' ) );
add_action( 'admin_init', array( $this, 'maybe_upgrade' ), -99999 );
}
/**
* Check if the current request is from some kind of test.
*
* This is primarily used to skip 'admin_init' and force-install tables.
*
* @since 3.0
*
* @return bool
*/
private function is_testing() {
return (bool)
// Tests constant is being used
( defined( 'WP_TESTS_DIR' ) && WP_TESTS_DIR )
||
// Scaffolded (https://make.wordpress.org/cli/handbook/plugin-unit-tests/)
function_exists( '_manually_load_plugin' );
}
/**
* Check if table is global
*
* @since 3.0
*
* @return bool
*/
protected function is_global() {
return ( true === $this->global );
}
/**
* Try to get a callable upgrade method, with some magic to avoid needing to
* do this dance repeatedly inside subclasses.
*
* @since 3.0
*
* @param string $method
* @return boolean
*/
private function get_callable( $method = '' ) {
$callable = $method;
// Look for global function
if ( ! is_callable( $callable ) ) {
$callable = array( $this, $method );
// Look for local class method
if ( ! is_callable( $callable ) ) {
$callable = array( $this, "__{$method}" );
// Look for method prefixed with "__"
if ( ! is_callable( $callable ) ) {
$callable = false;
}
}
}
// Return callable, if any
return $callable;
}
}
endif;

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,148 @@
<?php
/**
* Logs Query Class.
*
* @package RCP
* @subpackage Database\Queries
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.4
*/
namespace RCP\Database\Queries;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Query;
/**
* Class used for querying the logs table.
*
* @since 3.4
*
* @see \RCP\Database\Queries\Log::__construct() for accepted arguments.
*/
class Log extends Query {
/** Table Properties ******************************************************/
/**
* Name of the database table to query.
*
* @since 3.4
* @access public
* @var string
*/
protected $table_name = 'logs';
/**
* String used to alias the database table in MySQL statement.
*
* @since 3.4
* @access public
* @var string
*/
protected $table_alias = 'log';
/**
* Name of class used to setup the database schema
*
* @since 3.4
* @access public
* @var string
*/
protected $table_schema = '\\RCP\\Database\\Schemas\\Logs';
/** Item ******************************************************************/
/**
* Name for a single item
*
* @since 3.4
* @access public
* @var string
*/
protected $item_name = 'log';
/**
* Plural version for a group of items.
*
* @since 3.4
* @access public
* @var string
*/
protected $item_name_plural = 'logs';
/**
* Callback function for turning IDs into objects
*
* @since 3.4
* @access public
* @var mixed
*/
protected $item_shape = '\\RCP\\Logs\\Log';
/**
* Group to cache queries and queried items in.
*
* @since 3.0
* @access public
* @var string
*/
protected $cache_group = 'logs';
/**
* Sets up the log query, based on the query vars passed.
*
* @since 3.4
* @access public
*
* @param string|array $query {
* Optional. Array or query string of query parameters. Default empty.
*
* @type int $id An log ID to only return that order. Default empty.
* @type array $id__in Array of log IDs to include. Default empty.
* @type array $id__not_in Array of log IDs to exclude. Default empty.
* @type string $object_id An object ID to only return those objects. Default empty.
* @type array $object_id__in Array of object IDs to include. Default empty.
* @type array $object_id__not_in Array of IDs object to exclude. Default empty.
* @type string $object_type An object types to only return that type. Default empty.
* @type array $object_type__in Array of object types to include. Default empty.
* @type array $object_type__not_in Array of object types to exclude. Default empty.
* @type string $user_id A user ID to only return those users. Default empty.
* @type array $user_id__in Array of user IDs to include. Default empty.
* @type array $user_id__not_in Array of user IDs to exclude. Default empty.
* @type string $type A type to only return those types. Default empty.
* @type array $type__in Array of types to include. Default empty.
* @type array $type__not_in Array of types to exclude. Default empty.
* @type array $title Title to search by. Default empty.
* @type array $content Content to search by. Default empty.
* @type int $is_error Filter by error status. Default empty.
* @type array $date_query Query all datetime columns together. See WP_Date_Query.
* @type array $date_created_query Date query clauses to limit by. See WP_Date_Query.
* Default null.
* @type array $date_modified_query Date query clauses to limit by. See WP_Date_Query.
* Default null.
* @type bool $count Whether to return a count (true) or array of objects.
* Default false.
* @type string $fields Item fields to return. Accepts any column known names
* or empty (returns an array of complete objects). Default empty.
* @type int $number Limit number of logs to retrieve. Default 100.
* @type int $offset Number of logs to offset the query. Used to build LIMIT clause.
* Default 0.
* @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true.
* @type string|array $orderby Accepts 'id', 'object_id', 'object_type', 'user_id', 'type',
* 'title', 'is_error', 'date_created', and 'date_modified'.
* Also accepts false, an empty array, or 'none' to disable `ORDER BY`
* clause. Default 'id'.
* @type string $order How to order results. Accepts 'ASC', 'DESC'. Default 'DESC'.
* @type string $search Search term(s) to retrieve matching logs for. Default empty.
* @type bool $update_cache Whether to prime the cache for found logs. Default false.
* }
*/
public function __construct( $query = array() ) {
parent::__construct( $query );
}
}

View File

@@ -0,0 +1,148 @@
<?php
/**
* Logs Schema Class.
*
* @package RCP
* @subpackage Database\Schemas
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.4
*/
namespace RCP\Database\Schemas;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Schema;
/**
* Logs Schema Class.
*
* @since 3.4
*/
class Logs extends Schema {
/**
* Array of database column objects
*
* @since 3.4
* @access public
* @var array
*/
public $columns = array(
// id
array(
'name' => 'id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'extra' => 'auto_increment',
'primary' => true,
'sortable' => true
),
// object_type
array(
'name' => 'object_type',
'type' => 'varchar',
'length' => '20',
'default' => '',
'sortable' => true,
'cache_key' => true,
),
// object_id
array(
'name' => 'object_id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'default' => null,
'allow_null' => true,
'sortable' => true,
'cache_key' => true,
),
// user_id
array(
'name' => 'user_id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'default' => null,
'allow_null' => true,
'sortable' => true,
'cache_key' => true,
),
// type
array(
'name' => 'type',
'type' => 'varchar',
'length' => '20',
'default' => '',
'sortable' => true
),
// title
array(
'name' => 'title',
'type' => 'varchar',
'length' => '200',
'default' => '',
'searchable' => true,
'sortable' => true,
'in' => false,
'not_in' => false
),
// content
array(
'name' => 'content',
'type' => 'longtext',
'default' => '',
'searchable' => true,
'in' => false,
'not_in' => false
),
// is_error
array(
'name' => 'is_error',
'type' => 'tinyint',
'length' => '1',
'unsigned' => true,
'default' => 0,
'sortable' => true,
),
// date_created
array(
'name' => 'date_created',
'type' => 'datetime',
'default' => '',
'created' => true,
'date_query' => true,
'sortable' => true
),
// date_modified
array(
'name' => 'date_modified',
'type' => 'datetime',
'default' => '',
'modified' => true,
'date_query' => true,
'sortable' => true
),
// uuid
array(
'uuid' => true,
)
);
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* Logs Table.
*
* @package RCP
* @subpackage Database\Tables
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.4
*/
namespace RCP\Database\Tables;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Table;
/**
* Setup the "rcp_logs" database table
*
* @since 3.4
*/
final class Logs extends Table {
/**
* @var string Table name
*/
protected $name = 'logs';
/**
* @var string Database version
*/
protected $version = 202003051;
/**
* @var array Array of upgrade versions and methods
*/
protected $upgrades = array();
/**
* Setup the database schema
*
* @access protected
* @since 3.4
* @return void
*/
protected function set_schema() {
$this->schema = "id int unsigned NOT NULL AUTO_INCREMENT,
object_type varchar(20) NOT NULL,
object_id bigint(20) UNSIGNED DEFAULT NULL,
user_id bigint(20) UNSIGNED DEFAULT NULL,
type varchar(20) NOT NULL,
title varchar(200) NOT NULL,
content longtext NOT NULL,
is_error tinyint(1) NOT NULL DEFAULT 0,
date_created datetime NOT NULL,
date_modified datetime NOT NULL,
uuid varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY (id),
KEY object_id_object_type (object_id, object_type),
KEY user_id (user_id),
KEY type (type)";
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,137 @@
<?php
/**
* Membership Count Query Class.
*
* @package RCP
* @subpackage Database\Queries
* @copyright Copyright (c) 2019, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.3
*/
namespace RCP\Database\Queries;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Query;
/**
* Class used for querying memberships.
*
* @since 3.3
*
* @see \RCP\Database\Queries\Membership_Count::__construct() for accepted arguments.
*/
class Membership_Count extends Query {
/** Table Properties ******************************************************/
/**
* Name of the database table to query.
*
* @since 3.3
* @access public
* @var string
*/
protected $table_name = 'membership_counts';
/**
* String used to alias the database table in MySQL statement.
*
* @since 3.3
* @access public
* @var string
*/
protected $table_alias = 'mc';
/**
* Name of class used to setup the database schema
*
* @since 3.3
* @access public
* @var string
*/
protected $table_schema = '\\RCP\\Database\\Schemas\\Membership_Counts';
/** Item ******************************************************************/
/**
* Name for a single item
*
* @since 3.3
* @access public
* @var string
*/
protected $item_name = 'membership_count';
/**
* Plural version for a group of items.
*
* @since 3.0
* @access public
* @var string
*/
protected $item_name_plural = 'membership_counts';
/**
* Callback function for turning IDs into objects
*
* @since 3.3
* @access public
* @var mixed
*/
protected $item_shape = '\\RCP_Membership_Count';
/**
* Group to cache queries and queried items in.
*
* @since 3.0
* @access public
* @var string
*/
protected $cache_group = 'membership_counts';
/**
* Sets up the membership count query, based on the query vars passed.
*
* @since 3.3
* @access public
*
* @param string|array $query {
* Optional. Array or query string of membership count query
* parameters. Default empty.
*
* @type int $id An entry ID to only return that entry. Default empty.
* @type array $id__in Array of entry IDs to include. Default empty.
* @type array $id__not_in Array of entry IDs to exclude. Default empty.
* @type int $level_id A level ID to only return this level's entries. Default
* empty.
* @type array $level_id__in Array of level IDs to include. Default empty.
* @type array $level_id__not_in Array of level IDs to exclude. Default empty.
* @type array $date_query Query all datetime columns together. See WP_Date_Query.
* @type array $created_date_query Date query clauses to limit entries by. See WP_Date_Query.
* Default null.
* @type bool $count Whether to return an entry count (true) or array of entry
* objects. Default false.
* @type string $fields Item fields to return. Accepts any column known names
* or empty (returns an array of complete entry objects). Default
* empty.
* @type int $number Limit number of entries to retrieve. Default 100.
* @type int $offset Number of entries to offset the query. Used to build LIMIT
* clause. Default 0.
* @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true.
* @type string|array $orderby Accepts 'id', 'level_id', 'active_count', 'pending_count',
* `cancelled_count`, `expired_count`, and `date_created`.
* Also accepts false, an empty array, or 'none' to disable
* `ORDER BY` clause. Default 'id'.
* @type string $order How to order results. Accepts 'ASC', 'DESC'. Default 'DESC'.
* @type string $search Search term(s) to retrieve matching entries for. Default empty.
* @type bool $update_cache Whether to prime the cache for found entries. Default false.
* }
*/
public function __construct( $query = array() ) {
parent::__construct( $query );
}
}

View File

@@ -0,0 +1,113 @@
<?php
/**
* Membership Counts Schema Class.
*
* @package RCP
* @subpackage Database\Schemas
* @copyright Copyright (c) 2019, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.3
*/
namespace RCP\Database\Schemas;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Schema;
/**
* Membership Counts Schema Class.
*
* @since 3.3
*/
class Membership_Counts extends Schema {
/**
* Array of database column objects
*
* @since 3.3
* @access public
* @var array
*/
public $columns = array(
// id
array(
'name' => 'id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'extra' => 'auto_increment',
'primary' => true,
'sortable' => true
),
// level_id
array(
'name' => 'level_id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'sortable' => true,
'default' => 0
),
// active_count
array(
'name' => 'active_count',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'sortable' => true,
'default' => 0
),
// pending_count
array(
'name' => 'pending_count',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'sortable' => true,
'default' => 0
),
// cancelled_count
array(
'name' => 'cancelled_count',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'sortable' => true,
'default' => 0
),
// expired_count
array(
'name' => 'expired_count',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'sortable' => true,
'default' => 0
),
// date_created
array(
'name' => 'date_created',
'type' => 'datetime',
'default' => '',
'created' => true,
'date_query' => true,
'sortable' => true
),
// uuid
array(
'uuid' => true,
)
);
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* Membership Counts Table.
*
* @package RCP
* @subpackage Database\Tables
* @copyright Copyright (c) 2019, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.3
*/
namespace RCP\Database\Tables;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Table;
/**
* Setup the "rcp_membership_counts" database table
*
* @since 3.3
*/
final class Membership_Counts extends Table {
/**
* @var string Table name
*/
protected $name = 'membership_counts';
/**
* @var string Database version
*/
protected $version = 202003311;
/**
* @var array Array of upgrade versions and methods
*/
protected $upgrades = array(
'202003311' => 202003311
);
/**
* Membership_Counts constructor.
*
* @access public
* @since 3.3
* @return void
*/
public function __construct() {
parent::__construct();
}
/**
* Setup the database schema
*
* @access protected
* @since 3.3
* @return void
*/
protected function set_schema() {
$this->schema = "id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
level_id bigint(20) unsigned NOT NULL DEFAULT 0,
active_count bigint(20) unsigned NOT NULL DEFAULT 0,
pending_count bigint(20) unsigned NOT NULL DEFAULT 0,
cancelled_count bigint(20) unsigned NOT NULL DEFAULT 0,
expired_count bigint(20) unsigned NOT NULL DEFAULT 0,
date_created datetime NOT NULL,
uuid varchar(100) NOT NULL default '',
PRIMARY KEY (id),
KEY date_created (date_created)";
}
/**
* Upgrade to version 202003311
* - Remove default `date_created` value
*/
protected function __202003311() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY date_created datetime NOT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003311 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003311 failure.', $this->get_table_name() ), true );
}
return $success;
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,143 @@
<?php
/**
* Membership Level Query Class.
*
* @package RCP
* @subpackage Database\Queries
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.4
*/
namespace RCP\Database\Queries;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Query;
/**
* Class used for querying membership levels.
*
* @since 3.4
*
* @see \RCP\Database\Queries\Membership_Level::__construct() for accepted arguments.
*/
class Membership_Level extends Query {
/**
* We have to override this to strip out the `rcp_` prefix. This table doesn't have that.
*
* @var string Table prefix
*/
protected $prefix = '';
/** Table Properties ******************************************************/
/**
* Name of the database table to query.
*
* @since 3.4
* @access public
* @var string
*/
protected $table_name = 'restrict_content_pro';
/**
* String used to alias the database table in MySQL statement.
*
* @since 3.4
* @access public
* @var string
*/
protected $table_alias = 'ml';
/**
* Name of class used to setup the database schema
*
* @since 3.4
* @access public
* @var string
*/
protected $table_schema = '\\RCP\\Database\\Schemas\\Membership_Levels';
/** Item ******************************************************************/
/**
* Name for a single item
*
* @since 3.4
* @access public
* @var string
*/
protected $item_name = 'membership_level';
/**
* Plural version for a group of items.
*
* @since 3.4
* @access public
* @var string
*/
protected $item_name_plural = 'membership_levels';
/**
* Callback function for turning IDs into objects
*
* @since 3.4
* @access public
* @var mixed
*/
protected $item_shape = '\\RCP\\Membership_Level';
/**
* Group to cache queries and queried items in.
*
* @since 3.4
* @access public
* @var string
*/
protected $cache_group = 'membership_levels';
/**
* Sets up the membership level query, based on the query vars passed.
*
* @since 3.4
* @access public
*
* @param string|array $query {
* Optional. Array or query string of level query parameters.
* Default empty.
*
* @type int $id A level ID to only return that level. Default empty.
* @type array $id__in Array of level IDs to include. Default empty.
* @type array $id__not_in Array of level IDs to exclude. Default empty.
* @type string $name Specific level name to retrieve. Default empty.
* @type string $status Status to filter by. Default empty.
* @type array $date_query Query all datetime columns together. See WP_Date_Query.
* @type array $date_created_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type array $date_modified_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type bool $count Whether to return a level count (true) or array of level
* objects. Default false.
* @type string $fields Item fields to return. Accepts any column known names
* or empty (returns an array of complete level objects). Default
* empty.
* @type int $number Limit number of levels to retrieve. Default 100.
* @type int $offset Number of levels to offset the query. Used to build LIMIT
* clause. Default 0.
* @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true.
* @type string|array $orderby Accepts 'id', 'name', 'duration', 'trial_duration',
* 'maximum_renewals', 'list_order', 'level', 'status',
* 'date_created', and 'date_modified'. Also accepts
* false, an empty array, or 'none' to disable `ORDER BY` clause.
* Default 'id'.
* @type string $order How to order results. Accepts 'ASC', 'DESC'. Default 'DESC'.
* @type string $search Search term(s) to retrieve matching levels for. Default empty.
* @type bool $update_cache Whether to prime the cache for found levels. Default false.
* }
*/
public function __construct( $query = array() ) {
parent::__construct( $query );
}
}

View File

@@ -0,0 +1,202 @@
<?php
/**
* Membership Levels Schema Class.
*
* @package RCP
* @subpackage Database\Schemas
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.4
*/
namespace RCP\Database\Schemas;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Schema;
/**
* Membership Levels Schema Class.
*
* @since 3.4
*/
class Membership_Levels extends Schema {
/**
* Array of database column objects
*
* @since 3.4
* @access public
* @var array
*/
public $columns = array(
// id
array(
'name' => 'id',
'type' => 'bigint',
'length' => '9',
'unsigned' => true,
'extra' => 'auto_increment',
'primary' => true,
'sortable' => true
),
// name
array(
'name' => 'name',
'type' => 'varchar',
'length' => '200',
'default' => '',
'sortable' => true,
'searchable' => true,
'validate' => 'sanitize_text_field'
),
// description
array(
'name' => 'description',
'type' => 'longtext',
'default' => '',
'searchable' => true,
'validate' => 'wp_kses_post'
),
// duration
array(
'name' => 'duration',
'type' => 'smallint',
'unsigned' => true,
'default' => 0,
'sortable' => true,
'validate' => 'absint'
),
// duration_unit
array(
'name' => 'duration_unit',
'type' => 'tinytext',
'default' => '',
'validate' => '_rcp_sanitize_duration_unit'
),
// trial_duration
array(
'name' => 'trial_duration',
'type' => 'smallint',
'unsigned' => true,
'default' => 0,
'sortable' => true,
'validate' => 'absint'
),
// trial_duration_unit
array(
'name' => 'trial_duration_unit',
'type' => 'tinytext',
'default' => '',
'validate' => '_rcp_sanitize_duration_unit'
),
// price
array(
'name' => 'price',
'type' => 'tinytext',
'default' => '',
'validate' => 'sanitize_text_field'
),
// fee
array(
'name' => 'fee',
'type' => 'tinytext',
'default' => '',
'validate' => 'sanitize_text_field'
),
// maximum_renewals
array(
'name' => 'maximum_renewals',
'type' => 'smallint',
'unsigned' => true,
'default' => 0,
'sortable' => true,
'validate' => 'absint'
),
// after_final_payment
array(
'name' => 'after_final_payment',
'type' => 'tinytext',
'default' => '',
'validate' => 'sanitize_text_field'
),
// list_order
array(
'name' => 'list_order',
'type' => 'mediumint',
'unsigned' => true,
'default' => 0,
'sortable' => true,
'validate' => 'absint'
),
// level
array(
'name' => 'level',
'type' => 'mediumint',
'unsigned' => true,
'default' => 0,
'sortable' => true,
'validate' => 'absint'
),
// status
array(
'name' => 'status',
'type' => 'varchar',
'length' => '12',
'default' => '',
'sortable' => true,
'transition' => true,
'validate' => 'sanitize_text_field'
),
// role
array(
'name' => 'role',
'type' => 'tinytext',
'default' => '',
'validate' => 'sanitize_text_field'
),
// date_created
array(
'name' => 'date_created',
'type' => 'datetime',
'default' => '', // Defaults to current datetime in query class.
'created' => true,
'date_query' => true,
'sortable' => true,
),
// date_modified
array(
'name' => 'date_modified',
'type' => 'datetime',
'default' => '', // Defaults to current datetime in query class.
'modified' => true,
'date_query' => true,
'sortable' => true,
),
// uuid
array(
'uuid' => true,
)
);
}

View File

@@ -0,0 +1,390 @@
<?php
/**
* Membership Levels Table.
*
* @package RCP
* @subpackage Database\Tables
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.4
*/
namespace RCP\Database\Tables;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Table;
/**
* Setup the "wp_restrict_content_pro" database table
*
* @since 3.4
*/
final class Membership_Levels extends Table {
/**
* We have to override this to strip out the `rcp_` prefix. This table doesn't have that.
*
* @var string Table prefix
*/
protected $prefix = '';
/**
* @var string Table name
*/
protected $name = 'restrict_content_pro';
/**
* @var string Database version
*/
protected $version = 202003093;
/**
* @var array Array of upgrade versions and methods
*/
protected $upgrades = array(
'202003091' => 202003091,
'202003092' => 202003092,
'202003093' => 202003093,
'202008061' => 202008061,
'202008062' => 202008062,
'202009251' => 202009251,
'202009252' => 202009252
);
/**
* Membership_Levels constructor.
*
* Get the table name from `rcp_get_levels_db_name()`. This is for backwards compatibility because that
* function contains a filter.
*/
public function __construct() {
$this->table_name = str_replace( $this->get_db()->prefix, '', rcp_get_levels_db_name() );
return parent::__construct();
}
/**
* Setup the database schema
*
* @access protected
* @since 3.4
* @return void
*/
protected function set_schema() {
$this->schema = "id bigint(9) UNSIGNED NOT NULL AUTO_INCREMENT,
name varchar(200) NOT NULL,
description longtext NOT NULL,
duration smallint UNSIGNED NOT NULL DEFAULT 0,
duration_unit tinytext NOT NULL,
trial_duration smallint(6) UNSIGNED NOT NULL DEFAULT 0,
trial_duration_unit tinytext NOT NULL,
price tinytext NOT NULL,
fee tinytext NOT NULL,
maximum_renewals smallint UNSIGNED NOT NULL DEFAULT 0,
after_final_payment tinytext NOT NULL,
level mediumint UNSIGNED NOT NULL DEFAULT 0,
role tinytext NOT NULL,
status varchar(12) NOT NULL DEFAULT 'active',
list_order mediumint UNSIGNED NOT NULL DEFAULT 0,
date_created datetime NOT NULL,
date_modified datetime NOT NULL,
uuid varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY (id),
KEY name (name(191)),
KEY status (status)";
}
/**
* This method is overridden to allow us to change the generated database name. This is necessary due to
* a long-standing error where network enabled installs have an incorrect table name.
* This also allows us to apply our old filter to the table name.
*
* @link https://github.com/restrictcontentpro/restrict-content-pro/issues/1478
*
* @since 3.4
*/
protected function set_db_interface() {
// Get the database once, to avoid duplicate function calls
$db = $this->get_db();
// Bail if no database
if ( empty( $db ) ) {
return;
}
// Set variables for global tables
if ( $this->is_global() ) {
$site_id = 0;
$tables = 'ms_global_tables';
// Set variables for per-site tables
} else {
$site_id = null;
$tables = 'tables';
}
/*
* Set the table prefix and prefix the table name
*
* We've overridden the table prefix for this table because of a long-standing error where network
* enabled installs have an incorrect table name.
*
* @link https://github.com/restrictcontentpro/restrict-content-pro/issues/1478
*/
$this->table_prefix = ! $this->is_global() ? $db->get_blog_prefix( $site_id ) : '';
// Get the prefixed table name
$prefixed_table_name = rcp_get_levels_db_name();
// Set the database interface
$db->{$this->prefixed_name} = $this->table_name = $prefixed_table_name;
// Create the array if it does not exist
if ( ! isset( $db->{$tables} ) ) {
$db->{$tables} = array();
}
// Add the table to the global table array
$db->{$tables}[] = $this->prefixed_name;
// Charset
if ( ! empty( $db->charset ) ) {
$this->charset_collation = "DEFAULT CHARACTER SET {$db->charset}";
}
// Collation
if ( ! empty( $db->collate ) ) {
$this->charset_collation .= " COLLATE {$db->collate}";
}
}
/**
* Ensure existing installs prior to 3.4 get upgraded.
*
* @since 3.4
*/
public function maybe_upgrade() {
if ( false !== get_option( 'rcp_membership_level_db' ) ) {
update_option( $this->db_version_key, 1 );
delete_option( 'rcp_membership_level_db' );
}
return parent::maybe_upgrade();
}
/**
* Upgrade to 202003091
* - Add `date_created` column.
*
* @since 3.4
* @return bool
*/
protected function __202003091() {
// Look for column
$result = $this->column_exists( 'date_created' );
// Add column if it doesn't exist.
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN date_created datetime NOT NULL;" );
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003091 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003091 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to 202003092
* - Add `date_created` column.
*
* @since 3.4
* @return bool
*/
protected function __202003092() {
// Look for column
$result = $this->column_exists( 'date_modified' );
// Add column if it doesn't exist.
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN date_modified datetime NOT NULL;" );
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003092 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003092 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to 202003093
* - Add `uuid` column.
*
* @since 3.4
* @return bool
*/
protected function __202003093() {
// Look for column
$result = $this->column_exists( 'uuid' );
// Add column if it doesn't exist.
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN uuid varchar(100) NOT NULL DEFAULT '';" );
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003093 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003093 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to 202008061
*
* This ensures that pre-BerlinDB columns exist.
* - Add `maximum_renewals` column.
*
* @since 3.4
* @return bool
*/
protected function __202008061() {
// Look for column
$result = $this->column_exists( 'maximum_renewals' );
// Add column if it doesn't exist.
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN maximum_renewals smallint UNSIGNED NOT NULL DEFAULT 0 AFTER fee;" );
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202008061 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202008061 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to 202008062
*
* This ensures that pre-BerlinDB columns exist.
* - Add `after_final_payment` column.
*
* @since 3.4
* @return bool
*/
protected function __202008062() {
// Look for column
$result = $this->column_exists( 'after_final_payment' );
// Add column if it doesn't exist.
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN after_final_payment tinytext NOT NULL AFTER maximum_renewals;" );
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202008062 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202008062 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to 202009251
*
* This ensures that the pre-BerlinDB columns exist.
* - Add `trial_duration` column.
*
* @since 3.4.2
* @return bool
*/
protected function __202009251() {
// Look for column
$result = $this->column_exists( 'trial_duration' );
// Add column if it doesn't exist
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN trial_duration smallint(6) UNSIGNED NOT NULL DEFAULT 0;" );
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202009251 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202009251 successful.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to 202009252
*
* This ensure that the pre-BerlinDB columns exist.
* - Add `trial_duration_unit` column.
*
* @since 3.4.2
* @return bool
*/
protected function __202009252() {
// Look for column
$result = $this->column_exists( 'trial_duration_unit' );
// Add column if it doesn't exist
if ( false === $result ) {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} ADD COLUMN trial_duration_unit tinytext NOT NULL;" );
}
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202009252 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202009252 successful.', $this->get_table_name() ), true );
}
return $success;
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,72 @@
<?php
/**
* Membership Meta Table.
*
* @package RCP
* @subpackage Database\Tables
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database\Tables;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Table;
/**
* Setup the "rcp_membershipmeta" database table
*
* @since 3.0
*/
final class Membership_Meta extends Table {
/**
* @var string Table name
*/
protected $name = 'membershipmeta';
/**
* @var string Database version
*/
protected $version = 201901291;
/**
* @var array Array of upgrade versions and methods
*/
protected $upgrades = array();
/**
* Membership Meta constructor.
*
* @access public
* @since 3.0
* @return void
*/
public function __construct() {
parent::__construct();
}
/**
* Setup the database schema
*
* @access protected
* @since 3.0
* @return void
*/
protected function set_schema() {
$max_index_length = 191;
$this->schema = "meta_id bigint(20) unsigned NOT NULL auto_increment,
rcp_membership_id bigint(20) unsigned NOT NULL default '0',
meta_key varchar(255) DEFAULT NULL,
meta_value longtext DEFAULT NULL,
PRIMARY KEY (meta_id),
KEY rcp_membership_id (rcp_membership_id),
KEY meta_key (meta_key({$max_index_length}))";
}
}

View File

@@ -0,0 +1,167 @@
<?php
/**
* Membership Query Class.
*
* @package RCP
* @subpackage Database\Queries
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database\Queries;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Query;
/**
* Class used for querying memberships.
*
* @since 3.0
*
* @see \RCP\Database\Queries\Membership::__construct() for accepted arguments.
*/
class Membership extends Query {
/** Table Properties ******************************************************/
/**
* Name of the database table to query.
*
* @since 3.0
* @access public
* @var string
*/
protected $table_name = 'memberships';
/**
* String used to alias the database table in MySQL statement.
*
* @since 3.0
* @access public
* @var string
*/
protected $table_alias = 'm';
/**
* Name of class used to setup the database schema
*
* @since 3.0
* @access public
* @var string
*/
protected $table_schema = '\\RCP\\Database\\Schemas\\Memberships';
/** Item ******************************************************************/
/**
* Name for a single item
*
* @since 3.0
* @access public
* @var string
*/
protected $item_name = 'membership';
/**
* Plural version for a group of items.
*
* @since 3.0
* @access public
* @var string
*/
protected $item_name_plural = 'memberships';
/**
* Callback function for turning IDs into objects
*
* @since 3.0
* @access public
* @var mixed
*/
protected $item_shape = '\\RCP_Membership';
/**
* Group to cache queries and queried items in.
*
* @since 3.0
* @access public
* @var string
*/
protected $cache_group = 'memberships';
/**
* Sets up the membership query, based on the query vars passed.
*
* @since 3.0
* @access public
*
* @param string|array $query {
* Optional. Array or query string of membership query parameters.
* Default empty.
*
* @type int $id A membership ID to only return that membership. Default empty.
* @type array $id__in Array of membership IDs to include. Default empty.
* @type array $id__not_in Array of membership IDs to exclude. Default empty.
* @type int $customer_id A customer ID to only return this customer's memberships. Default
* empty.
* @type array $customer_id__in Array of customer IDs to include. Default empty.
* @type array $customer_id__not_in Array of customer IDs to exclude. Default empty.
* @type string $object_id An object ID to only return memberships for this object. Default
* empty.
* @type array $object_id__in Array of object IDs to include. Default empty.
* @type array $object_id__not_in Array of object IDs to exclude. Default empty.
* @type string $object_type An object type to only return this type. Default empty.
* @type array $object_type__in Array of object types to include. Default empty.
* @type array $object_type__not_in Array of object types to exclude. Default empty.
* @type string $currency A currency to only show memberships using this currency. Default
* empty.
* @type array $date_query Query all datetime columns together. See WP_Date_Query.
* @type array $created_date_query Date query clauses to limit memberships by. See WP_Date_Query.
* Default null.
* @type array $activated_date_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type array $trial_end_date_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type array $renewed_date_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type array $cancellation_date_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type array $expiration_date_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type array $date_modified_query Date query clauses to limit by. See WP_Date_Query. Default null.
* @type int $auto_renew Auto renewal status. Default null.
* @type string $status A status to filter by. Default null for all statuses.
* @type array $status__in Array of statuses to include. Default empty.
* @type array $status__not_in Array of statuses to exclude. Default empty.
* @type string $gateway_customer_id A gateway customer ID to search for. Default empty.
* @type string $gateway_subscription_id A gateway subscription ID to search for. Default empty.
* @type string $gateway A gateway to filter by. Default empty.
* @type string $subscription_key A subscription key to filter by. Default empty.
* @type int $upgraded_from A membership ID this membership upgraded from. Default empty.
* @type int $disabled Whether or not to show disabled memberships. Set to `0` to only
* include enabled memberships, set to `1` to only include disabled
* memberships, set to empty string to include both. Default empty.
* @type bool $count Whether to return a membership count (true) or array of membership
* objects. Default false.
* @type string $fields Item fields to return. Accepts any column known names
* or empty (returns an array of complete membership objects). Default
* empty.
* @type int $number Limit number of memberships to retrieve. Default 100.
* @type int $offset Number of memberships to offset the query. Used to build LIMIT
* clause. Default 0.
* @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true.
* @type string|array $orderby Accepts 'id', 'object_id', 'object_type', 'currency',
* `initial_amount`, `recurring_amount`, `created_date`,
* `trial_end_date`, `cancellation_date`, `expiration_date`,
* `times_billed`, `maximum_renewals`, `status`,
* `gateway_customer_id`, `gateway_subscription_id`, and
* `subscription_key`. Also accepts false, an empty array, or 'none'
* to disable `ORDER BY` clause. Default 'id'.
* @type string $order How to order results. Accepts 'ASC', 'DESC'. Default 'DESC'.
* @type string $search Search term(s) to retrieve matching memberships for. Default empty.
* @type bool $update_cache Whether to prime the cache for found memberships. Default false.
* }
*/
public function __construct( $query = array() ) {
parent::__construct( $query );
}
}

View File

@@ -0,0 +1,306 @@
<?php
/**
* Memberships Schema Class.
*
* @package RCP
* @subpackage Database\Schemas
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database\Schemas;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Schema;
/**
* Memberships Schema Class.
*
* @since 3.0
*/
class Memberships extends Schema {
/**
* Array of database column objects
*
* @since 3.0
* @access public
* @var array
*/
public $columns = array(
// id
array(
'name' => 'id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'extra' => 'auto_increment',
'primary' => true,
'sortable' => true
),
// customer_id
array(
'name' => 'customer_id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'default' => '0'
),
// user_id
array(
'name' => 'user_id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'default' => null,
'allow_null' => true
),
// object_id
array(
'name' => 'object_id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'default' => '0',
'sortable' => true,
'transition' => true
),
// object_type
array(
'name' => 'object_type',
'type' => 'varchar',
'length' => '20',
'default' => '',
'sortable' => true,
),
// currency
array(
'name' => 'currency',
'type' => 'varchar',
'length' => '20',
'default' => 'USD',
'sortable' => true
),
// initial_amount
array(
'name' => 'initial_amount',
'type' => 'mediumtext',
'default' => '',
'sortable' => true
),
// recurring_amount
array(
'name' => 'recurring_amount',
'type' => 'mediumtext',
'default' => '',
'sortable' => true
),
// created_date
array(
'name' => 'created_date',
'type' => 'datetime',
'default' => '',
'created' => true,
'date_query' => true,
'sortable' => true
),
// activated_date
array(
'name' => 'activated_date',
'type' => 'datetime',
'default' => null,
'allow_null' => true,
'date_query' => true,
'sortable' => true
),
// trial_end_date
array(
'name' => 'trial_end_date',
'type' => 'datetime',
'default' => null,
'allow_null' => true,
'date_query' => true,
'sortable' => true
),
// renewed_date
array(
'name' => 'renewed_date',
'type' => 'datetime',
'default' => null,
'allow_null' => true,
'date_query' => true,
'sortable' => true
),
// cancellation_date
array(
'name' => 'cancellation_date',
'type' => 'datetime',
'default' => null,
'allow_null' => true,
'date_query' => true,
'sortable' => true
),
// expiration_date
array(
'name' => 'expiration_date',
'type' => 'datetime',
'default' => null,
'allow_null' => true,
'date_query' => true,
'sortable' => true,
'transition' => true
),
// payment_plan_completed_date
array(
'name' => 'payment_plan_completed_date',
'type' => 'datetime',
'default' => null,
'allow_null' => true,
'date_query' => true,
'sortable' => true,
'transition' => true
),
// auto_renew
array(
'name' => 'auto_renew',
'type' => 'smallint',
'unsigned' => true,
'default' => '0',
'transition' => true
),
// times_billed
array(
'name' => 'times_billed',
'type' => 'smallint',
'unsigned' => true,
'default' => '0',
'sortable' => true,
'transition' => true
),
// maximum_renewals
array(
'name' => 'maximum_renewals',
'type' => 'smallint',
'unsigned' => true,
'default' => '0',
'sortable' => true
),
// status
array(
'name' => 'status',
'type' => 'varchar',
'length' => '12',
'default' => 'pending',
'sortable' => true,
'transition' => true
),
// gateway_customer_id
array(
'name' => 'gateway_customer_id',
'type' => 'tinytext',
'default' => '',
'searchable' => true,
'sortable' => true,
'transition' => true
),
// gateway_subscription_id
array(
'name' => 'gateway_subscription_id',
'type' => 'tinytext',
'default' => '',
'searchable' => true,
'sortable' => true,
'transition' => true
),
// gateway
array(
'name' => 'gateway',
'type' => 'tinytext',
'default' => '',
),
// signup_method
array(
'name' => 'signup_method',
'type' => 'tinytext',
'default' => '',
),
// subscription_key
array(
'name' => 'subscription_key',
'type' => 'varchar',
'length' => '32',
'default' => '',
'searchable' => true,
'sortable' => true
),
// notes
array(
'name' => 'notes',
'type' => 'longtext',
'default' => ''
),
// upgraded_from
array(
'name' => 'upgraded_from',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'default' => ''
),
// date_modified
array(
'name' => 'date_modified',
'type' => 'datetime',
'default' => '',
'modified' => true,
'date_query' => true,
'sortable' => true
),
// disabled
array(
'name' => 'disabled',
'type' => 'smallint',
'unsigned' => true,
'default' => '',
'pattern' => '%d'
),
// uuid
array(
'uuid' => true,
)
);
}

View File

@@ -0,0 +1,307 @@
<?php
/**
* Memberships Table.
*
* @package RCP
* @subpackage Database\Tables
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database\Tables;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Table;
/**
* Setup the "rcp_memberships" database table
*
* @since 3.0
*/
final class Memberships extends Table {
/**
* @var string Table name
*/
protected $name = 'memberships';
/**
* @var string Database version
*/
protected $version = 202003315;
/**
* @var array Array of upgrade versions and methods
*/
protected $upgrades = array(
'201811131' => 201811131,
'201811132' => 201811132,
'201811191' => 201811191,
'201910101' => 201910101,
'202001131' => 202001131,
'202003311' => 202003311,
'202003312' => 202003312,
'202003313' => 202003313,
'202003314' => 202003314,
'202003315' => 202003315
);
/**
* Memberships constructor.
*
* @access public
* @since 3.0
* @return void
*/
public function __construct() {
parent::__construct();
}
/**
* Setup the database schema
*
* @access protected
* @since 3.0
* @return void
*/
protected function set_schema() {
$this->schema = "id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
customer_id bigint(20) unsigned NOT NULL default '0',
user_id bigint(20) unsigned DEFAULT NULL,
object_id bigint(9) NOT NULL default '0',
object_type varchar(20) DEFAULT NULL,
currency varchar(20) NOT NULL DEFAULT 'USD',
initial_amount mediumtext NOT NULL,
recurring_amount mediumtext NOT NULL,
created_date datetime NOT NULL,
activated_date datetime DEFAULT NULL,
trial_end_date datetime DEFAULT NULL,
renewed_date datetime DEFAULT NULL,
cancellation_date datetime DEFAULT NULL,
expiration_date datetime DEFAULT NULL,
payment_plan_completed_date datetime DEFAULT NULL,
auto_renew smallint unsigned NOT NULL DEFAULT '0',
times_billed smallint unsigned NOT NULL DEFAULT '0',
maximum_renewals smallint unsigned NOT NULL DEFAULT '0',
status varchar(12) NOT NULL DEFAULT 'pending',
gateway_customer_id tinytext DEFAULT NULL,
gateway_subscription_id tinytext DEFAULT NULL,
gateway tinytext NOT NULL default '',
signup_method tinytext NOT NULL default '',
subscription_key varchar(32) NOT NULL default '',
notes longtext NOT NULL default '',
upgraded_from bigint(20) unsigned DEFAULT NULL,
date_modified datetime NOT NULL,
disabled smallint unsigned DEFAULT NULL,
uuid varchar(100) NOT NULL default '',
PRIMARY KEY (id),
KEY customer_id (customer_id),
KEY object_id (object_id),
KEY status (status),
KEY disabled (disabled)";
}
/**
* Upgrade to version 201811131
* - Add `renewed_date` column.
*/
protected function __201811131() {
// Look for column
$result = $this->column_exists( 'renewed_date' );
// Maybe add column
if ( false === $result ) {
$result = $this->get_db()->query( "
ALTER TABLE {$this->table_name} ADD COLUMN `renewed_date` datetime DEFAULT NULL AFTER `trial_end_date`;
" );
}
// Return success/fail
return $this->is_success( $result );
}
/**
* Upgrade to version 201811132
* - Add `date_modified` column.
*/
protected function __201811132() {
// Look for column
$result = $this->column_exists( 'date_modified' );
// Maybe add column
if ( false === $result ) {
$result = $this->get_db()->query( "
ALTER TABLE {$this->table_name} ADD COLUMN `date_modified` datetime NOT NULL AFTER `upgraded_from`;
" );
}
// Return success/fail
return $this->is_success( $result );
}
/**
* Upgrade to version 201811191
* - Add `payment_plan_completed_date` column.
*/
protected function __201811191() {
// Look for column
$result = $this->column_exists( 'payment_plan_completed_date' );
// Maybe add column
if ( false === $result ) {
$result = $this->get_db()->query( "
ALTER TABLE {$this->table_name} ADD COLUMN `payment_plan_completed_date` datetime DEFAULT NULL AFTER `expiration_date`;
" );
}
// Return success/fail
return $this->is_success( $result );
}
/**
* Upgrade to version 201910101
* - Add `activated_date` column.
*/
protected function __201910101() {
// Look for column
$result = $this->column_exists( 'activated_date' );
// Maybe add column
if ( false === $result ) {
$result = $this->get_db()->query( "
ALTER TABLE {$this->table_name} ADD COLUMN `activated_date` datetime DEFAULT NULL AFTER `created_date`;
" );
}
// Return success/fail
return $this->is_success( $result );
}
/**
* Upgrade to version 202001131
* - Add `user_id` column.
*/
protected function __202001131() {
// Look for column
$result = $this->column_exists( 'user_id' );
// Maybe add column
if ( false === $result ) {
$result = $this->get_db()->query( "
ALTER TABLE {$this->table_name} ADD COLUMN `user_id` bigint(20) unsigned DEFAULT NULL AFTER `customer_id`;
" );
}
// Return success/fail
return $this->is_success( $result );
}
/**
* Upgrade to version 202003311
* - Remove default `created_date` value
*/
protected function __202003311() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY created_date datetime NOT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003311 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003311 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to version 202003312
* - Change default `activated_date` value to `null`
*/
protected function __202003312() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY activated_date datetime DEFAULT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003312 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003312 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to version 202003313
* - Change default `renewed_date` value to `null`
*/
protected function __202003313() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY renewed_date datetime DEFAULT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003313 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003313 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to version 202003314
* - Change default `payment_plan_completed_date` value to `null`
*/
protected function __202003314() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY payment_plan_completed_date datetime DEFAULT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003314 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003314 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to version 202003315
* - Remove default `date_modified` value
*/
protected function __202003315() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY date_modified datetime NOT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003315 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003315 failure.', $this->get_table_name() ), true );
}
return $success;
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,135 @@
<?php
/**
* Queue Query Class.
*
* @package RCP
* @subpackage Database\Queries
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database\Queries;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Query;
/**
* Class used for querying the job queue.
*
* @since 3.0
*
* @see \RCP\Database\Queries\Queue::__construct() for accepted arguments.
*/
class Queue extends Query {
/** Table Properties ******************************************************/
/**
* Name of the database table to query.
*
* @since 3.0
* @access public
* @var string
*/
protected $table_name = 'queue';
/**
* String used to alias the database table in MySQL statement.
*
* @since 3.0
* @access public
* @var string
*/
protected $table_alias = 'q';
/**
* Name of class used to setup the database schema
*
* @since 3.0
* @access public
* @var string
*/
protected $table_schema = '\\RCP\\Database\\Schemas\\Queue';
/** Item ******************************************************************/
/**
* Name for a single item
*
* @since 3.0
* @access public
* @var string
*/
protected $item_name = 'job';
/**
* Plural version for a group of items.
*
* @since 3.0
* @access public
* @var string
*/
protected $item_name_plural = 'jobs';
/**
* Callback function for turning IDs into objects
*
* @since 3.0
* @access public
* @var mixed
*/
protected $item_shape = '\\RCP\\Utils\\Batch\\Job';
/**
* Group to cache queries and queried items in.
*
* @since 3.0
* @access public
* @var string
*/
protected $cache_group = 'queue';
/**
* Sets up the queue query, based on the query vars passed.
*
* @since 3.0
* @access public
*
* @param string|array $query {
* Optional. Array or query string of membership query parameters.
* Default empty.
*
* @type int $id A job ID to only return that job. Default empty.
* @type array $id__in Array of job IDs to include. Default empty.
* @type array $id__not_in Array of job IDs to exclude. Default empty.
* @type int $queue A queue name to only return jobs in this queue. Default empty.
* @type array $queue__in Array of queues to include. Default empty.
* @type array $queue__not_in Array of queues to exclude. Default empty.
* @type string $name A job name. Default empty.
* @type string $status A job status to only return jobs with this status. Default empty.
* @type array $status__in Array of statuses to include. Default empty.
* @type array $status__not_in Array of statuses to exclude. Default empty.
* @type bool $count Whether to return a job count (true) or array of job objects.
* Default false.
* @type string $fields Item fields to return. Accepts any column known names
* or empty (returns an array of complete job objects). Default
* empty.
* @type int $number Limit number of jobs to retrieve. Default 100.
* @type int $offset Number of jobs to offset the query. Used to build LIMIT clause.
* Default 0.
* @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true.
* @type string|array $orderby Accepts 'id', 'name', and 'status'. Also accepts false, an empty
* array, or 'none' to disable `ORDER BY` clause. Default 'id'.
* @type string $order How to order results. Accepts 'ASC', 'DESC'. Default 'DESC'.
* @type string $search Search term(s) to retrieve matching jobs for. Default empty.
* @type bool $update_cache Whether to prime the cache for found memberships. Default false.
* }
*/
public function __construct( $query = array() ) {
parent::__construct( $query );
}
}

View File

@@ -0,0 +1,153 @@
<?php
/**
* Queue Schema Class.
*
* @package RCP
* @subpackage Database\Schemas
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database\Schemas;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Schema;
/**
* Queue Schema Class.
*
* @since 3.0
*/
class Queue extends Schema {
/**
* Array of database column objects
*
* @since 3.0
* @access public
* @var array
*/
public $columns = array(
// id
array(
'name' => 'id',
'type' => 'bigint',
'length' => '20',
'unsigned' => true,
'extra' => 'auto_increment',
'primary' => true,
'sortable' => true
),
// queue
array(
'name' => 'queue',
'type' => 'varchar',
'length' => '20',
'default' => 'rcp_core'
),
// name
array(
'name' => 'name',
'type' => 'varchar',
'length' => '50',
'default' => '',
'searchable' => true,
'sortable' => true,
),
// description
array(
'name' => 'description',
'type' => 'varchar',
'length' => '256',
'default' => '',
),
// callback
array(
'name' => 'callback',
'type' => 'varchar',
'length' => '512',
'default' => '',
),
// total_count
array(
'name' => 'total_count',
'type' => 'bigint',
'length' => 20,
'unsigned' => true,
'default' => 0,
'sortable' => true
),
// current_count
array(
'name' => 'current_count',
'type' => 'bigint',
'length' => 20,
'unsigned' => true,
'default' => 0,
'sortable' => true
),
// step
array(
'name' => 'step',
'type' => 'bigint',
'length' => 20,
'unsigned' => true,
'default' => 0,
'sortable' => true
),
// status
array(
'name' => 'status',
'type' => 'varchar',
'length' => '20',
'default' => 'incomplete',
'sortable' => true
),
// data
array(
'name' => 'data',
'type' => 'longtext',
'default' => ''
),
// date_created
array(
'name' => 'date_created',
'type' => 'datetime',
'default' => '',
'created' => true,
'date_query' => true,
'sortable' => true
),
// date_completed
array(
'name' => 'date_completed',
'type' => 'datetime',
'default' => null,
'allow_null' => true,
'date_query' => true,
'sortable' => true
),
// uuid
array(
'uuid' => true,
)
);
}

View File

@@ -0,0 +1,204 @@
<?php
/**
* Queue Table.
*
* @package RCP
* @subpackage Database\Tables
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace RCP\Database\Tables;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
use RCP\Database\Table;
/**
* Setup the "rcp_queue" database table
*
* @since 3.0
*/
final class Queue extends Table {
/**
* @var string Table name
*/
protected $name = 'queue';
/**
* @var string Database version
*/
protected $version = 202003312;
/**
* @var array Array of upgrade versions and methods
*/
protected $upgrades = array(
'201905111' => 201905111,
'201908091' => 201908091,
'201908092' => 201908092,
'202003311' => 202003311,
'202003312' => 202003312
);
/**
* Queue constructor.
*
* @access public
* @since 3.0
* @return void
*/
public function __construct() {
parent::__construct();
}
/**
* Setup the database schema
*
* @access protected
* @since 3.0
* @return void
*/
protected function set_schema() {
$this->schema = "id int unsigned NOT NULL AUTO_INCREMENT,
queue varchar(20) NOT NULL DEFAULT '',
name varchar(50) NOT NULL DEFAULT '',
description varchar(256) NOT NULL DEFAULT '',
callback varchar(512) NOT NULL DEFAULT '',
total_count bigint(20) unsigned NOT NULL DEFAULT 0,
current_count bigint(20) unsigned NOT NULL DEFAULT 0,
step bigint(20) unsigned NOT NULL DEFAULT 0,
status varchar(20) NOT NULL DEFAULT 'incomplete',
data longtext NOT NULL DEFAULT '',
date_created datetime NOT NULL,
date_completed datetime DEFAULT NULL,
uuid varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY (id),
UNIQUE KEY name_queue (name,queue),
KEY queue (queue),
KEY status (status)";
}
/**
* Upgrade to version 201905111
* - Add `data` column for serialized data.
*/
protected function __201905111() {
// Look for column
$result = $this->column_exists( 'data' );
// Maybe add column
if ( false === $result ) {
$result = $this->get_db()->query( "
ALTER TABLE {$this->table_name} ADD COLUMN `data` longtext NOT NULL DEFAULT '' AFTER `status`;
" );
}
// Return success/fail
return $this->is_success( $result );
}
/**
* Upgrade to version 201908091
*
* - Add `date_created` column.
*
* @since 3.1.2
* @return bool
*/
protected function __201908091() {
// Look for column
$result = $this->column_exists( 'date_created' );
// Maybe add column
if ( false === $result ) {
$result = $this->get_db()->query( "
ALTER TABLE {$this->table_name} ADD COLUMN `date_created` datetime NOT NULL AFTER `data`;
" );
}
$success = $this->is_success( $result );
rcp_log( sprintf( '%s upgrade to version 201908091 result: %s', $this->table_name, var_export( $success, true ) ), true );
// Return success/fail
return $success;
}
/**
* Upgrade to version 201908092
*
* - Add `date_completed` column.
*
* @since 3.1.2
* @return bool
*/
protected function __201908092() {
// Look for column
$result = $this->column_exists( 'date_completed' );
// Maybe add column
if ( false === $result ) {
$result = $this->get_db()->query( "
ALTER TABLE {$this->table_name} ADD COLUMN `date_completed` datetime NOT NULL AFTER `date_created`;
" );
}
$success = $this->is_success( $result );
rcp_log( sprintf( '%s upgrade to version 201908092 result: %s', $this->table_name, var_export( $success, true ) ), true );
// Return success/fail
return $success;
}
/**
* Upgrade to version 202003311
* - Remove default `date_created` value
*/
protected function __202003311() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY date_created datetime NOT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003311 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003311 failure.', $this->get_table_name() ), true );
}
return $success;
}
/**
* Upgrade to version 202003312
* - Change default `date_completed` value to `null`
*/
protected function __202003312() {
$result = $this->get_db()->query( "ALTER TABLE {$this->table_name} MODIFY date_completed datetime DEFAULT NULL" );
$success = $this->is_success( $result );
if ( $success ) {
rcp_log( sprintf( '%s table upgrade to 202003312 successful.', $this->get_table_name() ), true );
} else {
rcp_log( sprintf( '%s table upgrade to 202003312 failure.', $this->get_table_name() ), true );
}
return $success;
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.