@@ -4,59 +4,59 @@ |
||
| 4 | 4 | * Class ActionScheduler_Versions |
| 5 | 5 | */ |
| 6 | 6 | class ActionScheduler_Versions { |
| 7 | - /** |
|
| 8 | - * @var ActionScheduler_Versions |
|
| 9 | - */ |
|
| 10 | - private static $instance = NULL; |
|
| 11 | - |
|
| 12 | - private $versions = array(); |
|
| 13 | - |
|
| 14 | - public function register( $version_string, $initialization_callback ) { |
|
| 15 | - if ( isset($this->versions[$version_string]) ) { |
|
| 16 | - return FALSE; |
|
| 17 | - } |
|
| 18 | - $this->versions[$version_string] = $initialization_callback; |
|
| 19 | - return TRUE; |
|
| 20 | - } |
|
| 21 | - |
|
| 22 | - public function get_versions() { |
|
| 23 | - return $this->versions; |
|
| 24 | - } |
|
| 25 | - |
|
| 26 | - public function latest_version() { |
|
| 27 | - $keys = array_keys($this->versions); |
|
| 28 | - if ( empty($keys) ) { |
|
| 29 | - return false; |
|
| 30 | - } |
|
| 31 | - uasort( $keys, 'version_compare' ); |
|
| 32 | - return end($keys); |
|
| 33 | - } |
|
| 34 | - |
|
| 35 | - public function latest_version_callback() { |
|
| 36 | - $latest = $this->latest_version(); |
|
| 37 | - if ( empty($latest) || !isset($this->versions[$latest]) ) { |
|
| 38 | - return '__return_null'; |
|
| 39 | - } |
|
| 40 | - return $this->versions[$latest]; |
|
| 41 | - } |
|
| 42 | - |
|
| 43 | - /** |
|
| 44 | - * @return ActionScheduler_Versions |
|
| 45 | - * @codeCoverageIgnore |
|
| 46 | - */ |
|
| 47 | - public static function instance() { |
|
| 48 | - if ( empty(self::$instance) ) { |
|
| 49 | - self::$instance = new self(); |
|
| 50 | - } |
|
| 51 | - return self::$instance; |
|
| 52 | - } |
|
| 53 | - |
|
| 54 | - /** |
|
| 55 | - * @codeCoverageIgnore |
|
| 56 | - */ |
|
| 57 | - public static function initialize_latest_version() { |
|
| 58 | - $self = self::instance(); |
|
| 59 | - call_user_func($self->latest_version_callback()); |
|
| 60 | - } |
|
| 7 | + /** |
|
| 8 | + * @var ActionScheduler_Versions |
|
| 9 | + */ |
|
| 10 | + private static $instance = NULL; |
|
| 11 | + |
|
| 12 | + private $versions = array(); |
|
| 13 | + |
|
| 14 | + public function register( $version_string, $initialization_callback ) { |
|
| 15 | + if ( isset($this->versions[$version_string]) ) { |
|
| 16 | + return FALSE; |
|
| 17 | + } |
|
| 18 | + $this->versions[$version_string] = $initialization_callback; |
|
| 19 | + return TRUE; |
|
| 20 | + } |
|
| 21 | + |
|
| 22 | + public function get_versions() { |
|
| 23 | + return $this->versions; |
|
| 24 | + } |
|
| 25 | + |
|
| 26 | + public function latest_version() { |
|
| 27 | + $keys = array_keys($this->versions); |
|
| 28 | + if ( empty($keys) ) { |
|
| 29 | + return false; |
|
| 30 | + } |
|
| 31 | + uasort( $keys, 'version_compare' ); |
|
| 32 | + return end($keys); |
|
| 33 | + } |
|
| 34 | + |
|
| 35 | + public function latest_version_callback() { |
|
| 36 | + $latest = $this->latest_version(); |
|
| 37 | + if ( empty($latest) || !isset($this->versions[$latest]) ) { |
|
| 38 | + return '__return_null'; |
|
| 39 | + } |
|
| 40 | + return $this->versions[$latest]; |
|
| 41 | + } |
|
| 42 | + |
|
| 43 | + /** |
|
| 44 | + * @return ActionScheduler_Versions |
|
| 45 | + * @codeCoverageIgnore |
|
| 46 | + */ |
|
| 47 | + public static function instance() { |
|
| 48 | + if ( empty(self::$instance) ) { |
|
| 49 | + self::$instance = new self(); |
|
| 50 | + } |
|
| 51 | + return self::$instance; |
|
| 52 | + } |
|
| 53 | + |
|
| 54 | + /** |
|
| 55 | + * @codeCoverageIgnore |
|
| 56 | + */ |
|
| 57 | + public static function initialize_latest_version() { |
|
| 58 | + $self = self::instance(); |
|
| 59 | + call_user_func($self->latest_version_callback()); |
|
| 60 | + } |
|
| 61 | 61 | } |
| 62 | - |
|
| 63 | 62 | \ No newline at end of file |
| 63 | + |
|
| 64 | 64 | \ No newline at end of file |
@@ -4,52 +4,52 @@ |
||
| 4 | 4 | * Class ActionScheduler_FatalErrorMonitor |
| 5 | 5 | */ |
| 6 | 6 | class ActionScheduler_FatalErrorMonitor { |
| 7 | - /** @var ActionScheduler_ActionClaim */ |
|
| 8 | - private $claim = NULL; |
|
| 9 | - /** @var ActionScheduler_Store */ |
|
| 10 | - private $store = NULL; |
|
| 11 | - private $action_id = 0; |
|
| 7 | + /** @var ActionScheduler_ActionClaim */ |
|
| 8 | + private $claim = NULL; |
|
| 9 | + /** @var ActionScheduler_Store */ |
|
| 10 | + private $store = NULL; |
|
| 11 | + private $action_id = 0; |
|
| 12 | 12 | |
| 13 | - public function __construct( ActionScheduler_Store $store ) { |
|
| 14 | - $this->store = $store; |
|
| 15 | - } |
|
| 13 | + public function __construct( ActionScheduler_Store $store ) { |
|
| 14 | + $this->store = $store; |
|
| 15 | + } |
|
| 16 | 16 | |
| 17 | - public function attach( ActionScheduler_ActionClaim $claim ) { |
|
| 18 | - $this->claim = $claim; |
|
| 19 | - add_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) ); |
|
| 20 | - add_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0, 1 ); |
|
| 21 | - add_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0, 0 ); |
|
| 22 | - add_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0, 0 ); |
|
| 23 | - add_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0, 0 ); |
|
| 24 | - } |
|
| 17 | + public function attach( ActionScheduler_ActionClaim $claim ) { |
|
| 18 | + $this->claim = $claim; |
|
| 19 | + add_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) ); |
|
| 20 | + add_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0, 1 ); |
|
| 21 | + add_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0, 0 ); |
|
| 22 | + add_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0, 0 ); |
|
| 23 | + add_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0, 0 ); |
|
| 24 | + } |
|
| 25 | 25 | |
| 26 | - public function detach() { |
|
| 27 | - $this->claim = NULL; |
|
| 28 | - $this->untrack_action(); |
|
| 29 | - remove_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) ); |
|
| 30 | - remove_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0 ); |
|
| 31 | - remove_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0 ); |
|
| 32 | - remove_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0 ); |
|
| 33 | - remove_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0 ); |
|
| 34 | - } |
|
| 26 | + public function detach() { |
|
| 27 | + $this->claim = NULL; |
|
| 28 | + $this->untrack_action(); |
|
| 29 | + remove_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) ); |
|
| 30 | + remove_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0 ); |
|
| 31 | + remove_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0 ); |
|
| 32 | + remove_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0 ); |
|
| 33 | + remove_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0 ); |
|
| 34 | + } |
|
| 35 | 35 | |
| 36 | - public function track_current_action( $action_id ) { |
|
| 37 | - $this->action_id = $action_id; |
|
| 38 | - } |
|
| 36 | + public function track_current_action( $action_id ) { |
|
| 37 | + $this->action_id = $action_id; |
|
| 38 | + } |
|
| 39 | 39 | |
| 40 | - public function untrack_action() { |
|
| 41 | - $this->action_id = 0; |
|
| 42 | - } |
|
| 40 | + public function untrack_action() { |
|
| 41 | + $this->action_id = 0; |
|
| 42 | + } |
|
| 43 | 43 | |
| 44 | - public function handle_unexpected_shutdown() { |
|
| 45 | - if ( $error = error_get_last() ) { |
|
| 46 | - if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ) ) ) { |
|
| 47 | - if ( !empty($this->action_id) ) { |
|
| 48 | - $this->store->mark_failure( $this->action_id ); |
|
| 49 | - do_action( 'action_scheduler_unexpected_shutdown', $this->action_id, $error ); |
|
| 50 | - } |
|
| 51 | - } |
|
| 52 | - $this->store->release_claim( $this->claim ); |
|
| 53 | - } |
|
| 54 | - } |
|
| 44 | + public function handle_unexpected_shutdown() { |
|
| 45 | + if ( $error = error_get_last() ) { |
|
| 46 | + if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ) ) ) { |
|
| 47 | + if ( !empty($this->action_id) ) { |
|
| 48 | + $this->store->mark_failure( $this->action_id ); |
|
| 49 | + do_action( 'action_scheduler_unexpected_shutdown', $this->action_id, $error ); |
|
| 50 | + } |
|
| 51 | + } |
|
| 52 | + $this->store->release_claim( $this->claim ); |
|
| 53 | + } |
|
| 54 | + } |
|
| 55 | 55 | } |
@@ -8,42 +8,42 @@ discard block |
||
| 8 | 8 | * Creates custom tables for storing scheduled actions |
| 9 | 9 | */ |
| 10 | 10 | class ActionScheduler_StoreSchema extends ActionScheduler_Abstract_Schema { |
| 11 | - const ACTIONS_TABLE = 'actionscheduler_actions'; |
|
| 12 | - const CLAIMS_TABLE = 'actionscheduler_claims'; |
|
| 13 | - const GROUPS_TABLE = 'actionscheduler_groups'; |
|
| 14 | - const DEFAULT_DATE = '0000-00-00 00:00:00'; |
|
| 15 | - |
|
| 16 | - /** |
|
| 17 | - * @var int Increment this value to trigger a schema update. |
|
| 18 | - */ |
|
| 19 | - protected $schema_version = 6; |
|
| 20 | - |
|
| 21 | - public function __construct() { |
|
| 22 | - $this->tables = [ |
|
| 23 | - self::ACTIONS_TABLE, |
|
| 24 | - self::CLAIMS_TABLE, |
|
| 25 | - self::GROUPS_TABLE, |
|
| 26 | - ]; |
|
| 27 | - } |
|
| 28 | - |
|
| 29 | - /** |
|
| 30 | - * Performs additional setup work required to support this schema. |
|
| 31 | - */ |
|
| 32 | - public function init() { |
|
| 33 | - add_action( 'action_scheduler_before_schema_update', array( $this, 'update_schema_5_0' ), 10, 2 ); |
|
| 34 | - } |
|
| 35 | - |
|
| 36 | - protected function get_table_definition( $table ) { |
|
| 37 | - global $wpdb; |
|
| 38 | - $table_name = $wpdb->$table; |
|
| 39 | - $charset_collate = $wpdb->get_charset_collate(); |
|
| 40 | - $max_index_length = 191; // @see wp_get_db_schema() |
|
| 41 | - $default_date = self::DEFAULT_DATE; |
|
| 42 | - switch ( $table ) { |
|
| 43 | - |
|
| 44 | - case self::ACTIONS_TABLE: |
|
| 45 | - |
|
| 46 | - return "CREATE TABLE {$table_name} ( |
|
| 11 | + const ACTIONS_TABLE = 'actionscheduler_actions'; |
|
| 12 | + const CLAIMS_TABLE = 'actionscheduler_claims'; |
|
| 13 | + const GROUPS_TABLE = 'actionscheduler_groups'; |
|
| 14 | + const DEFAULT_DATE = '0000-00-00 00:00:00'; |
|
| 15 | + |
|
| 16 | + /** |
|
| 17 | + * @var int Increment this value to trigger a schema update. |
|
| 18 | + */ |
|
| 19 | + protected $schema_version = 6; |
|
| 20 | + |
|
| 21 | + public function __construct() { |
|
| 22 | + $this->tables = [ |
|
| 23 | + self::ACTIONS_TABLE, |
|
| 24 | + self::CLAIMS_TABLE, |
|
| 25 | + self::GROUPS_TABLE, |
|
| 26 | + ]; |
|
| 27 | + } |
|
| 28 | + |
|
| 29 | + /** |
|
| 30 | + * Performs additional setup work required to support this schema. |
|
| 31 | + */ |
|
| 32 | + public function init() { |
|
| 33 | + add_action( 'action_scheduler_before_schema_update', array( $this, 'update_schema_5_0' ), 10, 2 ); |
|
| 34 | + } |
|
| 35 | + |
|
| 36 | + protected function get_table_definition( $table ) { |
|
| 37 | + global $wpdb; |
|
| 38 | + $table_name = $wpdb->$table; |
|
| 39 | + $charset_collate = $wpdb->get_charset_collate(); |
|
| 40 | + $max_index_length = 191; // @see wp_get_db_schema() |
|
| 41 | + $default_date = self::DEFAULT_DATE; |
|
| 42 | + switch ( $table ) { |
|
| 43 | + |
|
| 44 | + case self::ACTIONS_TABLE: |
|
| 45 | + |
|
| 46 | + return "CREATE TABLE {$table_name} ( |
|
| 47 | 47 | action_id bigint(20) unsigned NOT NULL auto_increment, |
| 48 | 48 | hook varchar(191) NOT NULL, |
| 49 | 49 | status varchar(20) NOT NULL, |
@@ -67,63 +67,63 @@ discard block |
||
| 67 | 67 | KEY `claim_id_status_scheduled_date_gmt` (`claim_id`, `status`, `scheduled_date_gmt`) |
| 68 | 68 | ) $charset_collate"; |
| 69 | 69 | |
| 70 | - case self::CLAIMS_TABLE: |
|
| 70 | + case self::CLAIMS_TABLE: |
|
| 71 | 71 | |
| 72 | - return "CREATE TABLE {$table_name} ( |
|
| 72 | + return "CREATE TABLE {$table_name} ( |
|
| 73 | 73 | claim_id bigint(20) unsigned NOT NULL auto_increment, |
| 74 | 74 | date_created_gmt datetime NULL default '${default_date}', |
| 75 | 75 | PRIMARY KEY (claim_id), |
| 76 | 76 | KEY date_created_gmt (date_created_gmt) |
| 77 | 77 | ) $charset_collate"; |
| 78 | 78 | |
| 79 | - case self::GROUPS_TABLE: |
|
| 79 | + case self::GROUPS_TABLE: |
|
| 80 | 80 | |
| 81 | - return "CREATE TABLE {$table_name} ( |
|
| 81 | + return "CREATE TABLE {$table_name} ( |
|
| 82 | 82 | group_id bigint(20) unsigned NOT NULL auto_increment, |
| 83 | 83 | slug varchar(255) NOT NULL, |
| 84 | 84 | PRIMARY KEY (group_id), |
| 85 | 85 | KEY slug (slug($max_index_length)) |
| 86 | 86 | ) $charset_collate"; |
| 87 | 87 | |
| 88 | - default: |
|
| 89 | - return ''; |
|
| 90 | - } |
|
| 91 | - } |
|
| 92 | - |
|
| 93 | - /** |
|
| 94 | - * Update the actions table schema, allowing datetime fields to be NULL. |
|
| 95 | - * |
|
| 96 | - * This is needed because the NOT NULL constraint causes a conflict with some versions of MySQL |
|
| 97 | - * configured with sql_mode=NO_ZERO_DATE, which can for instance lead to tables not being created. |
|
| 98 | - * |
|
| 99 | - * Most other schema updates happen via ActionScheduler_Abstract_Schema::update_table(), however |
|
| 100 | - * that method relies on dbDelta() and this change is not possible when using that function. |
|
| 101 | - * |
|
| 102 | - * @param string $table Name of table being updated. |
|
| 103 | - * @param string $db_version The existing schema version of the table. |
|
| 104 | - */ |
|
| 105 | - public function update_schema_5_0( $table, $db_version ) { |
|
| 106 | - global $wpdb; |
|
| 107 | - |
|
| 108 | - if ( 'actionscheduler_actions' !== $table || version_compare( $db_version, '5', '>=' ) ) { |
|
| 109 | - return; |
|
| 110 | - } |
|
| 111 | - |
|
| 112 | - // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
|
| 113 | - $table_name = $wpdb->prefix . 'actionscheduler_actions'; |
|
| 114 | - $table_list = $wpdb->get_col( "SHOW TABLES LIKE '${table_name}'" ); |
|
| 115 | - $default_date = self::DEFAULT_DATE; |
|
| 116 | - |
|
| 117 | - if ( ! empty( $table_list ) ) { |
|
| 118 | - $query = " |
|
| 88 | + default: |
|
| 89 | + return ''; |
|
| 90 | + } |
|
| 91 | + } |
|
| 92 | + |
|
| 93 | + /** |
|
| 94 | + * Update the actions table schema, allowing datetime fields to be NULL. |
|
| 95 | + * |
|
| 96 | + * This is needed because the NOT NULL constraint causes a conflict with some versions of MySQL |
|
| 97 | + * configured with sql_mode=NO_ZERO_DATE, which can for instance lead to tables not being created. |
|
| 98 | + * |
|
| 99 | + * Most other schema updates happen via ActionScheduler_Abstract_Schema::update_table(), however |
|
| 100 | + * that method relies on dbDelta() and this change is not possible when using that function. |
|
| 101 | + * |
|
| 102 | + * @param string $table Name of table being updated. |
|
| 103 | + * @param string $db_version The existing schema version of the table. |
|
| 104 | + */ |
|
| 105 | + public function update_schema_5_0( $table, $db_version ) { |
|
| 106 | + global $wpdb; |
|
| 107 | + |
|
| 108 | + if ( 'actionscheduler_actions' !== $table || version_compare( $db_version, '5', '>=' ) ) { |
|
| 109 | + return; |
|
| 110 | + } |
|
| 111 | + |
|
| 112 | + // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
|
| 113 | + $table_name = $wpdb->prefix . 'actionscheduler_actions'; |
|
| 114 | + $table_list = $wpdb->get_col( "SHOW TABLES LIKE '${table_name}'" ); |
|
| 115 | + $default_date = self::DEFAULT_DATE; |
|
| 116 | + |
|
| 117 | + if ( ! empty( $table_list ) ) { |
|
| 118 | + $query = " |
|
| 119 | 119 | ALTER TABLE ${table_name} |
| 120 | 120 | MODIFY COLUMN scheduled_date_gmt datetime NULL default '${default_date}', |
| 121 | 121 | MODIFY COLUMN scheduled_date_local datetime NULL default '${default_date}', |
| 122 | 122 | MODIFY COLUMN last_attempt_gmt datetime NULL default '${default_date}', |
| 123 | 123 | MODIFY COLUMN last_attempt_local datetime NULL default '${default_date}' |
| 124 | 124 | "; |
| 125 | - $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared |
|
| 126 | - } |
|
| 127 | - // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
|
| 128 | - } |
|
| 125 | + $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared |
|
| 126 | + } |
|
| 127 | + // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
|
| 128 | + } |
|
| 129 | 129 | } |
@@ -8,36 +8,36 @@ discard block |
||
| 8 | 8 | * Creates a custom table for storing action logs |
| 9 | 9 | */ |
| 10 | 10 | class ActionScheduler_LoggerSchema extends ActionScheduler_Abstract_Schema { |
| 11 | - const LOG_TABLE = 'actionscheduler_logs'; |
|
| 11 | + const LOG_TABLE = 'actionscheduler_logs'; |
|
| 12 | 12 | |
| 13 | - /** |
|
| 14 | - * @var int Increment this value to trigger a schema update. |
|
| 15 | - */ |
|
| 16 | - protected $schema_version = 3; |
|
| 13 | + /** |
|
| 14 | + * @var int Increment this value to trigger a schema update. |
|
| 15 | + */ |
|
| 16 | + protected $schema_version = 3; |
|
| 17 | 17 | |
| 18 | - public function __construct() { |
|
| 19 | - $this->tables = [ |
|
| 20 | - self::LOG_TABLE, |
|
| 21 | - ]; |
|
| 22 | - } |
|
| 18 | + public function __construct() { |
|
| 19 | + $this->tables = [ |
|
| 20 | + self::LOG_TABLE, |
|
| 21 | + ]; |
|
| 22 | + } |
|
| 23 | 23 | |
| 24 | - /** |
|
| 25 | - * Performs additional setup work required to support this schema. |
|
| 26 | - */ |
|
| 27 | - public function init() { |
|
| 28 | - add_action( 'action_scheduler_before_schema_update', array( $this, 'update_schema_3_0' ), 10, 2 ); |
|
| 29 | - } |
|
| 24 | + /** |
|
| 25 | + * Performs additional setup work required to support this schema. |
|
| 26 | + */ |
|
| 27 | + public function init() { |
|
| 28 | + add_action( 'action_scheduler_before_schema_update', array( $this, 'update_schema_3_0' ), 10, 2 ); |
|
| 29 | + } |
|
| 30 | 30 | |
| 31 | - protected function get_table_definition( $table ) { |
|
| 32 | - global $wpdb; |
|
| 33 | - $table_name = $wpdb->$table; |
|
| 34 | - $charset_collate = $wpdb->get_charset_collate(); |
|
| 35 | - switch ( $table ) { |
|
| 31 | + protected function get_table_definition( $table ) { |
|
| 32 | + global $wpdb; |
|
| 33 | + $table_name = $wpdb->$table; |
|
| 34 | + $charset_collate = $wpdb->get_charset_collate(); |
|
| 35 | + switch ( $table ) { |
|
| 36 | 36 | |
| 37 | - case self::LOG_TABLE: |
|
| 37 | + case self::LOG_TABLE: |
|
| 38 | 38 | |
| 39 | - $default_date = ActionScheduler_StoreSchema::DEFAULT_DATE; |
|
| 40 | - return "CREATE TABLE {$table_name} ( |
|
| 39 | + $default_date = ActionScheduler_StoreSchema::DEFAULT_DATE; |
|
| 40 | + return "CREATE TABLE {$table_name} ( |
|
| 41 | 41 | log_id bigint(20) unsigned NOT NULL auto_increment, |
| 42 | 42 | action_id bigint(20) unsigned NOT NULL, |
| 43 | 43 | message text NOT NULL, |
@@ -48,43 +48,43 @@ discard block |
||
| 48 | 48 | KEY log_date_gmt (log_date_gmt) |
| 49 | 49 | ) $charset_collate"; |
| 50 | 50 | |
| 51 | - default: |
|
| 52 | - return ''; |
|
| 53 | - } |
|
| 54 | - } |
|
| 51 | + default: |
|
| 52 | + return ''; |
|
| 53 | + } |
|
| 54 | + } |
|
| 55 | 55 | |
| 56 | - /** |
|
| 57 | - * Update the logs table schema, allowing datetime fields to be NULL. |
|
| 58 | - * |
|
| 59 | - * This is needed because the NOT NULL constraint causes a conflict with some versions of MySQL |
|
| 60 | - * configured with sql_mode=NO_ZERO_DATE, which can for instance lead to tables not being created. |
|
| 61 | - * |
|
| 62 | - * Most other schema updates happen via ActionScheduler_Abstract_Schema::update_table(), however |
|
| 63 | - * that method relies on dbDelta() and this change is not possible when using that function. |
|
| 64 | - * |
|
| 65 | - * @param string $table Name of table being updated. |
|
| 66 | - * @param string $db_version The existing schema version of the table. |
|
| 67 | - */ |
|
| 68 | - public function update_schema_3_0( $table, $db_version ) { |
|
| 69 | - global $wpdb; |
|
| 56 | + /** |
|
| 57 | + * Update the logs table schema, allowing datetime fields to be NULL. |
|
| 58 | + * |
|
| 59 | + * This is needed because the NOT NULL constraint causes a conflict with some versions of MySQL |
|
| 60 | + * configured with sql_mode=NO_ZERO_DATE, which can for instance lead to tables not being created. |
|
| 61 | + * |
|
| 62 | + * Most other schema updates happen via ActionScheduler_Abstract_Schema::update_table(), however |
|
| 63 | + * that method relies on dbDelta() and this change is not possible when using that function. |
|
| 64 | + * |
|
| 65 | + * @param string $table Name of table being updated. |
|
| 66 | + * @param string $db_version The existing schema version of the table. |
|
| 67 | + */ |
|
| 68 | + public function update_schema_3_0( $table, $db_version ) { |
|
| 69 | + global $wpdb; |
|
| 70 | 70 | |
| 71 | - if ( 'actionscheduler_logs' !== $table || version_compare( $db_version, '3', '>=' ) ) { |
|
| 72 | - return; |
|
| 73 | - } |
|
| 71 | + if ( 'actionscheduler_logs' !== $table || version_compare( $db_version, '3', '>=' ) ) { |
|
| 72 | + return; |
|
| 73 | + } |
|
| 74 | 74 | |
| 75 | - // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
|
| 76 | - $table_name = $wpdb->prefix . 'actionscheduler_logs'; |
|
| 77 | - $table_list = $wpdb->get_col( "SHOW TABLES LIKE '${table_name}'" ); |
|
| 78 | - $default_date = ActionScheduler_StoreSchema::DEFAULT_DATE; |
|
| 75 | + // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
|
| 76 | + $table_name = $wpdb->prefix . 'actionscheduler_logs'; |
|
| 77 | + $table_list = $wpdb->get_col( "SHOW TABLES LIKE '${table_name}'" ); |
|
| 78 | + $default_date = ActionScheduler_StoreSchema::DEFAULT_DATE; |
|
| 79 | 79 | |
| 80 | - if ( ! empty( $table_list ) ) { |
|
| 81 | - $query = " |
|
| 80 | + if ( ! empty( $table_list ) ) { |
|
| 81 | + $query = " |
|
| 82 | 82 | ALTER TABLE ${table_name} |
| 83 | 83 | MODIFY COLUMN log_date_gmt datetime NULL default '${default_date}', |
| 84 | 84 | MODIFY COLUMN log_date_local datetime NULL default '${default_date}' |
| 85 | 85 | "; |
| 86 | - $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared |
|
| 87 | - } |
|
| 88 | - // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
|
| 89 | - } |
|
| 86 | + $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared |
|
| 87 | + } |
|
| 88 | + // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
|
| 89 | + } |
|
| 90 | 90 | } |
@@ -5,105 +5,105 @@ |
||
| 5 | 5 | */ |
| 6 | 6 | class ActionScheduler_Compatibility { |
| 7 | 7 | |
| 8 | - /** |
|
| 9 | - * Converts a shorthand byte value to an integer byte value. |
|
| 10 | - * |
|
| 11 | - * Wrapper for wp_convert_hr_to_bytes(), moved to load.php in WordPress 4.6 from media.php |
|
| 12 | - * |
|
| 13 | - * @link https://secure.php.net/manual/en/function.ini-get.php |
|
| 14 | - * @link https://secure.php.net/manual/en/faq.using.php#faq.using.shorthandbytes |
|
| 15 | - * |
|
| 16 | - * @param string $value A (PHP ini) byte value, either shorthand or ordinary. |
|
| 17 | - * @return int An integer byte value. |
|
| 18 | - */ |
|
| 19 | - public static function convert_hr_to_bytes( $value ) { |
|
| 20 | - if ( function_exists( 'wp_convert_hr_to_bytes' ) ) { |
|
| 21 | - return wp_convert_hr_to_bytes( $value ); |
|
| 22 | - } |
|
| 8 | + /** |
|
| 9 | + * Converts a shorthand byte value to an integer byte value. |
|
| 10 | + * |
|
| 11 | + * Wrapper for wp_convert_hr_to_bytes(), moved to load.php in WordPress 4.6 from media.php |
|
| 12 | + * |
|
| 13 | + * @link https://secure.php.net/manual/en/function.ini-get.php |
|
| 14 | + * @link https://secure.php.net/manual/en/faq.using.php#faq.using.shorthandbytes |
|
| 15 | + * |
|
| 16 | + * @param string $value A (PHP ini) byte value, either shorthand or ordinary. |
|
| 17 | + * @return int An integer byte value. |
|
| 18 | + */ |
|
| 19 | + public static function convert_hr_to_bytes( $value ) { |
|
| 20 | + if ( function_exists( 'wp_convert_hr_to_bytes' ) ) { |
|
| 21 | + return wp_convert_hr_to_bytes( $value ); |
|
| 22 | + } |
|
| 23 | 23 | |
| 24 | - $value = strtolower( trim( $value ) ); |
|
| 25 | - $bytes = (int) $value; |
|
| 24 | + $value = strtolower( trim( $value ) ); |
|
| 25 | + $bytes = (int) $value; |
|
| 26 | 26 | |
| 27 | - if ( false !== strpos( $value, 'g' ) ) { |
|
| 28 | - $bytes *= GB_IN_BYTES; |
|
| 29 | - } elseif ( false !== strpos( $value, 'm' ) ) { |
|
| 30 | - $bytes *= MB_IN_BYTES; |
|
| 31 | - } elseif ( false !== strpos( $value, 'k' ) ) { |
|
| 32 | - $bytes *= KB_IN_BYTES; |
|
| 33 | - } |
|
| 27 | + if ( false !== strpos( $value, 'g' ) ) { |
|
| 28 | + $bytes *= GB_IN_BYTES; |
|
| 29 | + } elseif ( false !== strpos( $value, 'm' ) ) { |
|
| 30 | + $bytes *= MB_IN_BYTES; |
|
| 31 | + } elseif ( false !== strpos( $value, 'k' ) ) { |
|
| 32 | + $bytes *= KB_IN_BYTES; |
|
| 33 | + } |
|
| 34 | 34 | |
| 35 | - // Deal with large (float) values which run into the maximum integer size. |
|
| 36 | - return min( $bytes, PHP_INT_MAX ); |
|
| 37 | - } |
|
| 35 | + // Deal with large (float) values which run into the maximum integer size. |
|
| 36 | + return min( $bytes, PHP_INT_MAX ); |
|
| 37 | + } |
|
| 38 | 38 | |
| 39 | - /** |
|
| 40 | - * Attempts to raise the PHP memory limit for memory intensive processes. |
|
| 41 | - * |
|
| 42 | - * Only allows raising the existing limit and prevents lowering it. |
|
| 43 | - * |
|
| 44 | - * Wrapper for wp_raise_memory_limit(), added in WordPress v4.6.0 |
|
| 45 | - * |
|
| 46 | - * @return bool|int|string The limit that was set or false on failure. |
|
| 47 | - */ |
|
| 48 | - public static function raise_memory_limit() { |
|
| 49 | - if ( function_exists( 'wp_raise_memory_limit' ) ) { |
|
| 50 | - return wp_raise_memory_limit( 'admin' ); |
|
| 51 | - } |
|
| 39 | + /** |
|
| 40 | + * Attempts to raise the PHP memory limit for memory intensive processes. |
|
| 41 | + * |
|
| 42 | + * Only allows raising the existing limit and prevents lowering it. |
|
| 43 | + * |
|
| 44 | + * Wrapper for wp_raise_memory_limit(), added in WordPress v4.6.0 |
|
| 45 | + * |
|
| 46 | + * @return bool|int|string The limit that was set or false on failure. |
|
| 47 | + */ |
|
| 48 | + public static function raise_memory_limit() { |
|
| 49 | + if ( function_exists( 'wp_raise_memory_limit' ) ) { |
|
| 50 | + return wp_raise_memory_limit( 'admin' ); |
|
| 51 | + } |
|
| 52 | 52 | |
| 53 | - $current_limit = @ini_get( 'memory_limit' ); |
|
| 54 | - $current_limit_int = self::convert_hr_to_bytes( $current_limit ); |
|
| 53 | + $current_limit = @ini_get( 'memory_limit' ); |
|
| 54 | + $current_limit_int = self::convert_hr_to_bytes( $current_limit ); |
|
| 55 | 55 | |
| 56 | - if ( -1 === $current_limit_int ) { |
|
| 57 | - return false; |
|
| 58 | - } |
|
| 56 | + if ( -1 === $current_limit_int ) { |
|
| 57 | + return false; |
|
| 58 | + } |
|
| 59 | 59 | |
| 60 | - $wp_max_limit = WP_MAX_MEMORY_LIMIT; |
|
| 61 | - $wp_max_limit_int = self::convert_hr_to_bytes( $wp_max_limit ); |
|
| 62 | - $filtered_limit = apply_filters( 'admin_memory_limit', $wp_max_limit ); |
|
| 63 | - $filtered_limit_int = self::convert_hr_to_bytes( $filtered_limit ); |
|
| 60 | + $wp_max_limit = WP_MAX_MEMORY_LIMIT; |
|
| 61 | + $wp_max_limit_int = self::convert_hr_to_bytes( $wp_max_limit ); |
|
| 62 | + $filtered_limit = apply_filters( 'admin_memory_limit', $wp_max_limit ); |
|
| 63 | + $filtered_limit_int = self::convert_hr_to_bytes( $filtered_limit ); |
|
| 64 | 64 | |
| 65 | - if ( -1 === $filtered_limit_int || ( $filtered_limit_int > $wp_max_limit_int && $filtered_limit_int > $current_limit_int ) ) { |
|
| 66 | - if ( false !== @ini_set( 'memory_limit', $filtered_limit ) ) { |
|
| 67 | - return $filtered_limit; |
|
| 68 | - } else { |
|
| 69 | - return false; |
|
| 70 | - } |
|
| 71 | - } elseif ( -1 === $wp_max_limit_int || $wp_max_limit_int > $current_limit_int ) { |
|
| 72 | - if ( false !== @ini_set( 'memory_limit', $wp_max_limit ) ) { |
|
| 73 | - return $wp_max_limit; |
|
| 74 | - } else { |
|
| 75 | - return false; |
|
| 76 | - } |
|
| 77 | - } |
|
| 78 | - return false; |
|
| 79 | - } |
|
| 65 | + if ( -1 === $filtered_limit_int || ( $filtered_limit_int > $wp_max_limit_int && $filtered_limit_int > $current_limit_int ) ) { |
|
| 66 | + if ( false !== @ini_set( 'memory_limit', $filtered_limit ) ) { |
|
| 67 | + return $filtered_limit; |
|
| 68 | + } else { |
|
| 69 | + return false; |
|
| 70 | + } |
|
| 71 | + } elseif ( -1 === $wp_max_limit_int || $wp_max_limit_int > $current_limit_int ) { |
|
| 72 | + if ( false !== @ini_set( 'memory_limit', $wp_max_limit ) ) { |
|
| 73 | + return $wp_max_limit; |
|
| 74 | + } else { |
|
| 75 | + return false; |
|
| 76 | + } |
|
| 77 | + } |
|
| 78 | + return false; |
|
| 79 | + } |
|
| 80 | 80 | |
| 81 | - /** |
|
| 82 | - * Attempts to raise the PHP timeout for time intensive processes. |
|
| 83 | - * |
|
| 84 | - * Only allows raising the existing limit and prevents lowering it. Wrapper for wc_set_time_limit(), when available. |
|
| 85 | - * |
|
| 86 | - * @param int $limit The time limit in seconds. |
|
| 87 | - */ |
|
| 88 | - public static function raise_time_limit( $limit = 0 ) { |
|
| 89 | - $limit = (int) $limit; |
|
| 90 | - $max_execution_time = (int) ini_get( 'max_execution_time' ); |
|
| 81 | + /** |
|
| 82 | + * Attempts to raise the PHP timeout for time intensive processes. |
|
| 83 | + * |
|
| 84 | + * Only allows raising the existing limit and prevents lowering it. Wrapper for wc_set_time_limit(), when available. |
|
| 85 | + * |
|
| 86 | + * @param int $limit The time limit in seconds. |
|
| 87 | + */ |
|
| 88 | + public static function raise_time_limit( $limit = 0 ) { |
|
| 89 | + $limit = (int) $limit; |
|
| 90 | + $max_execution_time = (int) ini_get( 'max_execution_time' ); |
|
| 91 | 91 | |
| 92 | - /* |
|
| 92 | + /* |
|
| 93 | 93 | * If the max execution time is already unlimited (zero), or if it exceeds or is equal to the proposed |
| 94 | 94 | * limit, there is no reason for us to make further changes (we never want to lower it). |
| 95 | 95 | */ |
| 96 | - if ( |
|
| 97 | - 0 === $max_execution_time |
|
| 98 | - || ( $max_execution_time >= $limit && $limit !== 0 ) |
|
| 99 | - ) { |
|
| 100 | - return; |
|
| 101 | - } |
|
| 96 | + if ( |
|
| 97 | + 0 === $max_execution_time |
|
| 98 | + || ( $max_execution_time >= $limit && $limit !== 0 ) |
|
| 99 | + ) { |
|
| 100 | + return; |
|
| 101 | + } |
|
| 102 | 102 | |
| 103 | - if ( function_exists( 'wc_set_time_limit' ) ) { |
|
| 104 | - wc_set_time_limit( $limit ); |
|
| 105 | - } elseif ( function_exists( 'set_time_limit' ) && false === strpos( ini_get( 'disable_functions' ), 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) { // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.safe_modeDeprecatedRemoved |
|
| 106 | - @set_time_limit( $limit ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged |
|
| 107 | - } |
|
| 108 | - } |
|
| 103 | + if ( function_exists( 'wc_set_time_limit' ) ) { |
|
| 104 | + wc_set_time_limit( $limit ); |
|
| 105 | + } elseif ( function_exists( 'set_time_limit' ) && false === strpos( ini_get( 'disable_functions' ), 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) { // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.safe_modeDeprecatedRemoved |
|
| 106 | + @set_time_limit( $limit ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged |
|
| 107 | + } |
|
| 108 | + } |
|
| 109 | 109 | } |
@@ -9,189 +9,189 @@ |
||
| 9 | 9 | */ |
| 10 | 10 | class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRunner { |
| 11 | 11 | |
| 12 | - /** @var array */ |
|
| 13 | - protected $actions; |
|
| 14 | - |
|
| 15 | - /** @var ActionScheduler_ActionClaim */ |
|
| 16 | - protected $claim; |
|
| 17 | - |
|
| 18 | - /** @var \cli\progress\Bar */ |
|
| 19 | - protected $progress_bar; |
|
| 20 | - |
|
| 21 | - /** |
|
| 22 | - * ActionScheduler_WPCLI_QueueRunner constructor. |
|
| 23 | - * |
|
| 24 | - * @param ActionScheduler_Store $store |
|
| 25 | - * @param ActionScheduler_FatalErrorMonitor $monitor |
|
| 26 | - * @param ActionScheduler_QueueCleaner $cleaner |
|
| 27 | - * |
|
| 28 | - * @throws Exception When this is not run within WP CLI |
|
| 29 | - */ |
|
| 30 | - public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null ) { |
|
| 31 | - if ( ! ( defined( 'WP_CLI' ) && WP_CLI ) ) { |
|
| 32 | - /* translators: %s php class name */ |
|
| 33 | - throw new Exception( sprintf( __( 'The %s class can only be run within WP CLI.', 'woocommerce' ), __CLASS__ ) ); |
|
| 34 | - } |
|
| 35 | - |
|
| 36 | - parent::__construct( $store, $monitor, $cleaner ); |
|
| 37 | - } |
|
| 38 | - |
|
| 39 | - /** |
|
| 40 | - * Set up the Queue before processing. |
|
| 41 | - * |
|
| 42 | - * @author Jeremy Pry |
|
| 43 | - * |
|
| 44 | - * @param int $batch_size The batch size to process. |
|
| 45 | - * @param array $hooks The hooks being used to filter the actions claimed in this batch. |
|
| 46 | - * @param string $group The group of actions to claim with this batch. |
|
| 47 | - * @param bool $force Whether to force running even with too many concurrent processes. |
|
| 48 | - * |
|
| 49 | - * @return int The number of actions that will be run. |
|
| 50 | - * @throws \WP_CLI\ExitException When there are too many concurrent batches. |
|
| 51 | - */ |
|
| 52 | - public function setup( $batch_size, $hooks = array(), $group = '', $force = false ) { |
|
| 53 | - $this->run_cleanup(); |
|
| 54 | - $this->add_hooks(); |
|
| 55 | - |
|
| 56 | - // Check to make sure there aren't too many concurrent processes running. |
|
| 57 | - if ( $this->has_maximum_concurrent_batches() ) { |
|
| 58 | - if ( $force ) { |
|
| 59 | - WP_CLI::warning( __( 'There are too many concurrent batches, but the run is forced to continue.', 'woocommerce' ) ); |
|
| 60 | - } else { |
|
| 61 | - WP_CLI::error( __( 'There are too many concurrent batches.', 'woocommerce' ) ); |
|
| 62 | - } |
|
| 63 | - } |
|
| 64 | - |
|
| 65 | - // Stake a claim and store it. |
|
| 66 | - $this->claim = $this->store->stake_claim( $batch_size, null, $hooks, $group ); |
|
| 67 | - $this->monitor->attach( $this->claim ); |
|
| 68 | - $this->actions = $this->claim->get_actions(); |
|
| 69 | - |
|
| 70 | - return count( $this->actions ); |
|
| 71 | - } |
|
| 72 | - |
|
| 73 | - /** |
|
| 74 | - * Add our hooks to the appropriate actions. |
|
| 75 | - * |
|
| 76 | - * @author Jeremy Pry |
|
| 77 | - */ |
|
| 78 | - protected function add_hooks() { |
|
| 79 | - add_action( 'action_scheduler_before_execute', array( $this, 'before_execute' ) ); |
|
| 80 | - add_action( 'action_scheduler_after_execute', array( $this, 'after_execute' ), 10, 2 ); |
|
| 81 | - add_action( 'action_scheduler_failed_execution', array( $this, 'action_failed' ), 10, 2 ); |
|
| 82 | - } |
|
| 83 | - |
|
| 84 | - /** |
|
| 85 | - * Set up the WP CLI progress bar. |
|
| 86 | - * |
|
| 87 | - * @author Jeremy Pry |
|
| 88 | - */ |
|
| 89 | - protected function setup_progress_bar() { |
|
| 90 | - $count = count( $this->actions ); |
|
| 91 | - $this->progress_bar = new ProgressBar( |
|
| 92 | - /* translators: %d: amount of actions */ |
|
| 93 | - sprintf( _n( 'Running %d action', 'Running %d actions', $count, 'woocommerce' ), number_format_i18n( $count ) ), |
|
| 94 | - $count |
|
| 95 | - ); |
|
| 96 | - } |
|
| 97 | - |
|
| 98 | - /** |
|
| 99 | - * Process actions in the queue. |
|
| 100 | - * |
|
| 101 | - * @author Jeremy Pry |
|
| 102 | - * |
|
| 103 | - * @param string $context Optional runner context. Default 'WP CLI'. |
|
| 104 | - * |
|
| 105 | - * @return int The number of actions processed. |
|
| 106 | - */ |
|
| 107 | - public function run( $context = 'WP CLI' ) { |
|
| 108 | - do_action( 'action_scheduler_before_process_queue' ); |
|
| 109 | - $this->setup_progress_bar(); |
|
| 110 | - foreach ( $this->actions as $action_id ) { |
|
| 111 | - // Error if we lost the claim. |
|
| 112 | - if ( ! in_array( $action_id, $this->store->find_actions_by_claim_id( $this->claim->get_id() ) ) ) { |
|
| 113 | - WP_CLI::warning( __( 'The claim has been lost. Aborting current batch.', 'woocommerce' ) ); |
|
| 114 | - break; |
|
| 115 | - } |
|
| 116 | - |
|
| 117 | - $this->process_action( $action_id, $context ); |
|
| 118 | - $this->progress_bar->tick(); |
|
| 119 | - } |
|
| 120 | - |
|
| 121 | - $completed = $this->progress_bar->current(); |
|
| 122 | - $this->progress_bar->finish(); |
|
| 123 | - $this->store->release_claim( $this->claim ); |
|
| 124 | - do_action( 'action_scheduler_after_process_queue' ); |
|
| 125 | - |
|
| 126 | - return $completed; |
|
| 127 | - } |
|
| 128 | - |
|
| 129 | - /** |
|
| 130 | - * Handle WP CLI message when the action is starting. |
|
| 131 | - * |
|
| 132 | - * @author Jeremy Pry |
|
| 133 | - * |
|
| 134 | - * @param $action_id |
|
| 135 | - */ |
|
| 136 | - public function before_execute( $action_id ) { |
|
| 137 | - /* translators: %s refers to the action ID */ |
|
| 138 | - WP_CLI::log( sprintf( __( 'Started processing action %s', 'woocommerce' ), $action_id ) ); |
|
| 139 | - } |
|
| 140 | - |
|
| 141 | - /** |
|
| 142 | - * Handle WP CLI message when the action has completed. |
|
| 143 | - * |
|
| 144 | - * @author Jeremy Pry |
|
| 145 | - * |
|
| 146 | - * @param int $action_id |
|
| 147 | - * @param null|ActionScheduler_Action $action The instance of the action. Default to null for backward compatibility. |
|
| 148 | - */ |
|
| 149 | - public function after_execute( $action_id, $action = null ) { |
|
| 150 | - // backward compatibility |
|
| 151 | - if ( null === $action ) { |
|
| 152 | - $action = $this->store->fetch_action( $action_id ); |
|
| 153 | - } |
|
| 154 | - /* translators: 1: action ID 2: hook name */ |
|
| 155 | - WP_CLI::log( sprintf( __( 'Completed processing action %1$s with hook: %2$s', 'woocommerce' ), $action_id, $action->get_hook() ) ); |
|
| 156 | - } |
|
| 157 | - |
|
| 158 | - /** |
|
| 159 | - * Handle WP CLI message when the action has failed. |
|
| 160 | - * |
|
| 161 | - * @author Jeremy Pry |
|
| 162 | - * |
|
| 163 | - * @param int $action_id |
|
| 164 | - * @param Exception $exception |
|
| 165 | - * @throws \WP_CLI\ExitException With failure message. |
|
| 166 | - */ |
|
| 167 | - public function action_failed( $action_id, $exception ) { |
|
| 168 | - WP_CLI::error( |
|
| 169 | - /* translators: 1: action ID 2: exception message */ |
|
| 170 | - sprintf( __( 'Error processing action %1$s: %2$s', 'woocommerce' ), $action_id, $exception->getMessage() ), |
|
| 171 | - false |
|
| 172 | - ); |
|
| 173 | - } |
|
| 174 | - |
|
| 175 | - /** |
|
| 176 | - * Sleep and help avoid hitting memory limit |
|
| 177 | - * |
|
| 178 | - * @param int $sleep_time Amount of seconds to sleep |
|
| 179 | - * @deprecated 3.0.0 |
|
| 180 | - */ |
|
| 181 | - protected function stop_the_insanity( $sleep_time = 0 ) { |
|
| 182 | - _deprecated_function( 'ActionScheduler_WPCLI_QueueRunner::stop_the_insanity', '3.0.0', 'ActionScheduler_DataController::free_memory' ); |
|
| 183 | - |
|
| 184 | - ActionScheduler_DataController::free_memory(); |
|
| 185 | - } |
|
| 186 | - |
|
| 187 | - /** |
|
| 188 | - * Maybe trigger the stop_the_insanity() method to free up memory. |
|
| 189 | - */ |
|
| 190 | - protected function maybe_stop_the_insanity() { |
|
| 191 | - // The value returned by progress_bar->current() might be padded. Remove padding, and convert to int. |
|
| 192 | - $current_iteration = intval( trim( $this->progress_bar->current() ) ); |
|
| 193 | - if ( 0 === $current_iteration % 50 ) { |
|
| 194 | - $this->stop_the_insanity(); |
|
| 195 | - } |
|
| 196 | - } |
|
| 12 | + /** @var array */ |
|
| 13 | + protected $actions; |
|
| 14 | + |
|
| 15 | + /** @var ActionScheduler_ActionClaim */ |
|
| 16 | + protected $claim; |
|
| 17 | + |
|
| 18 | + /** @var \cli\progress\Bar */ |
|
| 19 | + protected $progress_bar; |
|
| 20 | + |
|
| 21 | + /** |
|
| 22 | + * ActionScheduler_WPCLI_QueueRunner constructor. |
|
| 23 | + * |
|
| 24 | + * @param ActionScheduler_Store $store |
|
| 25 | + * @param ActionScheduler_FatalErrorMonitor $monitor |
|
| 26 | + * @param ActionScheduler_QueueCleaner $cleaner |
|
| 27 | + * |
|
| 28 | + * @throws Exception When this is not run within WP CLI |
|
| 29 | + */ |
|
| 30 | + public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null ) { |
|
| 31 | + if ( ! ( defined( 'WP_CLI' ) && WP_CLI ) ) { |
|
| 32 | + /* translators: %s php class name */ |
|
| 33 | + throw new Exception( sprintf( __( 'The %s class can only be run within WP CLI.', 'woocommerce' ), __CLASS__ ) ); |
|
| 34 | + } |
|
| 35 | + |
|
| 36 | + parent::__construct( $store, $monitor, $cleaner ); |
|
| 37 | + } |
|
| 38 | + |
|
| 39 | + /** |
|
| 40 | + * Set up the Queue before processing. |
|
| 41 | + * |
|
| 42 | + * @author Jeremy Pry |
|
| 43 | + * |
|
| 44 | + * @param int $batch_size The batch size to process. |
|
| 45 | + * @param array $hooks The hooks being used to filter the actions claimed in this batch. |
|
| 46 | + * @param string $group The group of actions to claim with this batch. |
|
| 47 | + * @param bool $force Whether to force running even with too many concurrent processes. |
|
| 48 | + * |
|
| 49 | + * @return int The number of actions that will be run. |
|
| 50 | + * @throws \WP_CLI\ExitException When there are too many concurrent batches. |
|
| 51 | + */ |
|
| 52 | + public function setup( $batch_size, $hooks = array(), $group = '', $force = false ) { |
|
| 53 | + $this->run_cleanup(); |
|
| 54 | + $this->add_hooks(); |
|
| 55 | + |
|
| 56 | + // Check to make sure there aren't too many concurrent processes running. |
|
| 57 | + if ( $this->has_maximum_concurrent_batches() ) { |
|
| 58 | + if ( $force ) { |
|
| 59 | + WP_CLI::warning( __( 'There are too many concurrent batches, but the run is forced to continue.', 'woocommerce' ) ); |
|
| 60 | + } else { |
|
| 61 | + WP_CLI::error( __( 'There are too many concurrent batches.', 'woocommerce' ) ); |
|
| 62 | + } |
|
| 63 | + } |
|
| 64 | + |
|
| 65 | + // Stake a claim and store it. |
|
| 66 | + $this->claim = $this->store->stake_claim( $batch_size, null, $hooks, $group ); |
|
| 67 | + $this->monitor->attach( $this->claim ); |
|
| 68 | + $this->actions = $this->claim->get_actions(); |
|
| 69 | + |
|
| 70 | + return count( $this->actions ); |
|
| 71 | + } |
|
| 72 | + |
|
| 73 | + /** |
|
| 74 | + * Add our hooks to the appropriate actions. |
|
| 75 | + * |
|
| 76 | + * @author Jeremy Pry |
|
| 77 | + */ |
|
| 78 | + protected function add_hooks() { |
|
| 79 | + add_action( 'action_scheduler_before_execute', array( $this, 'before_execute' ) ); |
|
| 80 | + add_action( 'action_scheduler_after_execute', array( $this, 'after_execute' ), 10, 2 ); |
|
| 81 | + add_action( 'action_scheduler_failed_execution', array( $this, 'action_failed' ), 10, 2 ); |
|
| 82 | + } |
|
| 83 | + |
|
| 84 | + /** |
|
| 85 | + * Set up the WP CLI progress bar. |
|
| 86 | + * |
|
| 87 | + * @author Jeremy Pry |
|
| 88 | + */ |
|
| 89 | + protected function setup_progress_bar() { |
|
| 90 | + $count = count( $this->actions ); |
|
| 91 | + $this->progress_bar = new ProgressBar( |
|
| 92 | + /* translators: %d: amount of actions */ |
|
| 93 | + sprintf( _n( 'Running %d action', 'Running %d actions', $count, 'woocommerce' ), number_format_i18n( $count ) ), |
|
| 94 | + $count |
|
| 95 | + ); |
|
| 96 | + } |
|
| 97 | + |
|
| 98 | + /** |
|
| 99 | + * Process actions in the queue. |
|
| 100 | + * |
|
| 101 | + * @author Jeremy Pry |
|
| 102 | + * |
|
| 103 | + * @param string $context Optional runner context. Default 'WP CLI'. |
|
| 104 | + * |
|
| 105 | + * @return int The number of actions processed. |
|
| 106 | + */ |
|
| 107 | + public function run( $context = 'WP CLI' ) { |
|
| 108 | + do_action( 'action_scheduler_before_process_queue' ); |
|
| 109 | + $this->setup_progress_bar(); |
|
| 110 | + foreach ( $this->actions as $action_id ) { |
|
| 111 | + // Error if we lost the claim. |
|
| 112 | + if ( ! in_array( $action_id, $this->store->find_actions_by_claim_id( $this->claim->get_id() ) ) ) { |
|
| 113 | + WP_CLI::warning( __( 'The claim has been lost. Aborting current batch.', 'woocommerce' ) ); |
|
| 114 | + break; |
|
| 115 | + } |
|
| 116 | + |
|
| 117 | + $this->process_action( $action_id, $context ); |
|
| 118 | + $this->progress_bar->tick(); |
|
| 119 | + } |
|
| 120 | + |
|
| 121 | + $completed = $this->progress_bar->current(); |
|
| 122 | + $this->progress_bar->finish(); |
|
| 123 | + $this->store->release_claim( $this->claim ); |
|
| 124 | + do_action( 'action_scheduler_after_process_queue' ); |
|
| 125 | + |
|
| 126 | + return $completed; |
|
| 127 | + } |
|
| 128 | + |
|
| 129 | + /** |
|
| 130 | + * Handle WP CLI message when the action is starting. |
|
| 131 | + * |
|
| 132 | + * @author Jeremy Pry |
|
| 133 | + * |
|
| 134 | + * @param $action_id |
|
| 135 | + */ |
|
| 136 | + public function before_execute( $action_id ) { |
|
| 137 | + /* translators: %s refers to the action ID */ |
|
| 138 | + WP_CLI::log( sprintf( __( 'Started processing action %s', 'woocommerce' ), $action_id ) ); |
|
| 139 | + } |
|
| 140 | + |
|
| 141 | + /** |
|
| 142 | + * Handle WP CLI message when the action has completed. |
|
| 143 | + * |
|
| 144 | + * @author Jeremy Pry |
|
| 145 | + * |
|
| 146 | + * @param int $action_id |
|
| 147 | + * @param null|ActionScheduler_Action $action The instance of the action. Default to null for backward compatibility. |
|
| 148 | + */ |
|
| 149 | + public function after_execute( $action_id, $action = null ) { |
|
| 150 | + // backward compatibility |
|
| 151 | + if ( null === $action ) { |
|
| 152 | + $action = $this->store->fetch_action( $action_id ); |
|
| 153 | + } |
|
| 154 | + /* translators: 1: action ID 2: hook name */ |
|
| 155 | + WP_CLI::log( sprintf( __( 'Completed processing action %1$s with hook: %2$s', 'woocommerce' ), $action_id, $action->get_hook() ) ); |
|
| 156 | + } |
|
| 157 | + |
|
| 158 | + /** |
|
| 159 | + * Handle WP CLI message when the action has failed. |
|
| 160 | + * |
|
| 161 | + * @author Jeremy Pry |
|
| 162 | + * |
|
| 163 | + * @param int $action_id |
|
| 164 | + * @param Exception $exception |
|
| 165 | + * @throws \WP_CLI\ExitException With failure message. |
|
| 166 | + */ |
|
| 167 | + public function action_failed( $action_id, $exception ) { |
|
| 168 | + WP_CLI::error( |
|
| 169 | + /* translators: 1: action ID 2: exception message */ |
|
| 170 | + sprintf( __( 'Error processing action %1$s: %2$s', 'woocommerce' ), $action_id, $exception->getMessage() ), |
|
| 171 | + false |
|
| 172 | + ); |
|
| 173 | + } |
|
| 174 | + |
|
| 175 | + /** |
|
| 176 | + * Sleep and help avoid hitting memory limit |
|
| 177 | + * |
|
| 178 | + * @param int $sleep_time Amount of seconds to sleep |
|
| 179 | + * @deprecated 3.0.0 |
|
| 180 | + */ |
|
| 181 | + protected function stop_the_insanity( $sleep_time = 0 ) { |
|
| 182 | + _deprecated_function( 'ActionScheduler_WPCLI_QueueRunner::stop_the_insanity', '3.0.0', 'ActionScheduler_DataController::free_memory' ); |
|
| 183 | + |
|
| 184 | + ActionScheduler_DataController::free_memory(); |
|
| 185 | + } |
|
| 186 | + |
|
| 187 | + /** |
|
| 188 | + * Maybe trigger the stop_the_insanity() method to free up memory. |
|
| 189 | + */ |
|
| 190 | + protected function maybe_stop_the_insanity() { |
|
| 191 | + // The value returned by progress_bar->current() might be padded. Remove padding, and convert to int. |
|
| 192 | + $current_iteration = intval( trim( $this->progress_bar->current() ) ); |
|
| 193 | + if ( 0 === $current_iteration % 50 ) { |
|
| 194 | + $this->stop_the_insanity(); |
|
| 195 | + } |
|
| 196 | + } |
|
| 197 | 197 | } |
@@ -5,184 +5,184 @@ |
||
| 5 | 5 | */ |
| 6 | 6 | class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command { |
| 7 | 7 | |
| 8 | - /** |
|
| 9 | - * Force tables schema creation for Action Scheduler |
|
| 10 | - * |
|
| 11 | - * ## OPTIONS |
|
| 12 | - * |
|
| 13 | - * @param array $args Positional arguments. |
|
| 14 | - * @param array $assoc_args Keyed arguments. |
|
| 15 | - * |
|
| 16 | - * @subcommand fix-schema |
|
| 17 | - */ |
|
| 18 | - public function fix_schema( $args, $assoc_args ) { |
|
| 19 | - $schema_classes = array( ActionScheduler_LoggerSchema::class, ActionScheduler_StoreSchema::class ); |
|
| 20 | - |
|
| 21 | - foreach ( $schema_classes as $classname ) { |
|
| 22 | - if ( is_subclass_of( $classname, ActionScheduler_Abstract_Schema::class ) ) { |
|
| 23 | - $obj = new $classname(); |
|
| 24 | - $obj->init(); |
|
| 25 | - $obj->register_tables( true ); |
|
| 26 | - |
|
| 27 | - WP_CLI::success( |
|
| 28 | - sprintf( |
|
| 29 | - /* translators: %s refers to the schema name*/ |
|
| 30 | - __( 'Registered schema for %s', 'woocommerce' ), |
|
| 31 | - $classname |
|
| 32 | - ) |
|
| 33 | - ); |
|
| 34 | - } |
|
| 35 | - } |
|
| 36 | - } |
|
| 37 | - |
|
| 38 | - /** |
|
| 39 | - * Run the Action Scheduler |
|
| 40 | - * |
|
| 41 | - * ## OPTIONS |
|
| 42 | - * |
|
| 43 | - * [--batch-size=<size>] |
|
| 44 | - * : The maximum number of actions to run. Defaults to 100. |
|
| 45 | - * |
|
| 46 | - * [--batches=<size>] |
|
| 47 | - * : Limit execution to a number of batches. Defaults to 0, meaning batches will continue being executed until all actions are complete. |
|
| 48 | - * |
|
| 49 | - * [--cleanup-batch-size=<size>] |
|
| 50 | - * : The maximum number of actions to clean up. Defaults to the value of --batch-size. |
|
| 51 | - * |
|
| 52 | - * [--hooks=<hooks>] |
|
| 53 | - * : Only run actions with the specified hook. Omitting this option runs actions with any hook. Define multiple hooks as a comma separated string (without spaces), e.g. `--hooks=hook_one,hook_two,hook_three` |
|
| 54 | - * |
|
| 55 | - * [--group=<group>] |
|
| 56 | - * : Only run actions from the specified group. Omitting this option runs actions from all groups. |
|
| 57 | - * |
|
| 58 | - * [--free-memory-on=<count>] |
|
| 59 | - * : The number of actions to process between freeing memory. 0 disables freeing memory. Default 50. |
|
| 60 | - * |
|
| 61 | - * [--pause=<seconds>] |
|
| 62 | - * : The number of seconds to pause when freeing memory. Default no pause. |
|
| 63 | - * |
|
| 64 | - * [--force] |
|
| 65 | - * : Whether to force execution despite the maximum number of concurrent processes being exceeded. |
|
| 66 | - * |
|
| 67 | - * @param array $args Positional arguments. |
|
| 68 | - * @param array $assoc_args Keyed arguments. |
|
| 69 | - * @throws \WP_CLI\ExitException When an error occurs. |
|
| 70 | - * |
|
| 71 | - * @subcommand run |
|
| 72 | - */ |
|
| 73 | - public function run( $args, $assoc_args ) { |
|
| 74 | - // Handle passed arguments. |
|
| 75 | - $batch = absint( \WP_CLI\Utils\get_flag_value( $assoc_args, 'batch-size', 100 ) ); |
|
| 76 | - $batches = absint( \WP_CLI\Utils\get_flag_value( $assoc_args, 'batches', 0 ) ); |
|
| 77 | - $clean = absint( \WP_CLI\Utils\get_flag_value( $assoc_args, 'cleanup-batch-size', $batch ) ); |
|
| 78 | - $hooks = explode( ',', WP_CLI\Utils\get_flag_value( $assoc_args, 'hooks', '' ) ); |
|
| 79 | - $hooks = array_filter( array_map( 'trim', $hooks ) ); |
|
| 80 | - $group = \WP_CLI\Utils\get_flag_value( $assoc_args, 'group', '' ); |
|
| 81 | - $free_on = \WP_CLI\Utils\get_flag_value( $assoc_args, 'free-memory-on', 50 ); |
|
| 82 | - $sleep = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pause', 0 ); |
|
| 83 | - $force = \WP_CLI\Utils\get_flag_value( $assoc_args, 'force', false ); |
|
| 84 | - |
|
| 85 | - ActionScheduler_DataController::set_free_ticks( $free_on ); |
|
| 86 | - ActionScheduler_DataController::set_sleep_time( $sleep ); |
|
| 87 | - |
|
| 88 | - $batches_completed = 0; |
|
| 89 | - $actions_completed = 0; |
|
| 90 | - $unlimited = $batches === 0; |
|
| 91 | - |
|
| 92 | - try { |
|
| 93 | - // Custom queue cleaner instance. |
|
| 94 | - $cleaner = new ActionScheduler_QueueCleaner( null, $clean ); |
|
| 95 | - |
|
| 96 | - // Get the queue runner instance |
|
| 97 | - $runner = new ActionScheduler_WPCLI_QueueRunner( null, null, $cleaner ); |
|
| 98 | - |
|
| 99 | - // Determine how many tasks will be run in the first batch. |
|
| 100 | - $total = $runner->setup( $batch, $hooks, $group, $force ); |
|
| 101 | - |
|
| 102 | - // Run actions for as long as possible. |
|
| 103 | - while ( $total > 0 ) { |
|
| 104 | - $this->print_total_actions( $total ); |
|
| 105 | - $actions_completed += $runner->run(); |
|
| 106 | - $batches_completed++; |
|
| 107 | - |
|
| 108 | - // Maybe set up tasks for the next batch. |
|
| 109 | - $total = ( $unlimited || $batches_completed < $batches ) ? $runner->setup( $batch, $hooks, $group, $force ) : 0; |
|
| 110 | - } |
|
| 111 | - } catch ( Exception $e ) { |
|
| 112 | - $this->print_error( $e ); |
|
| 113 | - } |
|
| 114 | - |
|
| 115 | - $this->print_total_batches( $batches_completed ); |
|
| 116 | - $this->print_success( $actions_completed ); |
|
| 117 | - } |
|
| 118 | - |
|
| 119 | - /** |
|
| 120 | - * Print WP CLI message about how many actions are about to be processed. |
|
| 121 | - * |
|
| 122 | - * @author Jeremy Pry |
|
| 123 | - * |
|
| 124 | - * @param int $total |
|
| 125 | - */ |
|
| 126 | - protected function print_total_actions( $total ) { |
|
| 127 | - WP_CLI::log( |
|
| 128 | - sprintf( |
|
| 129 | - /* translators: %d refers to how many scheduled taks were found to run */ |
|
| 130 | - _n( 'Found %d scheduled task', 'Found %d scheduled tasks', $total, 'woocommerce' ), |
|
| 131 | - number_format_i18n( $total ) |
|
| 132 | - ) |
|
| 133 | - ); |
|
| 134 | - } |
|
| 135 | - |
|
| 136 | - /** |
|
| 137 | - * Print WP CLI message about how many batches of actions were processed. |
|
| 138 | - * |
|
| 139 | - * @author Jeremy Pry |
|
| 140 | - * |
|
| 141 | - * @param int $batches_completed |
|
| 142 | - */ |
|
| 143 | - protected function print_total_batches( $batches_completed ) { |
|
| 144 | - WP_CLI::log( |
|
| 145 | - sprintf( |
|
| 146 | - /* translators: %d refers to the total number of batches executed */ |
|
| 147 | - _n( '%d batch executed.', '%d batches executed.', $batches_completed, 'woocommerce' ), |
|
| 148 | - number_format_i18n( $batches_completed ) |
|
| 149 | - ) |
|
| 150 | - ); |
|
| 151 | - } |
|
| 152 | - |
|
| 153 | - /** |
|
| 154 | - * Convert an exception into a WP CLI error. |
|
| 155 | - * |
|
| 156 | - * @author Jeremy Pry |
|
| 157 | - * |
|
| 158 | - * @param Exception $e The error object. |
|
| 159 | - * |
|
| 160 | - * @throws \WP_CLI\ExitException |
|
| 161 | - */ |
|
| 162 | - protected function print_error( Exception $e ) { |
|
| 163 | - WP_CLI::error( |
|
| 164 | - sprintf( |
|
| 165 | - /* translators: %s refers to the exception error message */ |
|
| 166 | - __( 'There was an error running the action scheduler: %s', 'woocommerce' ), |
|
| 167 | - $e->getMessage() |
|
| 168 | - ) |
|
| 169 | - ); |
|
| 170 | - } |
|
| 171 | - |
|
| 172 | - /** |
|
| 173 | - * Print a success message with the number of completed actions. |
|
| 174 | - * |
|
| 175 | - * @author Jeremy Pry |
|
| 176 | - * |
|
| 177 | - * @param int $actions_completed |
|
| 178 | - */ |
|
| 179 | - protected function print_success( $actions_completed ) { |
|
| 180 | - WP_CLI::success( |
|
| 181 | - sprintf( |
|
| 182 | - /* translators: %d refers to the total number of taskes completed */ |
|
| 183 | - _n( '%d scheduled task completed.', '%d scheduled tasks completed.', $actions_completed, 'woocommerce' ), |
|
| 184 | - number_format_i18n( $actions_completed ) |
|
| 185 | - ) |
|
| 186 | - ); |
|
| 187 | - } |
|
| 8 | + /** |
|
| 9 | + * Force tables schema creation for Action Scheduler |
|
| 10 | + * |
|
| 11 | + * ## OPTIONS |
|
| 12 | + * |
|
| 13 | + * @param array $args Positional arguments. |
|
| 14 | + * @param array $assoc_args Keyed arguments. |
|
| 15 | + * |
|
| 16 | + * @subcommand fix-schema |
|
| 17 | + */ |
|
| 18 | + public function fix_schema( $args, $assoc_args ) { |
|
| 19 | + $schema_classes = array( ActionScheduler_LoggerSchema::class, ActionScheduler_StoreSchema::class ); |
|
| 20 | + |
|
| 21 | + foreach ( $schema_classes as $classname ) { |
|
| 22 | + if ( is_subclass_of( $classname, ActionScheduler_Abstract_Schema::class ) ) { |
|
| 23 | + $obj = new $classname(); |
|
| 24 | + $obj->init(); |
|
| 25 | + $obj->register_tables( true ); |
|
| 26 | + |
|
| 27 | + WP_CLI::success( |
|
| 28 | + sprintf( |
|
| 29 | + /* translators: %s refers to the schema name*/ |
|
| 30 | + __( 'Registered schema for %s', 'woocommerce' ), |
|
| 31 | + $classname |
|
| 32 | + ) |
|
| 33 | + ); |
|
| 34 | + } |
|
| 35 | + } |
|
| 36 | + } |
|
| 37 | + |
|
| 38 | + /** |
|
| 39 | + * Run the Action Scheduler |
|
| 40 | + * |
|
| 41 | + * ## OPTIONS |
|
| 42 | + * |
|
| 43 | + * [--batch-size=<size>] |
|
| 44 | + * : The maximum number of actions to run. Defaults to 100. |
|
| 45 | + * |
|
| 46 | + * [--batches=<size>] |
|
| 47 | + * : Limit execution to a number of batches. Defaults to 0, meaning batches will continue being executed until all actions are complete. |
|
| 48 | + * |
|
| 49 | + * [--cleanup-batch-size=<size>] |
|
| 50 | + * : The maximum number of actions to clean up. Defaults to the value of --batch-size. |
|
| 51 | + * |
|
| 52 | + * [--hooks=<hooks>] |
|
| 53 | + * : Only run actions with the specified hook. Omitting this option runs actions with any hook. Define multiple hooks as a comma separated string (without spaces), e.g. `--hooks=hook_one,hook_two,hook_three` |
|
| 54 | + * |
|
| 55 | + * [--group=<group>] |
|
| 56 | + * : Only run actions from the specified group. Omitting this option runs actions from all groups. |
|
| 57 | + * |
|
| 58 | + * [--free-memory-on=<count>] |
|
| 59 | + * : The number of actions to process between freeing memory. 0 disables freeing memory. Default 50. |
|
| 60 | + * |
|
| 61 | + * [--pause=<seconds>] |
|
| 62 | + * : The number of seconds to pause when freeing memory. Default no pause. |
|
| 63 | + * |
|
| 64 | + * [--force] |
|
| 65 | + * : Whether to force execution despite the maximum number of concurrent processes being exceeded. |
|
| 66 | + * |
|
| 67 | + * @param array $args Positional arguments. |
|
| 68 | + * @param array $assoc_args Keyed arguments. |
|
| 69 | + * @throws \WP_CLI\ExitException When an error occurs. |
|
| 70 | + * |
|
| 71 | + * @subcommand run |
|
| 72 | + */ |
|
| 73 | + public function run( $args, $assoc_args ) { |
|
| 74 | + // Handle passed arguments. |
|
| 75 | + $batch = absint( \WP_CLI\Utils\get_flag_value( $assoc_args, 'batch-size', 100 ) ); |
|
| 76 | + $batches = absint( \WP_CLI\Utils\get_flag_value( $assoc_args, 'batches', 0 ) ); |
|
| 77 | + $clean = absint( \WP_CLI\Utils\get_flag_value( $assoc_args, 'cleanup-batch-size', $batch ) ); |
|
| 78 | + $hooks = explode( ',', WP_CLI\Utils\get_flag_value( $assoc_args, 'hooks', '' ) ); |
|
| 79 | + $hooks = array_filter( array_map( 'trim', $hooks ) ); |
|
| 80 | + $group = \WP_CLI\Utils\get_flag_value( $assoc_args, 'group', '' ); |
|
| 81 | + $free_on = \WP_CLI\Utils\get_flag_value( $assoc_args, 'free-memory-on', 50 ); |
|
| 82 | + $sleep = \WP_CLI\Utils\get_flag_value( $assoc_args, 'pause', 0 ); |
|
| 83 | + $force = \WP_CLI\Utils\get_flag_value( $assoc_args, 'force', false ); |
|
| 84 | + |
|
| 85 | + ActionScheduler_DataController::set_free_ticks( $free_on ); |
|
| 86 | + ActionScheduler_DataController::set_sleep_time( $sleep ); |
|
| 87 | + |
|
| 88 | + $batches_completed = 0; |
|
| 89 | + $actions_completed = 0; |
|
| 90 | + $unlimited = $batches === 0; |
|
| 91 | + |
|
| 92 | + try { |
|
| 93 | + // Custom queue cleaner instance. |
|
| 94 | + $cleaner = new ActionScheduler_QueueCleaner( null, $clean ); |
|
| 95 | + |
|
| 96 | + // Get the queue runner instance |
|
| 97 | + $runner = new ActionScheduler_WPCLI_QueueRunner( null, null, $cleaner ); |
|
| 98 | + |
|
| 99 | + // Determine how many tasks will be run in the first batch. |
|
| 100 | + $total = $runner->setup( $batch, $hooks, $group, $force ); |
|
| 101 | + |
|
| 102 | + // Run actions for as long as possible. |
|
| 103 | + while ( $total > 0 ) { |
|
| 104 | + $this->print_total_actions( $total ); |
|
| 105 | + $actions_completed += $runner->run(); |
|
| 106 | + $batches_completed++; |
|
| 107 | + |
|
| 108 | + // Maybe set up tasks for the next batch. |
|
| 109 | + $total = ( $unlimited || $batches_completed < $batches ) ? $runner->setup( $batch, $hooks, $group, $force ) : 0; |
|
| 110 | + } |
|
| 111 | + } catch ( Exception $e ) { |
|
| 112 | + $this->print_error( $e ); |
|
| 113 | + } |
|
| 114 | + |
|
| 115 | + $this->print_total_batches( $batches_completed ); |
|
| 116 | + $this->print_success( $actions_completed ); |
|
| 117 | + } |
|
| 118 | + |
|
| 119 | + /** |
|
| 120 | + * Print WP CLI message about how many actions are about to be processed. |
|
| 121 | + * |
|
| 122 | + * @author Jeremy Pry |
|
| 123 | + * |
|
| 124 | + * @param int $total |
|
| 125 | + */ |
|
| 126 | + protected function print_total_actions( $total ) { |
|
| 127 | + WP_CLI::log( |
|
| 128 | + sprintf( |
|
| 129 | + /* translators: %d refers to how many scheduled taks were found to run */ |
|
| 130 | + _n( 'Found %d scheduled task', 'Found %d scheduled tasks', $total, 'woocommerce' ), |
|
| 131 | + number_format_i18n( $total ) |
|
| 132 | + ) |
|
| 133 | + ); |
|
| 134 | + } |
|
| 135 | + |
|
| 136 | + /** |
|
| 137 | + * Print WP CLI message about how many batches of actions were processed. |
|
| 138 | + * |
|
| 139 | + * @author Jeremy Pry |
|
| 140 | + * |
|
| 141 | + * @param int $batches_completed |
|
| 142 | + */ |
|
| 143 | + protected function print_total_batches( $batches_completed ) { |
|
| 144 | + WP_CLI::log( |
|
| 145 | + sprintf( |
|
| 146 | + /* translators: %d refers to the total number of batches executed */ |
|
| 147 | + _n( '%d batch executed.', '%d batches executed.', $batches_completed, 'woocommerce' ), |
|
| 148 | + number_format_i18n( $batches_completed ) |
|
| 149 | + ) |
|
| 150 | + ); |
|
| 151 | + } |
|
| 152 | + |
|
| 153 | + /** |
|
| 154 | + * Convert an exception into a WP CLI error. |
|
| 155 | + * |
|
| 156 | + * @author Jeremy Pry |
|
| 157 | + * |
|
| 158 | + * @param Exception $e The error object. |
|
| 159 | + * |
|
| 160 | + * @throws \WP_CLI\ExitException |
|
| 161 | + */ |
|
| 162 | + protected function print_error( Exception $e ) { |
|
| 163 | + WP_CLI::error( |
|
| 164 | + sprintf( |
|
| 165 | + /* translators: %s refers to the exception error message */ |
|
| 166 | + __( 'There was an error running the action scheduler: %s', 'woocommerce' ), |
|
| 167 | + $e->getMessage() |
|
| 168 | + ) |
|
| 169 | + ); |
|
| 170 | + } |
|
| 171 | + |
|
| 172 | + /** |
|
| 173 | + * Print a success message with the number of completed actions. |
|
| 174 | + * |
|
| 175 | + * @author Jeremy Pry |
|
| 176 | + * |
|
| 177 | + * @param int $actions_completed |
|
| 178 | + */ |
|
| 179 | + protected function print_success( $actions_completed ) { |
|
| 180 | + WP_CLI::success( |
|
| 181 | + sprintf( |
|
| 182 | + /* translators: %d refers to the total number of taskes completed */ |
|
| 183 | + _n( '%d scheduled task completed.', '%d scheduled tasks completed.', $actions_completed, 'woocommerce' ), |
|
| 184 | + number_format_i18n( $actions_completed ) |
|
| 185 | + ) |
|
| 186 | + ); |
|
| 187 | + } |
|
| 188 | 188 | } |
@@ -17,103 +17,103 @@ |
||
| 17 | 17 | */ |
| 18 | 18 | class ProgressBar { |
| 19 | 19 | |
| 20 | - /** @var integer */ |
|
| 21 | - protected $total_ticks; |
|
| 22 | - |
|
| 23 | - /** @var integer */ |
|
| 24 | - protected $count; |
|
| 25 | - |
|
| 26 | - /** @var integer */ |
|
| 27 | - protected $interval; |
|
| 28 | - |
|
| 29 | - /** @var string */ |
|
| 30 | - protected $message; |
|
| 31 | - |
|
| 32 | - /** @var \cli\progress\Bar */ |
|
| 33 | - protected $progress_bar; |
|
| 34 | - |
|
| 35 | - /** |
|
| 36 | - * ProgressBar constructor. |
|
| 37 | - * |
|
| 38 | - * @param string $message Text to display before the progress bar. |
|
| 39 | - * @param integer $count Total number of ticks to be performed. |
|
| 40 | - * @param integer $interval Optional. The interval in milliseconds between updates. Default 100. |
|
| 41 | - * |
|
| 42 | - * @throws Exception When this is not run within WP CLI |
|
| 43 | - */ |
|
| 44 | - public function __construct( $message, $count, $interval = 100 ) { |
|
| 45 | - if ( ! ( defined( 'WP_CLI' ) && WP_CLI ) ) { |
|
| 46 | - /* translators: %s php class name */ |
|
| 47 | - throw new \Exception( sprintf( __( 'The %s class can only be run within WP CLI.', 'woocommerce' ), __CLASS__ ) ); |
|
| 48 | - } |
|
| 49 | - |
|
| 50 | - $this->total_ticks = 0; |
|
| 51 | - $this->message = $message; |
|
| 52 | - $this->count = $count; |
|
| 53 | - $this->interval = $interval; |
|
| 54 | - } |
|
| 55 | - |
|
| 56 | - /** |
|
| 57 | - * Increment the progress bar ticks. |
|
| 58 | - */ |
|
| 59 | - public function tick() { |
|
| 60 | - if ( null === $this->progress_bar ) { |
|
| 61 | - $this->setup_progress_bar(); |
|
| 62 | - } |
|
| 63 | - |
|
| 64 | - $this->progress_bar->tick(); |
|
| 65 | - $this->total_ticks++; |
|
| 66 | - |
|
| 67 | - do_action( 'action_scheduler/progress_tick', $this->total_ticks ); |
|
| 68 | - } |
|
| 69 | - |
|
| 70 | - /** |
|
| 71 | - * Get the progress bar tick count. |
|
| 72 | - * |
|
| 73 | - * @return int |
|
| 74 | - */ |
|
| 75 | - public function current() { |
|
| 76 | - return $this->progress_bar ? $this->progress_bar->current() : 0; |
|
| 77 | - } |
|
| 78 | - |
|
| 79 | - /** |
|
| 80 | - * Finish the current progress bar. |
|
| 81 | - */ |
|
| 82 | - public function finish() { |
|
| 83 | - if ( null !== $this->progress_bar ) { |
|
| 84 | - $this->progress_bar->finish(); |
|
| 85 | - } |
|
| 86 | - |
|
| 87 | - $this->progress_bar = null; |
|
| 88 | - } |
|
| 89 | - |
|
| 90 | - /** |
|
| 91 | - * Set the message used when creating the progress bar. |
|
| 92 | - * |
|
| 93 | - * @param string $message The message to be used when the next progress bar is created. |
|
| 94 | - */ |
|
| 95 | - public function set_message( $message ) { |
|
| 96 | - $this->message = $message; |
|
| 97 | - } |
|
| 98 | - |
|
| 99 | - /** |
|
| 100 | - * Set the count for a new progress bar. |
|
| 101 | - * |
|
| 102 | - * @param integer $count The total number of ticks expected to complete. |
|
| 103 | - */ |
|
| 104 | - public function set_count( $count ) { |
|
| 105 | - $this->count = $count; |
|
| 106 | - $this->finish(); |
|
| 107 | - } |
|
| 108 | - |
|
| 109 | - /** |
|
| 110 | - * Set up the progress bar. |
|
| 111 | - */ |
|
| 112 | - protected function setup_progress_bar() { |
|
| 113 | - $this->progress_bar = \WP_CLI\Utils\make_progress_bar( |
|
| 114 | - $this->message, |
|
| 115 | - $this->count, |
|
| 116 | - $this->interval |
|
| 117 | - ); |
|
| 118 | - } |
|
| 20 | + /** @var integer */ |
|
| 21 | + protected $total_ticks; |
|
| 22 | + |
|
| 23 | + /** @var integer */ |
|
| 24 | + protected $count; |
|
| 25 | + |
|
| 26 | + /** @var integer */ |
|
| 27 | + protected $interval; |
|
| 28 | + |
|
| 29 | + /** @var string */ |
|
| 30 | + protected $message; |
|
| 31 | + |
|
| 32 | + /** @var \cli\progress\Bar */ |
|
| 33 | + protected $progress_bar; |
|
| 34 | + |
|
| 35 | + /** |
|
| 36 | + * ProgressBar constructor. |
|
| 37 | + * |
|
| 38 | + * @param string $message Text to display before the progress bar. |
|
| 39 | + * @param integer $count Total number of ticks to be performed. |
|
| 40 | + * @param integer $interval Optional. The interval in milliseconds between updates. Default 100. |
|
| 41 | + * |
|
| 42 | + * @throws Exception When this is not run within WP CLI |
|
| 43 | + */ |
|
| 44 | + public function __construct( $message, $count, $interval = 100 ) { |
|
| 45 | + if ( ! ( defined( 'WP_CLI' ) && WP_CLI ) ) { |
|
| 46 | + /* translators: %s php class name */ |
|
| 47 | + throw new \Exception( sprintf( __( 'The %s class can only be run within WP CLI.', 'woocommerce' ), __CLASS__ ) ); |
|
| 48 | + } |
|
| 49 | + |
|
| 50 | + $this->total_ticks = 0; |
|
| 51 | + $this->message = $message; |
|
| 52 | + $this->count = $count; |
|
| 53 | + $this->interval = $interval; |
|
| 54 | + } |
|
| 55 | + |
|
| 56 | + /** |
|
| 57 | + * Increment the progress bar ticks. |
|
| 58 | + */ |
|
| 59 | + public function tick() { |
|
| 60 | + if ( null === $this->progress_bar ) { |
|
| 61 | + $this->setup_progress_bar(); |
|
| 62 | + } |
|
| 63 | + |
|
| 64 | + $this->progress_bar->tick(); |
|
| 65 | + $this->total_ticks++; |
|
| 66 | + |
|
| 67 | + do_action( 'action_scheduler/progress_tick', $this->total_ticks ); |
|
| 68 | + } |
|
| 69 | + |
|
| 70 | + /** |
|
| 71 | + * Get the progress bar tick count. |
|
| 72 | + * |
|
| 73 | + * @return int |
|
| 74 | + */ |
|
| 75 | + public function current() { |
|
| 76 | + return $this->progress_bar ? $this->progress_bar->current() : 0; |
|
| 77 | + } |
|
| 78 | + |
|
| 79 | + /** |
|
| 80 | + * Finish the current progress bar. |
|
| 81 | + */ |
|
| 82 | + public function finish() { |
|
| 83 | + if ( null !== $this->progress_bar ) { |
|
| 84 | + $this->progress_bar->finish(); |
|
| 85 | + } |
|
| 86 | + |
|
| 87 | + $this->progress_bar = null; |
|
| 88 | + } |
|
| 89 | + |
|
| 90 | + /** |
|
| 91 | + * Set the message used when creating the progress bar. |
|
| 92 | + * |
|
| 93 | + * @param string $message The message to be used when the next progress bar is created. |
|
| 94 | + */ |
|
| 95 | + public function set_message( $message ) { |
|
| 96 | + $this->message = $message; |
|
| 97 | + } |
|
| 98 | + |
|
| 99 | + /** |
|
| 100 | + * Set the count for a new progress bar. |
|
| 101 | + * |
|
| 102 | + * @param integer $count The total number of ticks expected to complete. |
|
| 103 | + */ |
|
| 104 | + public function set_count( $count ) { |
|
| 105 | + $this->count = $count; |
|
| 106 | + $this->finish(); |
|
| 107 | + } |
|
| 108 | + |
|
| 109 | + /** |
|
| 110 | + * Set up the progress bar. |
|
| 111 | + */ |
|
| 112 | + protected function setup_progress_bar() { |
|
| 113 | + $this->progress_bar = \WP_CLI\Utils\make_progress_bar( |
|
| 114 | + $this->message, |
|
| 115 | + $this->count, |
|
| 116 | + $this->interval |
|
| 117 | + ); |
|
| 118 | + } |
|
| 119 | 119 | } |
@@ -21,128 +21,128 @@ |
||
| 21 | 21 | */ |
| 22 | 22 | class Migration_Command extends WP_CLI_Command { |
| 23 | 23 | |
| 24 | - /** @var int */ |
|
| 25 | - private $total_processed = 0; |
|
| 26 | - |
|
| 27 | - /** |
|
| 28 | - * Register the command with WP-CLI |
|
| 29 | - */ |
|
| 30 | - public function register() { |
|
| 31 | - if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) { |
|
| 32 | - return; |
|
| 33 | - } |
|
| 34 | - |
|
| 35 | - WP_CLI::add_command( 'action-scheduler migrate', [ $this, 'migrate' ], [ |
|
| 36 | - 'shortdesc' => 'Migrates actions to the DB tables store', |
|
| 37 | - 'synopsis' => [ |
|
| 38 | - [ |
|
| 39 | - 'type' => 'assoc', |
|
| 40 | - 'name' => 'batch-size', |
|
| 41 | - 'optional' => true, |
|
| 42 | - 'default' => 100, |
|
| 43 | - 'description' => 'The number of actions to process in each batch', |
|
| 44 | - ], |
|
| 45 | - [ |
|
| 46 | - 'type' => 'assoc', |
|
| 47 | - 'name' => 'free-memory-on', |
|
| 48 | - 'optional' => true, |
|
| 49 | - 'default' => 50, |
|
| 50 | - 'description' => 'The number of actions to process between freeing memory. 0 disables freeing memory', |
|
| 51 | - ], |
|
| 52 | - [ |
|
| 53 | - 'type' => 'assoc', |
|
| 54 | - 'name' => 'pause', |
|
| 55 | - 'optional' => true, |
|
| 56 | - 'default' => 0, |
|
| 57 | - 'description' => 'The number of seconds to pause when freeing memory', |
|
| 58 | - ], |
|
| 59 | - [ |
|
| 60 | - 'type' => 'flag', |
|
| 61 | - 'name' => 'dry-run', |
|
| 62 | - 'optional' => true, |
|
| 63 | - 'description' => 'Reports on the actions that would have been migrated, but does not change any data', |
|
| 64 | - ], |
|
| 65 | - ], |
|
| 66 | - ] ); |
|
| 67 | - } |
|
| 68 | - |
|
| 69 | - /** |
|
| 70 | - * Process the data migration. |
|
| 71 | - * |
|
| 72 | - * @param array $positional_args Required for WP CLI. Not used in migration. |
|
| 73 | - * @param array $assoc_args Optional arguments. |
|
| 74 | - * |
|
| 75 | - * @return void |
|
| 76 | - */ |
|
| 77 | - public function migrate( $positional_args, $assoc_args ) { |
|
| 78 | - $this->init_logging(); |
|
| 79 | - |
|
| 80 | - $config = $this->get_migration_config( $assoc_args ); |
|
| 81 | - $runner = new Runner( $config ); |
|
| 82 | - $runner->init_destination(); |
|
| 83 | - |
|
| 84 | - $batch_size = isset( $assoc_args[ 'batch-size' ] ) ? (int) $assoc_args[ 'batch-size' ] : 100; |
|
| 85 | - $free_on = isset( $assoc_args[ 'free-memory-on' ] ) ? (int) $assoc_args[ 'free-memory-on' ] : 50; |
|
| 86 | - $sleep = isset( $assoc_args[ 'pause' ] ) ? (int) $assoc_args[ 'pause' ] : 0; |
|
| 87 | - \ActionScheduler_DataController::set_free_ticks( $free_on ); |
|
| 88 | - \ActionScheduler_DataController::set_sleep_time( $sleep ); |
|
| 89 | - |
|
| 90 | - do { |
|
| 91 | - $actions_processed = $runner->run( $batch_size ); |
|
| 92 | - $this->total_processed += $actions_processed; |
|
| 93 | - } while ( $actions_processed > 0 ); |
|
| 94 | - |
|
| 95 | - if ( ! $config->get_dry_run() ) { |
|
| 96 | - // let the scheduler know that there's nothing left to do |
|
| 97 | - $scheduler = new Scheduler(); |
|
| 98 | - $scheduler->mark_complete(); |
|
| 99 | - } |
|
| 100 | - |
|
| 101 | - WP_CLI::success( sprintf( '%s complete. %d actions processed.', $config->get_dry_run() ? 'Dry run' : 'Migration', $this->total_processed ) ); |
|
| 102 | - } |
|
| 103 | - |
|
| 104 | - /** |
|
| 105 | - * Build the config object used to create the Runner |
|
| 106 | - * |
|
| 107 | - * @param array $args Optional arguments. |
|
| 108 | - * |
|
| 109 | - * @return ActionScheduler\Migration\Config |
|
| 110 | - */ |
|
| 111 | - private function get_migration_config( $args ) { |
|
| 112 | - $args = wp_parse_args( $args, [ |
|
| 113 | - 'dry-run' => false, |
|
| 114 | - ] ); |
|
| 115 | - |
|
| 116 | - $config = Controller::instance()->get_migration_config_object(); |
|
| 117 | - $config->set_dry_run( ! empty( $args[ 'dry-run' ] ) ); |
|
| 118 | - |
|
| 119 | - return $config; |
|
| 120 | - } |
|
| 121 | - |
|
| 122 | - /** |
|
| 123 | - * Hook command line logging into migration actions. |
|
| 124 | - */ |
|
| 125 | - private function init_logging() { |
|
| 126 | - add_action( 'action_scheduler/migrate_action_dry_run', function ( $action_id ) { |
|
| 127 | - WP_CLI::debug( sprintf( 'Dry-run: migrated action %d', $action_id ) ); |
|
| 128 | - }, 10, 1 ); |
|
| 129 | - add_action( 'action_scheduler/no_action_to_migrate', function ( $action_id ) { |
|
| 130 | - WP_CLI::debug( sprintf( 'No action found to migrate for ID %d', $action_id ) ); |
|
| 131 | - }, 10, 1 ); |
|
| 132 | - add_action( 'action_scheduler/migrate_action_failed', function ( $action_id ) { |
|
| 133 | - WP_CLI::warning( sprintf( 'Failed migrating action with ID %d', $action_id ) ); |
|
| 134 | - }, 10, 1 ); |
|
| 135 | - add_action( 'action_scheduler/migrate_action_incomplete', function ( $source_id, $destination_id ) { |
|
| 136 | - WP_CLI::warning( sprintf( 'Unable to remove source action with ID %d after migrating to new ID %d', $source_id, $destination_id ) ); |
|
| 137 | - }, 10, 2 ); |
|
| 138 | - add_action( 'action_scheduler/migrated_action', function ( $source_id, $destination_id ) { |
|
| 139 | - WP_CLI::debug( sprintf( 'Migrated source action with ID %d to new store with ID %d', $source_id, $destination_id ) ); |
|
| 140 | - }, 10, 2 ); |
|
| 141 | - add_action( 'action_scheduler/migration_batch_starting', function ( $batch ) { |
|
| 142 | - WP_CLI::debug( 'Beginning migration of batch: ' . print_r( $batch, true ) ); |
|
| 143 | - }, 10, 1 ); |
|
| 144 | - add_action( 'action_scheduler/migration_batch_complete', function ( $batch ) { |
|
| 145 | - WP_CLI::log( sprintf( 'Completed migration of %d actions', count( $batch ) ) ); |
|
| 146 | - }, 10, 1 ); |
|
| 147 | - } |
|
| 24 | + /** @var int */ |
|
| 25 | + private $total_processed = 0; |
|
| 26 | + |
|
| 27 | + /** |
|
| 28 | + * Register the command with WP-CLI |
|
| 29 | + */ |
|
| 30 | + public function register() { |
|
| 31 | + if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) { |
|
| 32 | + return; |
|
| 33 | + } |
|
| 34 | + |
|
| 35 | + WP_CLI::add_command( 'action-scheduler migrate', [ $this, 'migrate' ], [ |
|
| 36 | + 'shortdesc' => 'Migrates actions to the DB tables store', |
|
| 37 | + 'synopsis' => [ |
|
| 38 | + [ |
|
| 39 | + 'type' => 'assoc', |
|
| 40 | + 'name' => 'batch-size', |
|
| 41 | + 'optional' => true, |
|
| 42 | + 'default' => 100, |
|
| 43 | + 'description' => 'The number of actions to process in each batch', |
|
| 44 | + ], |
|
| 45 | + [ |
|
| 46 | + 'type' => 'assoc', |
|
| 47 | + 'name' => 'free-memory-on', |
|
| 48 | + 'optional' => true, |
|
| 49 | + 'default' => 50, |
|
| 50 | + 'description' => 'The number of actions to process between freeing memory. 0 disables freeing memory', |
|
| 51 | + ], |
|
| 52 | + [ |
|
| 53 | + 'type' => 'assoc', |
|
| 54 | + 'name' => 'pause', |
|
| 55 | + 'optional' => true, |
|
| 56 | + 'default' => 0, |
|
| 57 | + 'description' => 'The number of seconds to pause when freeing memory', |
|
| 58 | + ], |
|
| 59 | + [ |
|
| 60 | + 'type' => 'flag', |
|
| 61 | + 'name' => 'dry-run', |
|
| 62 | + 'optional' => true, |
|
| 63 | + 'description' => 'Reports on the actions that would have been migrated, but does not change any data', |
|
| 64 | + ], |
|
| 65 | + ], |
|
| 66 | + ] ); |
|
| 67 | + } |
|
| 68 | + |
|
| 69 | + /** |
|
| 70 | + * Process the data migration. |
|
| 71 | + * |
|
| 72 | + * @param array $positional_args Required for WP CLI. Not used in migration. |
|
| 73 | + * @param array $assoc_args Optional arguments. |
|
| 74 | + * |
|
| 75 | + * @return void |
|
| 76 | + */ |
|
| 77 | + public function migrate( $positional_args, $assoc_args ) { |
|
| 78 | + $this->init_logging(); |
|
| 79 | + |
|
| 80 | + $config = $this->get_migration_config( $assoc_args ); |
|
| 81 | + $runner = new Runner( $config ); |
|
| 82 | + $runner->init_destination(); |
|
| 83 | + |
|
| 84 | + $batch_size = isset( $assoc_args[ 'batch-size' ] ) ? (int) $assoc_args[ 'batch-size' ] : 100; |
|
| 85 | + $free_on = isset( $assoc_args[ 'free-memory-on' ] ) ? (int) $assoc_args[ 'free-memory-on' ] : 50; |
|
| 86 | + $sleep = isset( $assoc_args[ 'pause' ] ) ? (int) $assoc_args[ 'pause' ] : 0; |
|
| 87 | + \ActionScheduler_DataController::set_free_ticks( $free_on ); |
|
| 88 | + \ActionScheduler_DataController::set_sleep_time( $sleep ); |
|
| 89 | + |
|
| 90 | + do { |
|
| 91 | + $actions_processed = $runner->run( $batch_size ); |
|
| 92 | + $this->total_processed += $actions_processed; |
|
| 93 | + } while ( $actions_processed > 0 ); |
|
| 94 | + |
|
| 95 | + if ( ! $config->get_dry_run() ) { |
|
| 96 | + // let the scheduler know that there's nothing left to do |
|
| 97 | + $scheduler = new Scheduler(); |
|
| 98 | + $scheduler->mark_complete(); |
|
| 99 | + } |
|
| 100 | + |
|
| 101 | + WP_CLI::success( sprintf( '%s complete. %d actions processed.', $config->get_dry_run() ? 'Dry run' : 'Migration', $this->total_processed ) ); |
|
| 102 | + } |
|
| 103 | + |
|
| 104 | + /** |
|
| 105 | + * Build the config object used to create the Runner |
|
| 106 | + * |
|
| 107 | + * @param array $args Optional arguments. |
|
| 108 | + * |
|
| 109 | + * @return ActionScheduler\Migration\Config |
|
| 110 | + */ |
|
| 111 | + private function get_migration_config( $args ) { |
|
| 112 | + $args = wp_parse_args( $args, [ |
|
| 113 | + 'dry-run' => false, |
|
| 114 | + ] ); |
|
| 115 | + |
|
| 116 | + $config = Controller::instance()->get_migration_config_object(); |
|
| 117 | + $config->set_dry_run( ! empty( $args[ 'dry-run' ] ) ); |
|
| 118 | + |
|
| 119 | + return $config; |
|
| 120 | + } |
|
| 121 | + |
|
| 122 | + /** |
|
| 123 | + * Hook command line logging into migration actions. |
|
| 124 | + */ |
|
| 125 | + private function init_logging() { |
|
| 126 | + add_action( 'action_scheduler/migrate_action_dry_run', function ( $action_id ) { |
|
| 127 | + WP_CLI::debug( sprintf( 'Dry-run: migrated action %d', $action_id ) ); |
|
| 128 | + }, 10, 1 ); |
|
| 129 | + add_action( 'action_scheduler/no_action_to_migrate', function ( $action_id ) { |
|
| 130 | + WP_CLI::debug( sprintf( 'No action found to migrate for ID %d', $action_id ) ); |
|
| 131 | + }, 10, 1 ); |
|
| 132 | + add_action( 'action_scheduler/migrate_action_failed', function ( $action_id ) { |
|
| 133 | + WP_CLI::warning( sprintf( 'Failed migrating action with ID %d', $action_id ) ); |
|
| 134 | + }, 10, 1 ); |
|
| 135 | + add_action( 'action_scheduler/migrate_action_incomplete', function ( $source_id, $destination_id ) { |
|
| 136 | + WP_CLI::warning( sprintf( 'Unable to remove source action with ID %d after migrating to new ID %d', $source_id, $destination_id ) ); |
|
| 137 | + }, 10, 2 ); |
|
| 138 | + add_action( 'action_scheduler/migrated_action', function ( $source_id, $destination_id ) { |
|
| 139 | + WP_CLI::debug( sprintf( 'Migrated source action with ID %d to new store with ID %d', $source_id, $destination_id ) ); |
|
| 140 | + }, 10, 2 ); |
|
| 141 | + add_action( 'action_scheduler/migration_batch_starting', function ( $batch ) { |
|
| 142 | + WP_CLI::debug( 'Beginning migration of batch: ' . print_r( $batch, true ) ); |
|
| 143 | + }, 10, 1 ); |
|
| 144 | + add_action( 'action_scheduler/migration_batch_complete', function ( $batch ) { |
|
| 145 | + WP_CLI::log( sprintf( 'Completed migration of %d actions', count( $batch ) ) ); |
|
| 146 | + }, 10, 1 ); |
|
| 147 | + } |
|
| 148 | 148 | } |