Sid Gifari File Manager
🏠 Root
/
home
/
ailwtbdh
/
superstepsgroup.com
/
wp-content
/
plugins
/
all-in-one-seo-pack
/
app
/
Common
/
Utils
/
Editing: ActionScheduler.php
<?php namespace AIOSEO\Plugin\Common\Utils; // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Handles all Action Scheduler related tasks. * * @since 4.0.0 */ class ActionScheduler { /** * The Action Scheduler group. * * @since 4.1.5 * @version 4.2.7 * * @var string */ private $actionSchedulerGroup = 'aioseo'; /** * Class constructor. * * @since 4.0.0 */ public function __construct() { add_action( 'action_scheduler_after_execute', [ $this, 'cleanup' ], 1000, 2 ); // Note: \ActionScheduler is first loaded on `plugins_loaded` action hook. 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 4.2.7 * * @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 ( ! aioseo()->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 4.0.10 * * @param int $actionId The action ID processed. * @param \ActionScheduler_Action $action Class instance. * @return void */ public function cleanup( $actionId, $action = null ) { if ( // Bail if this isn't one of our actions or if we're in a dev environment. 'aioseo' !== $action->get_group() || ( defined( 'WP_ENVIRONMENT_TYPE' ) && 'development' === WP_ENVIRONMENT_TYPE ) || // Bail if the tables don't exist. ! aioseo()->core->db->tableExists( 'actionscheduler_actions' ) || ! aioseo()->core->db->tableExists( 'actionscheduler_groups' ) || // Bail if it hasn't been long enough since the last cleanup. aioseo()->core->cache->get( 'action_scheduler_log_cleanup' ) ) { return; } $prefix = aioseo()->core->db->db->prefix; // Clean up logs associated with entries in the actions table. aioseo()->core->db->execute( "DELETE al FROM {$prefix}actionscheduler_logs as al JOIN {$prefix}actionscheduler_actions as aa on `aa`.`action_id` = `al`.`action_id` LEFT 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')) OR (`aa`.`hook` LIKE 'aioseo_%' AND `aa`.`group_id` = 0 AND `aa`.`status` IN ('complete', 'failed', 'canceled')) );" ); // Clean up actions. aioseo()->core->db->execute( "DELETE aa FROM {$prefix}actionscheduler_actions as aa LEFT 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')) OR (`aa`.`hook` LIKE 'aioseo_%' AND `aa`.`group_id` = 0 AND `aa`.`status` IN ('complete', 'failed', 'canceled')) );" ); // Remove any duplicate pending actions, keeping only the earliest per hook+args combination. $this->deduplicatePendingActions( $prefix ); // Set a transient to prevent this from running again for a while. aioseo()->core->cache->update( 'action_scheduler_log_cleanup', true, DAY_IN_SECONDS ); } /** * Removes duplicate pending actions for the aioseo group, keeping only the earliest per hook+args. * * @since 4.9.5.2 * * @param string $prefix The database table prefix. * @return void */ private function deduplicatePendingActions( $prefix ) { aioseo()->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 = 'pending' AND aa.action_id NOT IN ( SELECT action_id FROM ( SELECT MIN(aa2.action_id) AS action_id FROM {$prefix}actionscheduler_actions AS aa2 JOIN {$prefix}actionscheduler_groups AS ag2 ON ag2.group_id = aa2.group_id WHERE ag2.slug = '{$this->actionSchedulerGroup}' AND aa2.status = 'pending' GROUP BY aa2.hook, aa2.args ) AS keepers );" ); } /** * Schedules a single action at a specific time in the future. * * @since 4.0.13 * @version 4.2.7 * * @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. * @param bool $forceSchedule Whether we should schedule a new action regardless of whether one is already set. * @return boolean Whether the action was scheduled. */ public function scheduleSingle( $actionName, $time = 0, $args = [], $forceSchedule = false ) { $lockKey = $this->getLockKey( $actionName, $args ); // Skip if another request is currently scheduling this action. if ( get_transient( $lockKey ) ) { return false; } // Set lock for 5 seconds. set_transient( $lockKey, 1, 5 ); try { if ( $forceSchedule || ! $this->isScheduled( $actionName, $args ) ) { as_schedule_single_action( time() + $time, $actionName, $args, $this->actionSchedulerGroup ); delete_transient( $lockKey ); return true; } } catch ( \RuntimeException $e ) { // Nothing needs to happen. } delete_transient( $lockKey ); return false; } /** * Checks if a given action is already scheduled. * * @since 4.0.13 * @version 4.2.7 * @version 4.9.4.2 Refactored to check all arguments. * @version 4.9.4.2 Use as_has_scheduled_action() for improved performance. * * @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 = [] ) { if ( ! function_exists( 'as_has_scheduled_action' ) ) { // In case site is loading older AS version. return as_next_scheduled_action( $actionName, $args, $this->actionSchedulerGroup ); } // Use Action Scheduler's optimized existence check. // as_has_scheduled_action() was introduced in Action Scheduler 3.3.0. return as_has_scheduled_action( $actionName, $args, $this->actionSchedulerGroup ); } /** * Unschedule all pending instances of an action. * * Uses as_unschedule_all_actions() to ensure recurring actions are fully stopped, * since as_unschedule_action() only cancels the next occurrence. * * @since 4.1.4 * @version 4.2.7 * @version 4.9.4.2 Use as_unschedule_all_actions() to properly stop recurring actions. * * @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 { as_unschedule_all_actions( $actionName, $args, $this->actionSchedulerGroup ); } catch ( \Exception $e ) { // Do nothing. } } /** * Schedules a recurring action. * * @since 4.1.5 * @version 4.2.7 * * @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 = [] ) { $lockKey = $this->getLockKey( $actionName, $args ); // Skip if another request is currently scheduling this action. if ( get_transient( $lockKey ) ) { return false; } // Set lock for 5 seconds. set_transient( $lockKey, 1, 5 ); try { if ( ! $this->isScheduled( $actionName, $args ) ) { as_schedule_recurring_action( time() + $time, $interval, $actionName, $args, $this->actionSchedulerGroup ); delete_transient( $lockKey ); return true; } } catch ( \RuntimeException $e ) { // Nothing needs to happen. } delete_transient( $lockKey ); return false; } /** * Schedule a single async action. * * @since 4.1.6 * @version 4.9.4.2 Added check for duplicates. * * @param string $actionName The name of the action. * @param array $args Any relevant arguments. * @return void */ public function scheduleAsync( $actionName, $args = [] ) { $lockKey = $this->getLockKey( $actionName, $args ); // Skip if another request is currently scheduling this action. if ( get_transient( $lockKey ) ) { return; } // Set lock for 5 seconds. set_transient( $lockKey, 1, 5 ); try { // Only schedule if not already scheduled to prevent duplicate actions. if ( ! $this->isScheduled( $actionName, $args ) ) { // Run the task immediately using an async action. as_enqueue_async_action( $actionName, $args, $this->actionSchedulerGroup ); } } catch ( \Exception $e ) { // Do nothing. } delete_transient( $lockKey ); } /** * Returns a transient lock key for the given action name and args. * * @since 4.9.4.2 * * @param string $actionName The action name. * @param array $args The action arguments. * @return string The lock key. */ private function getLockKey( $actionName, $args = [] ) { return 'aioseo_as_lock_' . md5( $actionName . wp_json_encode( $args ) ); } }
Save
Cancel