310 lines
8.6 KiB
PHP
310 lines
8.6 KiB
PHP
<?php
|
|
namespace AIOSEO\BrokenLinkChecker\Utils;
|
|
|
|
// Exit if accessed directly.
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* This class makes sure the Action Scheduler tables always exist.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
class ActionScheduler {
|
|
/**
|
|
* The Action Scheduler group.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @var string
|
|
*/
|
|
private $actionSchedulerGroup = 'aioseo_blc';
|
|
|
|
/**
|
|
* Class constructor.
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public function __construct() { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
|
add_action( 'action_scheduler_after_execute', [ $this, 'cleanup' ], 1000, 2 );
|
|
add_action( 'plugins_loaded', [ $this, 'maybeRecreateTables' ] );
|
|
}
|
|
|
|
/**
|
|
* Maybe register the `{$table_prefix}_actionscheduler_{$suffix}` tables with WordPress and create them if needed.
|
|
* Hooked into `plugins_loaded` action hook.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @return void
|
|
*/
|
|
public function maybeRecreateTables() {
|
|
if ( ! is_admin() ) {
|
|
return;
|
|
}
|
|
|
|
if ( ! apply_filters( 'action_scheduler_enable_recreate_data_store', true ) ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
|
|
return;
|
|
}
|
|
|
|
if (
|
|
! class_exists( 'ActionScheduler' ) ||
|
|
! class_exists( 'ActionScheduler_HybridStore' ) ||
|
|
! class_exists( 'ActionScheduler_StoreSchema' ) ||
|
|
! class_exists( 'ActionScheduler_LoggerSchema' )
|
|
) {
|
|
return;
|
|
}
|
|
|
|
$store = \ActionScheduler::store();
|
|
|
|
if ( ! is_a( $store, 'ActionScheduler_HybridStore' ) ) {
|
|
$store = new \ActionScheduler_HybridStore();
|
|
}
|
|
|
|
$tableList = [
|
|
'actionscheduler_actions',
|
|
'actionscheduler_logs',
|
|
'actionscheduler_groups',
|
|
'actionscheduler_claims',
|
|
];
|
|
|
|
foreach ( $tableList as $tableName ) {
|
|
if ( ! aioseoBrokenLinkChecker()->core->db->tableExists( $tableName ) ) {
|
|
add_action( 'action_scheduler/created_table', [ $store, 'set_autoincrement' ], 10, 2 );
|
|
|
|
$storeSchema = new \ActionScheduler_StoreSchema();
|
|
$loggerSchema = new \ActionScheduler_LoggerSchema();
|
|
$storeSchema->register_tables( true );
|
|
$loggerSchema->register_tables( true );
|
|
|
|
remove_action( 'action_scheduler/created_table', [ $store, 'set_autoincrement' ] );
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cleans up the Action Scheduler tables after one of our actions completes.
|
|
* Hooked into `action_scheduler_after_execute` action hook.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param int $actionId The action ID processed.
|
|
* @param \ActionScheduler_Action $action Class instance.
|
|
* @return void
|
|
*/
|
|
public function cleanup( $actionId, $action ) {
|
|
if (
|
|
// Bail if this isn't one of our actions or if we're in a dev environment.
|
|
$this->actionSchedulerGroup !== $action->get_group() ||
|
|
defined( 'AIOSEO_BROKEN_LINK_CHECKER_DEV_VERSION' ) ||
|
|
// Bail if the tables don't exist.
|
|
! aioseoBrokenLinkChecker()->core->db->tableExists( 'actionscheduler_actions' ) ||
|
|
! aioseoBrokenLinkChecker()->core->db->tableExists( 'actionscheduler_groups' )
|
|
) {
|
|
return;
|
|
}
|
|
|
|
$prefix = aioseoBrokenLinkChecker()->core->db->db->prefix;
|
|
|
|
// Clean up logs associated with entries in the actions table.
|
|
aioseoBrokenLinkChecker()->core->db->execute(
|
|
"DELETE al FROM {$prefix}actionscheduler_logs as al
|
|
JOIN {$prefix}actionscheduler_actions as aa on `aa`.`action_id` = `al`.`action_id`
|
|
JOIN {$prefix}actionscheduler_groups as ag on `ag`.`group_id` = `aa`.`group_id`
|
|
WHERE `ag`.`slug` = '{$this->actionSchedulerGroup}'
|
|
AND `aa`.`status` IN ('complete', 'failed', 'canceled');"
|
|
);
|
|
|
|
// Clean up actions.
|
|
aioseoBrokenLinkChecker()->core->db->execute(
|
|
"DELETE aa FROM {$prefix}actionscheduler_actions as aa
|
|
JOIN {$prefix}actionscheduler_groups as ag on `ag`.`group_id` = `aa`.`group_id`
|
|
WHERE `ag`.`slug` = '{$this->actionSchedulerGroup}'
|
|
AND `aa`.`status` IN ('complete', 'failed', 'canceled');"
|
|
);
|
|
|
|
// Clean up logs where there was no group.
|
|
aioseoBrokenLinkChecker()->core->db->execute(
|
|
"DELETE al FROM {$prefix}actionscheduler_logs as al
|
|
JOIN {$prefix}actionscheduler_actions as aa on `aa`.`action_id` = `al`.`action_id`
|
|
WHERE `aa`.`hook` LIKE '{$this->actionSchedulerGroup}_%'
|
|
AND `aa`.`group_id` = 0
|
|
AND `aa`.`status` IN ('complete', 'failed', 'canceled');"
|
|
);
|
|
|
|
// Clean up actions that start with aioseo_ and have no group.
|
|
aioseoBrokenLinkChecker()->core->db->execute(
|
|
"DELETE aa FROM {$prefix}actionscheduler_actions as aa
|
|
WHERE `aa`.`hook` LIKE '{$this->actionSchedulerGroup}_%'
|
|
AND `aa`.`group_id` = 0
|
|
AND `aa`.`status` IN ('complete', 'failed', 'canceled');"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Schedules a single action at a specific time in the future.
|
|
* @NOTE: This method differs from the one in the main plugin!
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $actionName The action name.
|
|
* @param int $time The time to add to the current time.
|
|
* @param array $args Args passed down to the action.
|
|
* @return boolean Whether the action was scheduled.
|
|
*/
|
|
public function scheduleSingle( $actionName, $time, $args = [] ) {
|
|
try {
|
|
if ( empty( $this->getPendingActions( $actionName, $args ) ) ) {
|
|
\as_schedule_single_action( time() + $time, $actionName, $args, $this->actionSchedulerGroup );
|
|
|
|
return true;
|
|
}
|
|
} catch ( \RuntimeException $e ) {
|
|
// Nothing needs to happen.
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Checks if a given action is already scheduled.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $actionName The action name.
|
|
* @param array $args Args passed down to the action.
|
|
* @return boolean Whether the action is already scheduled.
|
|
*/
|
|
public function isScheduled( $actionName, $args = [] ) {
|
|
$actions = array_merge(
|
|
$this->getRunningActions( $actionName, $args ),
|
|
$this->getPendingActions( $actionName, $args )
|
|
);
|
|
|
|
return ! empty( $actions );
|
|
}
|
|
|
|
/**
|
|
* Returns the running actions for a given action.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $actionName The action name.
|
|
* @param array $args Args passed down to the action.
|
|
* @return array The actions.
|
|
*/
|
|
public function getRunningActions( $actionName, $args = [] ) {
|
|
if ( ! class_exists( 'ActionScheduler_Store' ) ) {
|
|
return [];
|
|
}
|
|
|
|
$runningArgs = [
|
|
'hook' => $actionName,
|
|
'status' => \ActionScheduler_Store::STATUS_RUNNING,
|
|
'per_page' => 1
|
|
];
|
|
|
|
if ( empty( $args ) ) {
|
|
$runningArgs['args'] = $args;
|
|
}
|
|
|
|
$actions = as_get_scheduled_actions( $runningArgs );
|
|
|
|
return $actions;
|
|
}
|
|
|
|
/**
|
|
* Returns the pending actions for a given action.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $actionName The action name.
|
|
* @param array $args Args passed down to the action.
|
|
* @return array The actions.
|
|
*/
|
|
public function getPendingActions( $actionName, $args = [] ) {
|
|
if ( ! class_exists( 'ActionScheduler_Store' ) ) {
|
|
return [];
|
|
}
|
|
|
|
$pendingArgs = [
|
|
'hook' => $actionName,
|
|
'status' => \ActionScheduler_Store::STATUS_PENDING,
|
|
'per_page' => 1
|
|
];
|
|
|
|
if ( empty( $args ) ) {
|
|
$pendingArgs['args'] = $args;
|
|
}
|
|
|
|
$actions = as_get_scheduled_actions( $pendingArgs );
|
|
|
|
return $actions;
|
|
}
|
|
|
|
/**
|
|
* Unschedule an action.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $actionName The action name to unschedule.
|
|
* @param array $args Args passed down to the action.
|
|
* @return void
|
|
*/
|
|
public function unschedule( $actionName, $args = [] ) {
|
|
try {
|
|
if ( as_next_scheduled_action( $actionName ) ) {
|
|
as_unschedule_action( $actionName, $args, $this->actionSchedulerGroup );
|
|
}
|
|
} catch ( \Exception $e ) {
|
|
// Do nothing.
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Schedules a recurring action.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $actionName The action name.
|
|
* @param int $time The seconds to add to the current time.
|
|
* @param int $interval The interval in seconds.
|
|
* @param array $args Args passed down to the action.
|
|
* @return boolean Whether the action was scheduled.
|
|
*/
|
|
public function scheduleRecurrent( $actionName, $time, $interval = 60, $args = [] ) {
|
|
try {
|
|
if ( ! $this->isScheduled( $actionName ) ) {
|
|
as_schedule_recurring_action( time() + $time, $interval, $actionName, $args, $this->actionSchedulerGroup );
|
|
|
|
return true;
|
|
}
|
|
} catch ( \RuntimeException $e ) {
|
|
// Nothing needs to happen.
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Schedule a single async action.
|
|
*
|
|
* @since 1.0.0
|
|
*
|
|
* @param string $actionName The name of the action.
|
|
* @param array $args Any relevant arguments.
|
|
* @return void
|
|
*/
|
|
public function scheduleAsync( $actionName, $args = [] ) {
|
|
try {
|
|
// Run the task immediately using an async action.
|
|
as_enqueue_async_action( $actionName, $args, $this->actionSchedulerGroup );
|
|
} catch ( \Exception $e ) {
|
|
// Do nothing.
|
|
}
|
|
}
|
|
} |