Passed
Pull Request — master (#281)
by Kiran
04:07
created
includes/libraries/action-scheduler/classes/migration/LogMigrator.php 1 patch
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -15,35 +15,35 @@
 block discarded – undo
15 15
  * @codeCoverageIgnore
16 16
  */
17 17
 class LogMigrator {
18
-	/** @var ActionScheduler_Logger */
19
-	private $source;
18
+    /** @var ActionScheduler_Logger */
19
+    private $source;
20 20
 
21
-	/** @var ActionScheduler_Logger */
22
-	private $destination;
21
+    /** @var ActionScheduler_Logger */
22
+    private $destination;
23 23
 
24
-	/**
25
-	 * ActionMigrator constructor.
26
-	 *
27
-	 * @param ActionScheduler_Logger $source_logger Source logger object.
28
-	 * @param ActionScheduler_Logger $destination_Logger Destination logger object.
29
-	 */
30
-	public function __construct( ActionScheduler_Logger $source_logger, ActionScheduler_Logger $destination_Logger ) {
31
-		$this->source      = $source_logger;
32
-		$this->destination = $destination_Logger;
33
-	}
24
+    /**
25
+     * ActionMigrator constructor.
26
+     *
27
+     * @param ActionScheduler_Logger $source_logger Source logger object.
28
+     * @param ActionScheduler_Logger $destination_Logger Destination logger object.
29
+     */
30
+    public function __construct( ActionScheduler_Logger $source_logger, ActionScheduler_Logger $destination_Logger ) {
31
+        $this->source      = $source_logger;
32
+        $this->destination = $destination_Logger;
33
+    }
34 34
 
35
-	/**
36
-	 * Migrate an action log.
37
-	 *
38
-	 * @param int $source_action_id Source logger object.
39
-	 * @param int $destination_action_id Destination logger object.
40
-	 */
41
-	public function migrate( $source_action_id, $destination_action_id ) {
42
-		$logs = $this->source->get_logs( $source_action_id );
43
-		foreach ( $logs as $log ) {
44
-			if ( $log->get_action_id() == $source_action_id ) {
45
-				$this->destination->log( $destination_action_id, $log->get_message(), $log->get_date() );
46
-			}
47
-		}
48
-	}
35
+    /**
36
+     * Migrate an action log.
37
+     *
38
+     * @param int $source_action_id Source logger object.
39
+     * @param int $destination_action_id Destination logger object.
40
+     */
41
+    public function migrate( $source_action_id, $destination_action_id ) {
42
+        $logs = $this->source->get_logs( $source_action_id );
43
+        foreach ( $logs as $log ) {
44
+            if ( $log->get_action_id() == $source_action_id ) {
45
+                $this->destination->log( $destination_action_id, $log->get_message(), $log->get_date() );
46
+            }
47
+        }
48
+    }
49 49
 }
Please login to merge, or discard this patch.
includes/libraries/action-scheduler/classes/migration/Scheduler.php 1 patch
Indentation   +111 added lines, -111 removed lines patch added patch discarded remove patch
@@ -13,116 +13,116 @@
 block discarded – undo
13 13
  * @codeCoverageIgnore
14 14
  */
15 15
 class Scheduler {
16
-	/** Migration action hook. */
17
-	const HOOK            = 'action_scheduler/migration_hook';
18
-
19
-	/** Migration action group. */
20
-	const GROUP           = 'action-scheduler-migration';
21
-
22
-	/**
23
-	 * Set up the callback for the scheduled job.
24
-	 */
25
-	public function hook() {
26
-		add_action( self::HOOK, array( $this, 'run_migration' ), 10, 0 );
27
-	}
28
-
29
-	/**
30
-	 * Remove the callback for the scheduled job.
31
-	 */
32
-	public function unhook() {
33
-		remove_action( self::HOOK, array( $this, 'run_migration' ), 10 );
34
-	}
35
-
36
-	/**
37
-	 * The migration callback.
38
-	 */
39
-	public function run_migration() {
40
-		$migration_runner = $this->get_migration_runner();
41
-		$count            = $migration_runner->run( $this->get_batch_size() );
42
-
43
-		if ( $count === 0 ) {
44
-			$this->mark_complete();
45
-		} else {
46
-			$this->schedule_migration( time() + $this->get_schedule_interval() );
47
-		}
48
-	}
49
-
50
-	/**
51
-	 * Mark the migration complete.
52
-	 */
53
-	public function mark_complete() {
54
-		$this->unschedule_migration();
55
-
56
-		\ActionScheduler_DataController::mark_migration_complete();
57
-		do_action( 'action_scheduler/migration_complete' );
58
-	}
59
-
60
-	/**
61
-	 * Get a flag indicating whether the migration is scheduled.
62
-	 *
63
-	 * @return bool Whether there is a pending action in the store to handle the migration
64
-	 */
65
-	public function is_migration_scheduled() {
66
-		$next = as_next_scheduled_action( self::HOOK );
67
-
68
-		return ! empty( $next );
69
-	}
70
-
71
-	/**
72
-	 * Schedule the migration.
73
-	 *
74
-	 * @param int $when Optional timestamp to run the next migration batch. Defaults to now.
75
-	 *
76
-	 * @return string The action ID
77
-	 */
78
-	public function schedule_migration( $when = 0 ) {
79
-		$next = as_next_scheduled_action( self::HOOK );
80
-
81
-		if ( ! empty( $next ) ) {
82
-			return $next;
83
-		}
84
-
85
-		if ( empty( $when ) ) {
86
-			$when = time();
87
-		}
88
-
89
-		return as_schedule_single_action( $when, self::HOOK, array(), self::GROUP );
90
-	}
91
-
92
-	/**
93
-	 * Remove the scheduled migration action.
94
-	 */
95
-	public function unschedule_migration() {
96
-		as_unschedule_action( self::HOOK, null, self::GROUP );
97
-	}
98
-
99
-	/**
100
-	 * Get migration batch schedule interval.
101
-	 *
102
-	 * @return int Seconds between migration runs. Defaults to 0 seconds to allow chaining migration via Async Runners.
103
-	 */
104
-	private function get_schedule_interval() {
105
-		return (int) apply_filters( 'action_scheduler/migration_interval', 0 );
106
-	}
107
-
108
-	/**
109
-	 * Get migration batch size.
110
-	 *
111
-	 * @return int Number of actions to migrate in each batch. Defaults to 250.
112
-	 */
113
-	private function get_batch_size() {
114
-		return (int) apply_filters( 'action_scheduler/migration_batch_size', 250 );
115
-	}
116
-
117
-	/**
118
-	 * Get migration runner object.
119
-	 *
120
-	 * @return Runner
121
-	 */
122
-	private function get_migration_runner() {
123
-		$config = Controller::instance()->get_migration_config_object();
124
-
125
-		return new Runner( $config );
126
-	}
16
+    /** Migration action hook. */
17
+    const HOOK            = 'action_scheduler/migration_hook';
18
+
19
+    /** Migration action group. */
20
+    const GROUP           = 'action-scheduler-migration';
21
+
22
+    /**
23
+     * Set up the callback for the scheduled job.
24
+     */
25
+    public function hook() {
26
+        add_action( self::HOOK, array( $this, 'run_migration' ), 10, 0 );
27
+    }
28
+
29
+    /**
30
+     * Remove the callback for the scheduled job.
31
+     */
32
+    public function unhook() {
33
+        remove_action( self::HOOK, array( $this, 'run_migration' ), 10 );
34
+    }
35
+
36
+    /**
37
+     * The migration callback.
38
+     */
39
+    public function run_migration() {
40
+        $migration_runner = $this->get_migration_runner();
41
+        $count            = $migration_runner->run( $this->get_batch_size() );
42
+
43
+        if ( $count === 0 ) {
44
+            $this->mark_complete();
45
+        } else {
46
+            $this->schedule_migration( time() + $this->get_schedule_interval() );
47
+        }
48
+    }
49
+
50
+    /**
51
+     * Mark the migration complete.
52
+     */
53
+    public function mark_complete() {
54
+        $this->unschedule_migration();
55
+
56
+        \ActionScheduler_DataController::mark_migration_complete();
57
+        do_action( 'action_scheduler/migration_complete' );
58
+    }
59
+
60
+    /**
61
+     * Get a flag indicating whether the migration is scheduled.
62
+     *
63
+     * @return bool Whether there is a pending action in the store to handle the migration
64
+     */
65
+    public function is_migration_scheduled() {
66
+        $next = as_next_scheduled_action( self::HOOK );
67
+
68
+        return ! empty( $next );
69
+    }
70
+
71
+    /**
72
+     * Schedule the migration.
73
+     *
74
+     * @param int $when Optional timestamp to run the next migration batch. Defaults to now.
75
+     *
76
+     * @return string The action ID
77
+     */
78
+    public function schedule_migration( $when = 0 ) {
79
+        $next = as_next_scheduled_action( self::HOOK );
80
+
81
+        if ( ! empty( $next ) ) {
82
+            return $next;
83
+        }
84
+
85
+        if ( empty( $when ) ) {
86
+            $when = time();
87
+        }
88
+
89
+        return as_schedule_single_action( $when, self::HOOK, array(), self::GROUP );
90
+    }
91
+
92
+    /**
93
+     * Remove the scheduled migration action.
94
+     */
95
+    public function unschedule_migration() {
96
+        as_unschedule_action( self::HOOK, null, self::GROUP );
97
+    }
98
+
99
+    /**
100
+     * Get migration batch schedule interval.
101
+     *
102
+     * @return int Seconds between migration runs. Defaults to 0 seconds to allow chaining migration via Async Runners.
103
+     */
104
+    private function get_schedule_interval() {
105
+        return (int) apply_filters( 'action_scheduler/migration_interval', 0 );
106
+    }
107
+
108
+    /**
109
+     * Get migration batch size.
110
+     *
111
+     * @return int Number of actions to migrate in each batch. Defaults to 250.
112
+     */
113
+    private function get_batch_size() {
114
+        return (int) apply_filters( 'action_scheduler/migration_batch_size', 250 );
115
+    }
116
+
117
+    /**
118
+     * Get migration runner object.
119
+     *
120
+     * @return Runner
121
+     */
122
+    private function get_migration_runner() {
123
+        $config = Controller::instance()->get_migration_config_object();
124
+
125
+        return new Runner( $config );
126
+    }
127 127
 
128 128
 }
Please login to merge, or discard this patch.
libraries/action-scheduler/classes/migration/DryRun_ActionMigrator.php 1 patch
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -13,16 +13,16 @@
 block discarded – undo
13 13
  * @codeCoverageIgnore
14 14
  */
15 15
 class DryRun_ActionMigrator extends ActionMigrator {
16
-	/**
17
-	 * Simulate migrating an action.
18
-	 *
19
-	 * @param int $source_action_id Action ID.
20
-	 *
21
-	 * @return int
22
-	 */
23
-	public function migrate( $source_action_id ) {
24
-		do_action( 'action_scheduler/migrate_action_dry_run', $source_action_id );
16
+    /**
17
+     * Simulate migrating an action.
18
+     *
19
+     * @param int $source_action_id Action ID.
20
+     *
21
+     * @return int
22
+     */
23
+    public function migrate( $source_action_id ) {
24
+        do_action( 'action_scheduler/migrate_action_dry_run', $source_action_id );
25 25
 
26
-		return 0;
27
-	}
26
+        return 0;
27
+    }
28 28
 }
Please login to merge, or discard this patch.
libraries/action-scheduler/classes/migration/DryRun_LogMigrator.php 1 patch
Indentation   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -11,13 +11,13 @@
 block discarded – undo
11 11
  * @codeCoverageIgnore
12 12
  */
13 13
 class DryRun_LogMigrator extends LogMigrator {
14
-	/**
15
-	 * Simulate migrating an action log.
16
-	 *
17
-	 * @param int $source_action_id Source logger object.
18
-	 * @param int $destination_action_id Destination logger object.
19
-	 */
20
-	public function migrate( $source_action_id, $destination_action_id ) {
21
-		// no-op
22
-	}
14
+    /**
15
+     * Simulate migrating an action log.
16
+     *
17
+     * @param int $source_action_id Source logger object.
18
+     * @param int $destination_action_id Destination logger object.
19
+     */
20
+    public function migrate( $source_action_id, $destination_action_id ) {
21
+        // no-op
22
+    }
23 23
 }
24 24
\ No newline at end of file
Please login to merge, or discard this patch.
action-scheduler/classes/migration/ActionScheduler_DBStoreMigrator.php 1 patch
Indentation   +31 added lines, -31 removed lines patch added patch discarded remove patch
@@ -9,39 +9,39 @@
 block discarded – undo
9 9
  */
10 10
 class ActionScheduler_DBStoreMigrator extends ActionScheduler_DBStore {
11 11
 
12
-	/**
13
-	 * Save an action with optional last attempt date.
14
-	 *
15
-	 * Normally, saving an action sets its attempted date to 0000-00-00 00:00:00 because when an action is first saved,
16
-	 * it can't have been attempted yet, but migrated completed actions will have an attempted date, so we need to save
17
-	 * that when first saving the action.
18
-	 *
19
-	 * @param ActionScheduler_Action $action
20
-	 * @param \DateTime $scheduled_date Optional date of the first instance to store.
21
-	 * @param \DateTime $last_attempt_date Optional date the action was last attempted.
22
-	 *
23
-	 * @return string The action ID
24
-	 * @throws \RuntimeException When the action is not saved.
25
-	 */
26
-	public function save_action( ActionScheduler_Action $action, \DateTime $scheduled_date = null, \DateTime $last_attempt_date = null ){
27
-		try {
28
-			/** @var \wpdb $wpdb */
29
-			global $wpdb;
12
+    /**
13
+     * Save an action with optional last attempt date.
14
+     *
15
+     * Normally, saving an action sets its attempted date to 0000-00-00 00:00:00 because when an action is first saved,
16
+     * it can't have been attempted yet, but migrated completed actions will have an attempted date, so we need to save
17
+     * that when first saving the action.
18
+     *
19
+     * @param ActionScheduler_Action $action
20
+     * @param \DateTime $scheduled_date Optional date of the first instance to store.
21
+     * @param \DateTime $last_attempt_date Optional date the action was last attempted.
22
+     *
23
+     * @return string The action ID
24
+     * @throws \RuntimeException When the action is not saved.
25
+     */
26
+    public function save_action( ActionScheduler_Action $action, \DateTime $scheduled_date = null, \DateTime $last_attempt_date = null ){
27
+        try {
28
+            /** @var \wpdb $wpdb */
29
+            global $wpdb;
30 30
 
31
-			$action_id = parent::save_action( $action, $scheduled_date );
31
+            $action_id = parent::save_action( $action, $scheduled_date );
32 32
 
33
-			if ( null !== $last_attempt_date ) {
34
-				$data = [
35
-					'last_attempt_gmt'   => $this->get_scheduled_date_string( $action, $last_attempt_date ),
36
-					'last_attempt_local' => $this->get_scheduled_date_string_local( $action, $last_attempt_date ),
37
-				];
33
+            if ( null !== $last_attempt_date ) {
34
+                $data = [
35
+                    'last_attempt_gmt'   => $this->get_scheduled_date_string( $action, $last_attempt_date ),
36
+                    'last_attempt_local' => $this->get_scheduled_date_string_local( $action, $last_attempt_date ),
37
+                ];
38 38
 
39
-				$wpdb->update( $wpdb->actionscheduler_actions, $data, array( 'action_id' => $action_id ), array( '%s', '%s' ), array( '%d' ) );
40
-			}
39
+                $wpdb->update( $wpdb->actionscheduler_actions, $data, array( 'action_id' => $action_id ), array( '%s', '%s' ), array( '%d' ) );
40
+            }
41 41
 
42
-			return $action_id;
43
-		} catch ( \Exception $e ) {
44
-			throw new \RuntimeException( sprintf( __( 'Error saving action: %s', 'action-scheduler' ), $e->getMessage() ), 0 );
45
-		}
46
-	}
42
+            return $action_id;
43
+        } catch ( \Exception $e ) {
44
+            throw new \RuntimeException( sprintf( __( 'Error saving action: %s', 'action-scheduler' ), $e->getMessage() ), 0 );
45
+        }
46
+    }
47 47
 }
Please login to merge, or discard this patch.
includes/libraries/action-scheduler/classes/migration/Controller.php 1 patch
Indentation   +186 added lines, -186 removed lines patch added patch discarded remove patch
@@ -17,190 +17,190 @@
 block discarded – undo
17 17
  * @codeCoverageIgnore
18 18
  */
19 19
 class Controller {
20
-	private static $instance;
21
-
22
-	/** @var Action_Scheduler\Migration\Scheduler */
23
-	private $migration_scheduler;
24
-
25
-	/** @var string */
26
-	private $store_classname;
27
-
28
-	/** @var string */
29
-	private $logger_classname;
30
-
31
-	/** @var bool */
32
-	private $migrate_custom_store;
33
-
34
-	/**
35
-	 * Controller constructor.
36
-	 *
37
-	 * @param Scheduler $migration_scheduler Migration scheduler object.
38
-	 */
39
-	protected function __construct( Scheduler $migration_scheduler ) {
40
-		$this->migration_scheduler = $migration_scheduler;
41
-		$this->store_classname     = '';
42
-	}
43
-
44
-	/**
45
-	 * Set the action store class name.
46
-	 *
47
-	 * @param string $class Classname of the store class.
48
-	 *
49
-	 * @return string
50
-	 */
51
-	public function get_store_class( $class ) {
52
-		if ( \ActionScheduler_DataController::is_migration_complete() ) {
53
-			return \ActionScheduler_DataController::DATASTORE_CLASS;
54
-		} elseif ( \ActionScheduler_Store::DEFAULT_CLASS !== $class ) {
55
-			$this->store_classname = $class;
56
-			return $class;
57
-		} else {
58
-			return 'ActionScheduler_HybridStore';
59
-		}
60
-	}
61
-
62
-	/**
63
-	 * Set the action logger class name.
64
-	 *
65
-	 * @param string $class Classname of the logger class.
66
-	 *
67
-	 * @return string
68
-	 */
69
-	public function get_logger_class( $class ) {
70
-		\ActionScheduler_Store::instance();
71
-
72
-		if ( $this->has_custom_datastore() ) {
73
-			$this->logger_classname = $class;
74
-			return $class;
75
-		} else {
76
-			return \ActionScheduler_DataController::LOGGER_CLASS;
77
-		}
78
-	}
79
-
80
-	/**
81
-	 * Get flag indicating whether a custom datastore is in use.
82
-	 *
83
-	 * @return bool
84
-	 */
85
-	public function has_custom_datastore() {
86
-		return (bool) $this->store_classname;
87
-	}
88
-
89
-	/**
90
-	 * Set up the background migration process
91
-	 *
92
-	 * @return void
93
-	 */
94
-	public function schedule_migration() {
95
-		if ( \ActionScheduler_DataController::is_migration_complete() || $this->migration_scheduler->is_migration_scheduled() ) {
96
-			return;
97
-		}
98
-
99
-		$this->migration_scheduler->schedule_migration();
100
-	}
101
-
102
-	/**
103
-	 * Get the default migration config object
104
-	 *
105
-	 * @return ActionScheduler\Migration\Config
106
-	 */
107
-	public function get_migration_config_object() {
108
-		static $config = null;
109
-
110
-		if ( ! $config ) {
111
-			$source_store  = $this->store_classname ? new $this->store_classname() : new \ActionScheduler_wpPostStore();
112
-			$source_logger = $this->logger_classname ? new $this->logger_classname() : new \ActionScheduler_wpCommentLogger();
113
-
114
-			$config = new Config();
115
-			$config->set_source_store( $source_store );
116
-			$config->set_source_logger( $source_logger );
117
-			$config->set_destination_store( new \ActionScheduler_DBStoreMigrator() );
118
-			$config->set_destination_logger( new \ActionScheduler_DBLogger() );
119
-
120
-			if ( defined( 'WP_CLI' ) && WP_CLI ) {
121
-				$config->set_progress_bar( new ProgressBar( '', 0 ) );
122
-			}
123
-		}
124
-
125
-		return apply_filters( 'action_scheduler/migration_config', $config );
126
-	}
127
-
128
-	/**
129
-	 * Hook dashboard migration notice.
130
-	 */
131
-	public function hook_admin_notices() {
132
-		if ( ! $this->allow_migration() || \ActionScheduler_DataController::is_migration_complete() ) {
133
-			return;
134
-		}
135
-		add_action( 'admin_notices', array( $this, 'display_migration_notice' ), 10, 0 );
136
-	}
137
-
138
-	/**
139
-	 * Show a dashboard notice that migration is in progress.
140
-	 */
141
-	public function display_migration_notice() {
142
-		printf( '<div class="notice notice-warning"><p>%s</p></div>', __( 'Action Scheduler migration in progress. The list of scheduled actions may be incomplete.', 'action-scheduler' ) );
143
-	}
144
-
145
-	/**
146
-	 * Add store classes. Hook migration.
147
-	 */
148
-	private function hook() {
149
-		add_filter( 'action_scheduler_store_class', array( $this, 'get_store_class' ), 100, 1 );
150
-		add_filter( 'action_scheduler_logger_class', array( $this, 'get_logger_class' ), 100, 1 );
151
-		add_action( 'init', array( $this, 'maybe_hook_migration' ) );
152
-		add_action( 'shutdown', array( $this, 'schedule_migration' ), 0, 0 );
153
-
154
-		// Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen
155
-		add_action( 'load-tools_page_action-scheduler', array( $this, 'hook_admin_notices' ), 10, 0 );
156
-		add_action( 'load-woocommerce_page_wc-status', array( $this, 'hook_admin_notices' ), 10, 0 );
157
-	}
158
-
159
-	/**
160
-	 * Possibly hook the migration scheduler action.
161
-	 *
162
-	 * @author Jeremy Pry
163
-	 */
164
-	public function maybe_hook_migration() {
165
-		if ( ! $this->allow_migration() || \ActionScheduler_DataController::is_migration_complete() ) {
166
-			return;
167
-		}
168
-
169
-		$this->migration_scheduler->hook();
170
-	}
171
-
172
-	/**
173
-	 * Allow datastores to enable migration to AS tables.
174
-	 */
175
-	public function allow_migration() {
176
-		if ( ! \ActionScheduler_DataController::dependencies_met() ) {
177
-			return false;
178
-		}
179
-
180
-		if ( null === $this->migrate_custom_store ) {
181
-			$this->migrate_custom_store = apply_filters( 'action_scheduler_migrate_data_store', false );
182
-		}
183
-
184
-		return ( ! $this->has_custom_datastore() ) || $this->migrate_custom_store;
185
-	}
186
-
187
-	/**
188
-	 * Proceed with the migration if the dependencies have been met.
189
-	 */
190
-	public static function init() {
191
-		if ( \ActionScheduler_DataController::dependencies_met() ) {
192
-			self::instance()->hook();
193
-		}
194
-	}
195
-
196
-	/**
197
-	 * Singleton factory.
198
-	 */
199
-	public static function instance() {
200
-		if ( ! isset( self::$instance ) ) {
201
-			self::$instance = new static( new Scheduler() );
202
-		}
203
-
204
-		return self::$instance;
205
-	}
20
+    private static $instance;
21
+
22
+    /** @var Action_Scheduler\Migration\Scheduler */
23
+    private $migration_scheduler;
24
+
25
+    /** @var string */
26
+    private $store_classname;
27
+
28
+    /** @var string */
29
+    private $logger_classname;
30
+
31
+    /** @var bool */
32
+    private $migrate_custom_store;
33
+
34
+    /**
35
+     * Controller constructor.
36
+     *
37
+     * @param Scheduler $migration_scheduler Migration scheduler object.
38
+     */
39
+    protected function __construct( Scheduler $migration_scheduler ) {
40
+        $this->migration_scheduler = $migration_scheduler;
41
+        $this->store_classname     = '';
42
+    }
43
+
44
+    /**
45
+     * Set the action store class name.
46
+     *
47
+     * @param string $class Classname of the store class.
48
+     *
49
+     * @return string
50
+     */
51
+    public function get_store_class( $class ) {
52
+        if ( \ActionScheduler_DataController::is_migration_complete() ) {
53
+            return \ActionScheduler_DataController::DATASTORE_CLASS;
54
+        } elseif ( \ActionScheduler_Store::DEFAULT_CLASS !== $class ) {
55
+            $this->store_classname = $class;
56
+            return $class;
57
+        } else {
58
+            return 'ActionScheduler_HybridStore';
59
+        }
60
+    }
61
+
62
+    /**
63
+     * Set the action logger class name.
64
+     *
65
+     * @param string $class Classname of the logger class.
66
+     *
67
+     * @return string
68
+     */
69
+    public function get_logger_class( $class ) {
70
+        \ActionScheduler_Store::instance();
71
+
72
+        if ( $this->has_custom_datastore() ) {
73
+            $this->logger_classname = $class;
74
+            return $class;
75
+        } else {
76
+            return \ActionScheduler_DataController::LOGGER_CLASS;
77
+        }
78
+    }
79
+
80
+    /**
81
+     * Get flag indicating whether a custom datastore is in use.
82
+     *
83
+     * @return bool
84
+     */
85
+    public function has_custom_datastore() {
86
+        return (bool) $this->store_classname;
87
+    }
88
+
89
+    /**
90
+     * Set up the background migration process
91
+     *
92
+     * @return void
93
+     */
94
+    public function schedule_migration() {
95
+        if ( \ActionScheduler_DataController::is_migration_complete() || $this->migration_scheduler->is_migration_scheduled() ) {
96
+            return;
97
+        }
98
+
99
+        $this->migration_scheduler->schedule_migration();
100
+    }
101
+
102
+    /**
103
+     * Get the default migration config object
104
+     *
105
+     * @return ActionScheduler\Migration\Config
106
+     */
107
+    public function get_migration_config_object() {
108
+        static $config = null;
109
+
110
+        if ( ! $config ) {
111
+            $source_store  = $this->store_classname ? new $this->store_classname() : new \ActionScheduler_wpPostStore();
112
+            $source_logger = $this->logger_classname ? new $this->logger_classname() : new \ActionScheduler_wpCommentLogger();
113
+
114
+            $config = new Config();
115
+            $config->set_source_store( $source_store );
116
+            $config->set_source_logger( $source_logger );
117
+            $config->set_destination_store( new \ActionScheduler_DBStoreMigrator() );
118
+            $config->set_destination_logger( new \ActionScheduler_DBLogger() );
119
+
120
+            if ( defined( 'WP_CLI' ) && WP_CLI ) {
121
+                $config->set_progress_bar( new ProgressBar( '', 0 ) );
122
+            }
123
+        }
124
+
125
+        return apply_filters( 'action_scheduler/migration_config', $config );
126
+    }
127
+
128
+    /**
129
+     * Hook dashboard migration notice.
130
+     */
131
+    public function hook_admin_notices() {
132
+        if ( ! $this->allow_migration() || \ActionScheduler_DataController::is_migration_complete() ) {
133
+            return;
134
+        }
135
+        add_action( 'admin_notices', array( $this, 'display_migration_notice' ), 10, 0 );
136
+    }
137
+
138
+    /**
139
+     * Show a dashboard notice that migration is in progress.
140
+     */
141
+    public function display_migration_notice() {
142
+        printf( '<div class="notice notice-warning"><p>%s</p></div>', __( 'Action Scheduler migration in progress. The list of scheduled actions may be incomplete.', 'action-scheduler' ) );
143
+    }
144
+
145
+    /**
146
+     * Add store classes. Hook migration.
147
+     */
148
+    private function hook() {
149
+        add_filter( 'action_scheduler_store_class', array( $this, 'get_store_class' ), 100, 1 );
150
+        add_filter( 'action_scheduler_logger_class', array( $this, 'get_logger_class' ), 100, 1 );
151
+        add_action( 'init', array( $this, 'maybe_hook_migration' ) );
152
+        add_action( 'shutdown', array( $this, 'schedule_migration' ), 0, 0 );
153
+
154
+        // Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen
155
+        add_action( 'load-tools_page_action-scheduler', array( $this, 'hook_admin_notices' ), 10, 0 );
156
+        add_action( 'load-woocommerce_page_wc-status', array( $this, 'hook_admin_notices' ), 10, 0 );
157
+    }
158
+
159
+    /**
160
+     * Possibly hook the migration scheduler action.
161
+     *
162
+     * @author Jeremy Pry
163
+     */
164
+    public function maybe_hook_migration() {
165
+        if ( ! $this->allow_migration() || \ActionScheduler_DataController::is_migration_complete() ) {
166
+            return;
167
+        }
168
+
169
+        $this->migration_scheduler->hook();
170
+    }
171
+
172
+    /**
173
+     * Allow datastores to enable migration to AS tables.
174
+     */
175
+    public function allow_migration() {
176
+        if ( ! \ActionScheduler_DataController::dependencies_met() ) {
177
+            return false;
178
+        }
179
+
180
+        if ( null === $this->migrate_custom_store ) {
181
+            $this->migrate_custom_store = apply_filters( 'action_scheduler_migrate_data_store', false );
182
+        }
183
+
184
+        return ( ! $this->has_custom_datastore() ) || $this->migrate_custom_store;
185
+    }
186
+
187
+    /**
188
+     * Proceed with the migration if the dependencies have been met.
189
+     */
190
+    public static function init() {
191
+        if ( \ActionScheduler_DataController::dependencies_met() ) {
192
+            self::instance()->hook();
193
+        }
194
+    }
195
+
196
+    /**
197
+     * Singleton factory.
198
+     */
199
+    public static function instance() {
200
+        if ( ! isset( self::$instance ) ) {
201
+            self::$instance = new static( new Scheduler() );
202
+        }
203
+
204
+        return self::$instance;
205
+    }
206 206
 }
Please login to merge, or discard this patch.
includes/libraries/action-scheduler/classes/migration/ActionMigrator.php 1 patch
Indentation   +93 added lines, -93 removed lines patch added patch discarded remove patch
@@ -13,97 +13,97 @@
 block discarded – undo
13 13
  * @codeCoverageIgnore
14 14
  */
15 15
 class ActionMigrator {
16
-	/** var ActionScheduler_Store */
17
-	private $source;
18
-
19
-	/** var ActionScheduler_Store */
20
-	private $destination;
21
-
22
-	/** var LogMigrator */
23
-	private $log_migrator;
24
-
25
-	/**
26
-	 * ActionMigrator constructor.
27
-	 *
28
-	 * @param ActionScheduler_Store $source_store Source store object.
29
-	 * @param ActionScheduler_Store $destination_store Destination store object.
30
-	 * @param LogMigrator           $log_migrator Log migrator object.
31
-	 */
32
-	public function __construct( \ActionScheduler_Store $source_store, \ActionScheduler_Store $destination_store, LogMigrator $log_migrator ) {
33
-		$this->source       = $source_store;
34
-		$this->destination  = $destination_store;
35
-		$this->log_migrator = $log_migrator;
36
-	}
37
-
38
-	/**
39
-	 * Migrate an action.
40
-	 *
41
-	 * @param int $source_action_id Action ID.
42
-	 *
43
-	 * @return int 0|new action ID
44
-	 */
45
-	public function migrate( $source_action_id ) {
46
-		try {
47
-			$action = $this->source->fetch_action( $source_action_id );
48
-			$status = $this->source->get_status( $source_action_id );
49
-		} catch ( \Exception $e ) {
50
-			$action = null;
51
-			$status = '';
52
-		}
53
-
54
-		if ( is_null( $action ) || empty( $status ) || ! $action->get_schedule()->get_date() ) {
55
-			// null action or empty status means the fetch operation failed or the action didn't exist
56
-			// null schedule means it's missing vital data
57
-			// delete it and move on
58
-			try {
59
-				$this->source->delete_action( $source_action_id );
60
-			} catch ( \Exception $e ) {
61
-				// nothing to do, it didn't exist in the first place
62
-			}
63
-			do_action( 'action_scheduler/no_action_to_migrate', $source_action_id, $this->source, $this->destination );
64
-
65
-			return 0;
66
-		}
67
-
68
-		try {
69
-
70
-			// Make sure the last attempt date is set correctly for completed and failed actions
71
-			$last_attempt_date = ( $status !== \ActionScheduler_Store::STATUS_PENDING ) ? $this->source->get_date( $source_action_id ) : null;
72
-
73
-			$destination_action_id = $this->destination->save_action( $action, null, $last_attempt_date );
74
-		} catch ( \Exception $e ) {
75
-			do_action( 'action_scheduler/migrate_action_failed', $source_action_id, $this->source, $this->destination );
76
-
77
-			return 0; // could not save the action in the new store
78
-		}
79
-
80
-		try {
81
-			switch ( $status ) {
82
-				case \ActionScheduler_Store::STATUS_FAILED :
83
-					$this->destination->mark_failure( $destination_action_id );
84
-					break;
85
-				case \ActionScheduler_Store::STATUS_CANCELED :
86
-					$this->destination->cancel_action( $destination_action_id );
87
-					break;
88
-			}
89
-
90
-			$this->log_migrator->migrate( $source_action_id, $destination_action_id );
91
-			$this->source->delete_action( $source_action_id );
92
-
93
-			$test_action = $this->source->fetch_action( $source_action_id );
94
-			if ( ! is_a( $test_action, 'ActionScheduler_NullAction' ) ) {
95
-				throw new \RuntimeException( sprintf( __( 'Unable to remove source migrated action %s', 'action-scheduler' ), $source_action_id ) );
96
-			}
97
-			do_action( 'action_scheduler/migrated_action', $source_action_id, $destination_action_id, $this->source, $this->destination );
98
-
99
-			return $destination_action_id;
100
-		} catch ( \Exception $e ) {
101
-			// could not delete from the old store
102
-			$this->source->mark_migrated( $source_action_id );
103
-			do_action( 'action_scheduler/migrate_action_incomplete', $source_action_id, $destination_action_id, $this->source, $this->destination );
104
-			do_action( 'action_scheduler/migrated_action', $source_action_id, $destination_action_id, $this->source, $this->destination );
105
-
106
-			return $destination_action_id;
107
-		}
108
-	}
16
+    /** var ActionScheduler_Store */
17
+    private $source;
18
+
19
+    /** var ActionScheduler_Store */
20
+    private $destination;
21
+
22
+    /** var LogMigrator */
23
+    private $log_migrator;
24
+
25
+    /**
26
+     * ActionMigrator constructor.
27
+     *
28
+     * @param ActionScheduler_Store $source_store Source store object.
29
+     * @param ActionScheduler_Store $destination_store Destination store object.
30
+     * @param LogMigrator           $log_migrator Log migrator object.
31
+     */
32
+    public function __construct( \ActionScheduler_Store $source_store, \ActionScheduler_Store $destination_store, LogMigrator $log_migrator ) {
33
+        $this->source       = $source_store;
34
+        $this->destination  = $destination_store;
35
+        $this->log_migrator = $log_migrator;
36
+    }
37
+
38
+    /**
39
+     * Migrate an action.
40
+     *
41
+     * @param int $source_action_id Action ID.
42
+     *
43
+     * @return int 0|new action ID
44
+     */
45
+    public function migrate( $source_action_id ) {
46
+        try {
47
+            $action = $this->source->fetch_action( $source_action_id );
48
+            $status = $this->source->get_status( $source_action_id );
49
+        } catch ( \Exception $e ) {
50
+            $action = null;
51
+            $status = '';
52
+        }
53
+
54
+        if ( is_null( $action ) || empty( $status ) || ! $action->get_schedule()->get_date() ) {
55
+            // null action or empty status means the fetch operation failed or the action didn't exist
56
+            // null schedule means it's missing vital data
57
+            // delete it and move on
58
+            try {
59
+                $this->source->delete_action( $source_action_id );
60
+            } catch ( \Exception $e ) {
61
+                // nothing to do, it didn't exist in the first place
62
+            }
63
+            do_action( 'action_scheduler/no_action_to_migrate', $source_action_id, $this->source, $this->destination );
64
+
65
+            return 0;
66
+        }
67
+
68
+        try {
69
+
70
+            // Make sure the last attempt date is set correctly for completed and failed actions
71
+            $last_attempt_date = ( $status !== \ActionScheduler_Store::STATUS_PENDING ) ? $this->source->get_date( $source_action_id ) : null;
72
+
73
+            $destination_action_id = $this->destination->save_action( $action, null, $last_attempt_date );
74
+        } catch ( \Exception $e ) {
75
+            do_action( 'action_scheduler/migrate_action_failed', $source_action_id, $this->source, $this->destination );
76
+
77
+            return 0; // could not save the action in the new store
78
+        }
79
+
80
+        try {
81
+            switch ( $status ) {
82
+                case \ActionScheduler_Store::STATUS_FAILED :
83
+                    $this->destination->mark_failure( $destination_action_id );
84
+                    break;
85
+                case \ActionScheduler_Store::STATUS_CANCELED :
86
+                    $this->destination->cancel_action( $destination_action_id );
87
+                    break;
88
+            }
89
+
90
+            $this->log_migrator->migrate( $source_action_id, $destination_action_id );
91
+            $this->source->delete_action( $source_action_id );
92
+
93
+            $test_action = $this->source->fetch_action( $source_action_id );
94
+            if ( ! is_a( $test_action, 'ActionScheduler_NullAction' ) ) {
95
+                throw new \RuntimeException( sprintf( __( 'Unable to remove source migrated action %s', 'action-scheduler' ), $source_action_id ) );
96
+            }
97
+            do_action( 'action_scheduler/migrated_action', $source_action_id, $destination_action_id, $this->source, $this->destination );
98
+
99
+            return $destination_action_id;
100
+        } catch ( \Exception $e ) {
101
+            // could not delete from the old store
102
+            $this->source->mark_migrated( $source_action_id );
103
+            do_action( 'action_scheduler/migrate_action_incomplete', $source_action_id, $destination_action_id, $this->source, $this->destination );
104
+            do_action( 'action_scheduler/migrated_action', $source_action_id, $destination_action_id, $this->source, $this->destination );
105
+
106
+            return $destination_action_id;
107
+        }
108
+    }
109 109
 }
Please login to merge, or discard this patch.
action-scheduler/classes/schedules/ActionScheduler_IntervalSchedule.php 1 patch
Indentation   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -5,77 +5,77 @@
 block discarded – undo
5 5
  */
6 6
 class ActionScheduler_IntervalSchedule extends ActionScheduler_Abstract_RecurringSchedule implements ActionScheduler_Schedule {
7 7
 
8
-	/**
9
-	 * Deprecated property @see $this->__wakeup() for details.
10
-	 **/
11
-	private $start_timestamp = NULL;
8
+    /**
9
+     * Deprecated property @see $this->__wakeup() for details.
10
+     **/
11
+    private $start_timestamp = NULL;
12 12
 
13
-	/**
14
-	 * Deprecated property @see $this->__wakeup() for details.
15
-	 **/
16
-	private $interval_in_seconds = NULL;
13
+    /**
14
+     * Deprecated property @see $this->__wakeup() for details.
15
+     **/
16
+    private $interval_in_seconds = NULL;
17 17
 
18
-	/**
19
-	 * Calculate when this schedule should start after a given date & time using
20
-	 * the number of seconds between recurrences.
21
-	 *
22
-	 * @param DateTime $after
23
-	 * @return DateTime
24
-	 */
25
-	protected function calculate_next( DateTime $after ) {
26
-		$after->modify( '+' . (int) $this->get_recurrence() . ' seconds' );
27
-		return $after;
28
-	}
18
+    /**
19
+     * Calculate when this schedule should start after a given date & time using
20
+     * the number of seconds between recurrences.
21
+     *
22
+     * @param DateTime $after
23
+     * @return DateTime
24
+     */
25
+    protected function calculate_next( DateTime $after ) {
26
+        $after->modify( '+' . (int) $this->get_recurrence() . ' seconds' );
27
+        return $after;
28
+    }
29 29
 
30
-	/**
31
-	 * @return int
32
-	 */
33
-	public function interval_in_seconds() {
34
-		_deprecated_function( __METHOD__, '3.0.0', '(int)ActionScheduler_Abstract_RecurringSchedule::get_recurrence()' );
35
-		return (int) $this->get_recurrence();
36
-	}
30
+    /**
31
+     * @return int
32
+     */
33
+    public function interval_in_seconds() {
34
+        _deprecated_function( __METHOD__, '3.0.0', '(int)ActionScheduler_Abstract_RecurringSchedule::get_recurrence()' );
35
+        return (int) $this->get_recurrence();
36
+    }
37 37
 
38
-	/**
39
-	 * Serialize interval schedules with data required prior to AS 3.0.0
40
-	 *
41
-	 * Prior to Action Scheduler 3.0.0, reccuring schedules used different property names to
42
-	 * refer to equivalent data. For example, ActionScheduler_IntervalSchedule::start_timestamp
43
-	 * was the same as ActionScheduler_SimpleSchedule::timestamp. Action Scheduler 3.0.0
44
-	 * aligned properties and property names for better inheritance. To guard against the
45
-	 * possibility of infinite loops if downgrading to Action Scheduler < 3.0.0, we need to
46
-	 * also store the data with the old property names so if it's unserialized in AS < 3.0,
47
-	 * the schedule doesn't end up with a null/false/0 recurrence.
48
-	 *
49
-	 * @return array
50
-	 */
51
-	public function __sleep() {
38
+    /**
39
+     * Serialize interval schedules with data required prior to AS 3.0.0
40
+     *
41
+     * Prior to Action Scheduler 3.0.0, reccuring schedules used different property names to
42
+     * refer to equivalent data. For example, ActionScheduler_IntervalSchedule::start_timestamp
43
+     * was the same as ActionScheduler_SimpleSchedule::timestamp. Action Scheduler 3.0.0
44
+     * aligned properties and property names for better inheritance. To guard against the
45
+     * possibility of infinite loops if downgrading to Action Scheduler < 3.0.0, we need to
46
+     * also store the data with the old property names so if it's unserialized in AS < 3.0,
47
+     * the schedule doesn't end up with a null/false/0 recurrence.
48
+     *
49
+     * @return array
50
+     */
51
+    public function __sleep() {
52 52
 
53
-		$sleep_params = parent::__sleep();
53
+        $sleep_params = parent::__sleep();
54 54
 
55
-		$this->start_timestamp     = $this->scheduled_timestamp;
56
-		$this->interval_in_seconds = $this->recurrence;
55
+        $this->start_timestamp     = $this->scheduled_timestamp;
56
+        $this->interval_in_seconds = $this->recurrence;
57 57
 
58
-		return array_merge( $sleep_params, array(
59
-			'start_timestamp',
60
-			'interval_in_seconds'
61
-		) );
62
-	}
58
+        return array_merge( $sleep_params, array(
59
+            'start_timestamp',
60
+            'interval_in_seconds'
61
+        ) );
62
+    }
63 63
 
64
-	/**
65
-	 * Unserialize interval schedules serialized/stored prior to AS 3.0.0
66
-	 *
67
-	 * For more background, @see ActionScheduler_Abstract_RecurringSchedule::__wakeup().
68
-	 */
69
-	public function __wakeup() {
70
-		if ( is_null( $this->scheduled_timestamp ) && ! is_null( $this->start_timestamp ) ) {
71
-			$this->scheduled_timestamp = $this->start_timestamp;
72
-			unset( $this->start_timestamp );
73
-		}
64
+    /**
65
+     * Unserialize interval schedules serialized/stored prior to AS 3.0.0
66
+     *
67
+     * For more background, @see ActionScheduler_Abstract_RecurringSchedule::__wakeup().
68
+     */
69
+    public function __wakeup() {
70
+        if ( is_null( $this->scheduled_timestamp ) && ! is_null( $this->start_timestamp ) ) {
71
+            $this->scheduled_timestamp = $this->start_timestamp;
72
+            unset( $this->start_timestamp );
73
+        }
74 74
 
75
-		if ( is_null( $this->recurrence ) && ! is_null( $this->interval_in_seconds ) ) {
76
-			$this->recurrence = $this->interval_in_seconds;
77
-			unset( $this->interval_in_seconds );
78
-		}
79
-		parent::__wakeup();
80
-	}
75
+        if ( is_null( $this->recurrence ) && ! is_null( $this->interval_in_seconds ) ) {
76
+            $this->recurrence = $this->interval_in_seconds;
77
+            unset( $this->interval_in_seconds );
78
+        }
79
+        parent::__wakeup();
80
+    }
81 81
 }
Please login to merge, or discard this patch.
action-scheduler/classes/schedules/ActionScheduler_SimpleSchedule.php 1 patch
Indentation   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -5,67 +5,67 @@
 block discarded – undo
5 5
  */
6 6
 class ActionScheduler_SimpleSchedule extends ActionScheduler_Abstract_Schedule {
7 7
 
8
-	/**
9
-	 * Deprecated property @see $this->__wakeup() for details.
10
-	 **/
11
-	private $timestamp = NULL;
8
+    /**
9
+     * Deprecated property @see $this->__wakeup() for details.
10
+     **/
11
+    private $timestamp = NULL;
12 12
 
13
-	/**
14
-	 * @param DateTime $after
15
-	 *
16
-	 * @return DateTime|null
17
-	 */
18
-	public function calculate_next( DateTime $after ) {
19
-		return null;
20
-	}
13
+    /**
14
+     * @param DateTime $after
15
+     *
16
+     * @return DateTime|null
17
+     */
18
+    public function calculate_next( DateTime $after ) {
19
+        return null;
20
+    }
21 21
 
22
-	/**
23
-	 * @return bool
24
-	 */
25
-	public function is_recurring() {
26
-		return false;
27
-	}
22
+    /**
23
+     * @return bool
24
+     */
25
+    public function is_recurring() {
26
+        return false;
27
+    }
28 28
 
29
-	/**
30
-	 * Serialize schedule with data required prior to AS 3.0.0
31
-	 *
32
-	 * Prior to Action Scheduler 3.0.0, schedules used different property names to refer
33
-	 * to equivalent data. For example, ActionScheduler_IntervalSchedule::start_timestamp
34
-	 * was the same as ActionScheduler_SimpleSchedule::timestamp. Action Scheduler 3.0.0
35
-	 * aligned properties and property names for better inheritance. To guard against the
36
-	 * scheduled date for single actions always being seen as "now" if downgrading to
37
-	 * Action Scheduler < 3.0.0, we need to also store the data with the old property names
38
-	 * so if it's unserialized in AS < 3.0, the schedule doesn't end up with a null recurrence.
39
-	 *
40
-	 * @return array
41
-	 */
42
-	public function __sleep() {
29
+    /**
30
+     * Serialize schedule with data required prior to AS 3.0.0
31
+     *
32
+     * Prior to Action Scheduler 3.0.0, schedules used different property names to refer
33
+     * to equivalent data. For example, ActionScheduler_IntervalSchedule::start_timestamp
34
+     * was the same as ActionScheduler_SimpleSchedule::timestamp. Action Scheduler 3.0.0
35
+     * aligned properties and property names for better inheritance. To guard against the
36
+     * scheduled date for single actions always being seen as "now" if downgrading to
37
+     * Action Scheduler < 3.0.0, we need to also store the data with the old property names
38
+     * so if it's unserialized in AS < 3.0, the schedule doesn't end up with a null recurrence.
39
+     *
40
+     * @return array
41
+     */
42
+    public function __sleep() {
43 43
 
44
-		$sleep_params = parent::__sleep();
44
+        $sleep_params = parent::__sleep();
45 45
 
46
-		$this->timestamp = $this->scheduled_timestamp;
46
+        $this->timestamp = $this->scheduled_timestamp;
47 47
 
48
-		return array_merge( $sleep_params, array(
49
-			'timestamp',
50
-		) );
51
-	}
48
+        return array_merge( $sleep_params, array(
49
+            'timestamp',
50
+        ) );
51
+    }
52 52
 
53
-	/**
54
-	 * Unserialize recurring schedules serialized/stored prior to AS 3.0.0
55
-	 *
56
-	 * Prior to Action Scheduler 3.0.0, schedules used different property names to refer
57
-	 * to equivalent data. For example, ActionScheduler_IntervalSchedule::start_timestamp
58
-	 * was the same as ActionScheduler_SimpleSchedule::timestamp. Action Scheduler 3.0.0
59
-	 * aligned properties and property names for better inheritance. To maintain backward
60
-	 * compatibility with schedules serialized and stored prior to 3.0, we need to correctly
61
-	 * map the old property names with matching visibility.
62
-	 */
63
-	public function __wakeup() {
53
+    /**
54
+     * Unserialize recurring schedules serialized/stored prior to AS 3.0.0
55
+     *
56
+     * Prior to Action Scheduler 3.0.0, schedules used different property names to refer
57
+     * to equivalent data. For example, ActionScheduler_IntervalSchedule::start_timestamp
58
+     * was the same as ActionScheduler_SimpleSchedule::timestamp. Action Scheduler 3.0.0
59
+     * aligned properties and property names for better inheritance. To maintain backward
60
+     * compatibility with schedules serialized and stored prior to 3.0, we need to correctly
61
+     * map the old property names with matching visibility.
62
+     */
63
+    public function __wakeup() {
64 64
 
65
-		if ( is_null( $this->scheduled_timestamp ) && ! is_null( $this->timestamp ) ) {
66
-			$this->scheduled_timestamp = $this->timestamp;
67
-			unset( $this->timestamp );
68
-		}
69
-		parent::__wakeup();
70
-	}
65
+        if ( is_null( $this->scheduled_timestamp ) && ! is_null( $this->timestamp ) ) {
66
+            $this->scheduled_timestamp = $this->timestamp;
67
+            unset( $this->timestamp );
68
+        }
69
+        parent::__wakeup();
70
+    }
71 71
 }
Please login to merge, or discard this patch.