Passed
Push — main ( aaef5c...e4c121 )
by TARIQ
71:39
created
packages/action-scheduler/classes/abstracts/ActionScheduler_Store.php 2 patches
Indentation   +414 added lines, -414 removed lines patch added patch discarded remove patch
@@ -5,418 +5,418 @@
 block discarded – undo
5 5
  * @codeCoverageIgnore
6 6
  */
7 7
 abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
8
-	const STATUS_COMPLETE = 'complete';
9
-	const STATUS_PENDING  = 'pending';
10
-	const STATUS_RUNNING  = 'in-progress';
11
-	const STATUS_FAILED   = 'failed';
12
-	const STATUS_CANCELED = 'canceled';
13
-	const DEFAULT_CLASS   = 'ActionScheduler_wpPostStore';
14
-
15
-	/** @var ActionScheduler_Store */
16
-	private static $store = NULL;
17
-
18
-	/** @var int */
19
-	protected static $max_args_length = 191;
20
-
21
-	/**
22
-	 * @param ActionScheduler_Action $action
23
-	 * @param DateTime $scheduled_date Optional Date of the first instance
24
-	 *        to store. Otherwise uses the first date of the action's
25
-	 *        schedule.
26
-	 *
27
-	 * @return int The action ID
28
-	 */
29
-	abstract public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = NULL );
30
-
31
-	/**
32
-	 * @param string $action_id
33
-	 *
34
-	 * @return ActionScheduler_Action
35
-	 */
36
-	abstract public function fetch_action( $action_id );
37
-
38
-	/**
39
-	 * Find an action.
40
-	 *
41
-	 * Note: the query ordering changes based on the passed 'status' value.
42
-	 *
43
-	 * @param string $hook Action hook.
44
-	 * @param array  $params Parameters of the action to find.
45
-	 *
46
-	 * @return string|null ID of the next action matching the criteria or NULL if not found.
47
-	 */
48
-	public function find_action( $hook, $params = array() ) {
49
-		$params = wp_parse_args(
50
-			$params,
51
-			array(
52
-				'args'   => null,
53
-				'status' => self::STATUS_PENDING,
54
-				'group'  => '',
55
-			)
56
-		);
57
-
58
-		// These params are fixed for this method.
59
-		$params['hook']     = $hook;
60
-		$params['orderby']  = 'date';
61
-		$params['per_page'] = 1;
62
-
63
-		if ( ! empty( $params['status'] ) ) {
64
-			if ( self::STATUS_PENDING === $params['status'] ) {
65
-				$params['order'] = 'ASC'; // Find the next action that matches.
66
-			} else {
67
-				$params['order'] = 'DESC'; // Find the most recent action that matches.
68
-			}
69
-		}
70
-
71
-		$results = $this->query_actions( $params );
72
-
73
-		return empty( $results ) ? null : $results[0];
74
-	}
75
-
76
-	/**
77
-	 * Query for action count or list of action IDs.
78
-	 *
79
-	 * @since x.x.x $query['status'] accepts array of statuses instead of a single status.
80
-	 *
81
-	 * @param array  $query {
82
-	 *      Query filtering options.
83
-	 *
84
-	 *      @type string       $hook             The name of the actions. Optional.
85
-	 *      @type string|array $status           The status or statuses of the actions. Optional.
86
-	 *      @type array        $args             The args array of the actions. Optional.
87
-	 *      @type DateTime     $date             The scheduled date of the action. Used in UTC timezone. Optional.
88
-	 *      @type string       $date_compare     Operator for selecting by $date param. Accepted values are '!=', '>', '>=', '<', '<=', '='. Defaults to '<='.
89
-	 *      @type DateTime     $modified         The last modified date of the action. Used in UTC timezone. Optional.
90
-	 *      @type string       $modified_compare Operator for comparing $modified param. Accepted values are '!=', '>', '>=', '<', '<=', '='. Defaults to '<='.
91
-	 *      @type string       $group            The group the action belongs to. Optional.
92
-	 *      @type bool|int     $claimed          TRUE to find claimed actions, FALSE to find unclaimed actions, an int to find a specific claim ID. Optional.
93
-	 *      @type int          $per_page         Number of results to return. Defaults to 5.
94
-	 *      @type int          $offset           The query pagination offset. Defaults to 0.
95
-	 *      @type int          $orderby          Accepted values are 'hook', 'group', 'modified', 'date' or 'none'. Defaults to 'date'.
96
-	 *      @type string       $order            Accepted values are 'ASC' or 'DESC'. Defaults to 'ASC'.
97
-	 * }
98
-	 * @param string $query_type Whether to select or count the results. Default, select.
99
-	 *
100
-	 * @return string|array|null The IDs of actions matching the query. Null on failure.
101
-	 */
102
-	abstract public function query_actions( $query = array(), $query_type = 'select' );
103
-
104
-	/**
105
-	 * Run query to get a single action ID.
106
-	 *
107
-	 * @since x.x.x
108
-	 *
109
-	 * @see ActionScheduler_Store::query_actions for $query arg usage but 'per_page' and 'offset' can't be used.
110
-	 *
111
-	 * @param array $query Query parameters.
112
-	 *
113
-	 * @return int|null
114
-	 */
115
-	public function query_action( $query ) {
116
-		$query['per_page'] = 1;
117
-		$query['offset']   = 0;
118
-		$results           = $this->query_actions( $query );
119
-
120
-		if ( empty( $results ) ) {
121
-			return null;
122
-		} else {
123
-			return (int) $results[0];
124
-		}
125
-	}
126
-
127
-	/**
128
-	 * Get a count of all actions in the store, grouped by status
129
-	 *
130
-	 * @return array
131
-	 */
132
-	abstract public function action_counts();
133
-
134
-	/**
135
-	 * @param string $action_id
136
-	 */
137
-	abstract public function cancel_action( $action_id );
138
-
139
-	/**
140
-	 * @param string $action_id
141
-	 */
142
-	abstract public function delete_action( $action_id );
143
-
144
-	/**
145
-	 * @param string $action_id
146
-	 *
147
-	 * @return DateTime The date the action is schedule to run, or the date that it ran.
148
-	 */
149
-	abstract public function get_date( $action_id );
150
-
151
-
152
-	/**
153
-	 * @param int      $max_actions
154
-	 * @param DateTime $before_date Claim only actions schedule before the given date. Defaults to now.
155
-	 * @param array    $hooks       Claim only actions with a hook or hooks.
156
-	 * @param string   $group       Claim only actions in the given group.
157
-	 *
158
-	 * @return ActionScheduler_ActionClaim
159
-	 */
160
-	abstract public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' );
161
-
162
-	/**
163
-	 * @return int
164
-	 */
165
-	abstract public function get_claim_count();
166
-
167
-	/**
168
-	 * @param ActionScheduler_ActionClaim $claim
169
-	 */
170
-	abstract public function release_claim( ActionScheduler_ActionClaim $claim );
171
-
172
-	/**
173
-	 * @param string $action_id
174
-	 */
175
-	abstract public function unclaim_action( $action_id );
176
-
177
-	/**
178
-	 * @param string $action_id
179
-	 */
180
-	abstract public function mark_failure( $action_id );
181
-
182
-	/**
183
-	 * @param string $action_id
184
-	 */
185
-	abstract public function log_execution( $action_id );
186
-
187
-	/**
188
-	 * @param string $action_id
189
-	 */
190
-	abstract public function mark_complete( $action_id );
191
-
192
-	/**
193
-	 * @param string $action_id
194
-	 *
195
-	 * @return string
196
-	 */
197
-	abstract public function get_status( $action_id );
198
-
199
-	/**
200
-	 * @param string $action_id
201
-	 * @return mixed
202
-	 */
203
-	abstract public function get_claim_id( $action_id );
204
-
205
-	/**
206
-	 * @param string $claim_id
207
-	 * @return array
208
-	 */
209
-	abstract public function find_actions_by_claim_id( $claim_id );
210
-
211
-	/**
212
-	 * @param string $comparison_operator
213
-	 * @return string
214
-	 */
215
-	protected function validate_sql_comparator( $comparison_operator ) {
216
-		if ( in_array( $comparison_operator, array('!=', '>', '>=', '<', '<=', '=') ) ) {
217
-			return $comparison_operator;
218
-		}
219
-		return '=';
220
-	}
221
-
222
-	/**
223
-	 * Get the time MySQL formated date/time string for an action's (next) scheduled date.
224
-	 *
225
-	 * @param ActionScheduler_Action $action
226
-	 * @param DateTime $scheduled_date (optional)
227
-	 * @return string
228
-	 */
229
-	protected function get_scheduled_date_string( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
230
-		$next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
231
-		if ( ! $next ) {
232
-			return '0000-00-00 00:00:00';
233
-		}
234
-		$next->setTimezone( new DateTimeZone( 'UTC' ) );
235
-
236
-		return $next->format( 'Y-m-d H:i:s' );
237
-	}
238
-
239
-	/**
240
-	 * Get the time MySQL formated date/time string for an action's (next) scheduled date.
241
-	 *
242
-	 * @param ActionScheduler_Action $action
243
-	 * @param DateTime $scheduled_date (optional)
244
-	 * @return string
245
-	 */
246
-	protected function get_scheduled_date_string_local( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
247
-		$next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
248
-		if ( ! $next ) {
249
-			return '0000-00-00 00:00:00';
250
-		}
251
-
252
-		ActionScheduler_TimezoneHelper::set_local_timezone( $next );
253
-		return $next->format( 'Y-m-d H:i:s' );
254
-	}
255
-
256
-	/**
257
-	 * Validate that we could decode action arguments.
258
-	 *
259
-	 * @param mixed $args      The decoded arguments.
260
-	 * @param int   $action_id The action ID.
261
-	 *
262
-	 * @throws ActionScheduler_InvalidActionException When the decoded arguments are invalid.
263
-	 */
264
-	protected function validate_args( $args, $action_id ) {
265
-		// Ensure we have an array of args.
266
-		if ( ! is_array( $args ) ) {
267
-			throw ActionScheduler_InvalidActionException::from_decoding_args( $action_id );
268
-		}
269
-
270
-		// Validate JSON decoding if possible.
271
-		if ( function_exists( 'json_last_error' ) && JSON_ERROR_NONE !== json_last_error() ) {
272
-			throw ActionScheduler_InvalidActionException::from_decoding_args( $action_id, $args );
273
-		}
274
-	}
275
-
276
-	/**
277
-	 * Validate a ActionScheduler_Schedule object.
278
-	 *
279
-	 * @param mixed $schedule  The unserialized ActionScheduler_Schedule object.
280
-	 * @param int   $action_id The action ID.
281
-	 *
282
-	 * @throws ActionScheduler_InvalidActionException When the schedule is invalid.
283
-	 */
284
-	protected function validate_schedule( $schedule, $action_id ) {
285
-		if ( empty( $schedule ) || ! is_a( $schedule, 'ActionScheduler_Schedule' ) ) {
286
-			throw ActionScheduler_InvalidActionException::from_schedule( $action_id, $schedule );
287
-		}
288
-	}
289
-
290
-	/**
291
-	 * InnoDB indexes have a maximum size of 767 bytes by default, which is only 191 characters with utf8mb4.
292
-	 *
293
-	 * Previously, AS wasn't concerned about args length, as we used the (unindex) post_content column. However,
294
-	 * with custom tables, we use an indexed VARCHAR column instead.
295
-	 *
296
-	 * @param  ActionScheduler_Action $action Action to be validated.
297
-	 * @throws InvalidArgumentException When json encoded args is too long.
298
-	 */
299
-	protected function validate_action( ActionScheduler_Action $action ) {
300
-		if ( strlen( json_encode( $action->get_args() ) ) > static::$max_args_length ) {
301
-			throw new InvalidArgumentException( sprintf( __( 'ActionScheduler_Action::$args too long. To ensure the args column can be indexed, action args should not be more than %d characters when encoded as JSON.', 'woocommerce' ), static::$max_args_length ) );
302
-		}
303
-	}
304
-
305
-	/**
306
-	 * Cancel pending actions by hook.
307
-	 *
308
-	 * @since 3.0.0
309
-	 *
310
-	 * @param string $hook Hook name.
311
-	 *
312
-	 * @return void
313
-	 */
314
-	public function cancel_actions_by_hook( $hook ) {
315
-		$action_ids = true;
316
-		while ( ! empty( $action_ids ) ) {
317
-			$action_ids = $this->query_actions(
318
-				array(
319
-					'hook'     => $hook,
320
-					'status'   => self::STATUS_PENDING,
321
-					'per_page' => 1000,
322
-					'orderby'  => 'action_id',
323
-				)
324
-			);
325
-
326
-			$this->bulk_cancel_actions( $action_ids );
327
-		}
328
-	}
329
-
330
-	/**
331
-	 * Cancel pending actions by group.
332
-	 *
333
-	 * @since 3.0.0
334
-	 *
335
-	 * @param string $group Group slug.
336
-	 *
337
-	 * @return void
338
-	 */
339
-	public function cancel_actions_by_group( $group ) {
340
-		$action_ids = true;
341
-		while ( ! empty( $action_ids ) ) {
342
-			$action_ids = $this->query_actions(
343
-				array(
344
-					'group'    => $group,
345
-					'status'   => self::STATUS_PENDING,
346
-					'per_page' => 1000,
347
-					'orderby'  => 'action_id',
348
-				)
349
-			);
350
-
351
-			$this->bulk_cancel_actions( $action_ids );
352
-		}
353
-	}
354
-
355
-	/**
356
-	 * Cancel a set of action IDs.
357
-	 *
358
-	 * @since 3.0.0
359
-	 *
360
-	 * @param array $action_ids List of action IDs.
361
-	 *
362
-	 * @return void
363
-	 */
364
-	private function bulk_cancel_actions( $action_ids ) {
365
-		foreach ( $action_ids as $action_id ) {
366
-			$this->cancel_action( $action_id );
367
-		}
368
-
369
-		do_action( 'action_scheduler_bulk_cancel_actions', $action_ids );
370
-	}
371
-
372
-	/**
373
-	 * @return array
374
-	 */
375
-	public function get_status_labels() {
376
-		return array(
377
-			self::STATUS_COMPLETE => __( 'Complete', 'woocommerce' ),
378
-			self::STATUS_PENDING  => __( 'Pending', 'woocommerce' ),
379
-			self::STATUS_RUNNING  => __( 'In-progress', 'woocommerce' ),
380
-			self::STATUS_FAILED   => __( 'Failed', 'woocommerce' ),
381
-			self::STATUS_CANCELED => __( 'Canceled', 'woocommerce' ),
382
-		);
383
-	}
384
-
385
-	/**
386
-	 * Check if there are any pending scheduled actions due to run.
387
-	 *
388
-	 * @param ActionScheduler_Action $action
389
-	 * @param DateTime $scheduled_date (optional)
390
-	 * @return string
391
-	 */
392
-	public function has_pending_actions_due() {
393
-		$pending_actions = $this->query_actions( array(
394
-			'date'    => as_get_datetime_object(),
395
-			'status'  => ActionScheduler_Store::STATUS_PENDING,
396
-			'orderby' => 'none',
397
-		) );
398
-
399
-		return ! empty( $pending_actions );
400
-	}
401
-
402
-	/**
403
-	 * Callable initialization function optionally overridden in derived classes.
404
-	 */
405
-	public function init() {}
406
-
407
-	/**
408
-	 * Callable function to mark an action as migrated optionally overridden in derived classes.
409
-	 */
410
-	public function mark_migrated( $action_id ) {}
411
-
412
-	/**
413
-	 * @return ActionScheduler_Store
414
-	 */
415
-	public static function instance() {
416
-		if ( empty( self::$store ) ) {
417
-			$class = apply_filters( 'action_scheduler_store_class', self::DEFAULT_CLASS );
418
-			self::$store = new $class();
419
-		}
420
-		return self::$store;
421
-	}
8
+    const STATUS_COMPLETE = 'complete';
9
+    const STATUS_PENDING  = 'pending';
10
+    const STATUS_RUNNING  = 'in-progress';
11
+    const STATUS_FAILED   = 'failed';
12
+    const STATUS_CANCELED = 'canceled';
13
+    const DEFAULT_CLASS   = 'ActionScheduler_wpPostStore';
14
+
15
+    /** @var ActionScheduler_Store */
16
+    private static $store = NULL;
17
+
18
+    /** @var int */
19
+    protected static $max_args_length = 191;
20
+
21
+    /**
22
+     * @param ActionScheduler_Action $action
23
+     * @param DateTime $scheduled_date Optional Date of the first instance
24
+     *        to store. Otherwise uses the first date of the action's
25
+     *        schedule.
26
+     *
27
+     * @return int The action ID
28
+     */
29
+    abstract public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = NULL );
30
+
31
+    /**
32
+     * @param string $action_id
33
+     *
34
+     * @return ActionScheduler_Action
35
+     */
36
+    abstract public function fetch_action( $action_id );
37
+
38
+    /**
39
+     * Find an action.
40
+     *
41
+     * Note: the query ordering changes based on the passed 'status' value.
42
+     *
43
+     * @param string $hook Action hook.
44
+     * @param array  $params Parameters of the action to find.
45
+     *
46
+     * @return string|null ID of the next action matching the criteria or NULL if not found.
47
+     */
48
+    public function find_action( $hook, $params = array() ) {
49
+        $params = wp_parse_args(
50
+            $params,
51
+            array(
52
+                'args'   => null,
53
+                'status' => self::STATUS_PENDING,
54
+                'group'  => '',
55
+            )
56
+        );
57
+
58
+        // These params are fixed for this method.
59
+        $params['hook']     = $hook;
60
+        $params['orderby']  = 'date';
61
+        $params['per_page'] = 1;
62
+
63
+        if ( ! empty( $params['status'] ) ) {
64
+            if ( self::STATUS_PENDING === $params['status'] ) {
65
+                $params['order'] = 'ASC'; // Find the next action that matches.
66
+            } else {
67
+                $params['order'] = 'DESC'; // Find the most recent action that matches.
68
+            }
69
+        }
70
+
71
+        $results = $this->query_actions( $params );
72
+
73
+        return empty( $results ) ? null : $results[0];
74
+    }
75
+
76
+    /**
77
+     * Query for action count or list of action IDs.
78
+     *
79
+     * @since x.x.x $query['status'] accepts array of statuses instead of a single status.
80
+     *
81
+     * @param array  $query {
82
+     *      Query filtering options.
83
+     *
84
+     *      @type string       $hook             The name of the actions. Optional.
85
+     *      @type string|array $status           The status or statuses of the actions. Optional.
86
+     *      @type array        $args             The args array of the actions. Optional.
87
+     *      @type DateTime     $date             The scheduled date of the action. Used in UTC timezone. Optional.
88
+     *      @type string       $date_compare     Operator for selecting by $date param. Accepted values are '!=', '>', '>=', '<', '<=', '='. Defaults to '<='.
89
+     *      @type DateTime     $modified         The last modified date of the action. Used in UTC timezone. Optional.
90
+     *      @type string       $modified_compare Operator for comparing $modified param. Accepted values are '!=', '>', '>=', '<', '<=', '='. Defaults to '<='.
91
+     *      @type string       $group            The group the action belongs to. Optional.
92
+     *      @type bool|int     $claimed          TRUE to find claimed actions, FALSE to find unclaimed actions, an int to find a specific claim ID. Optional.
93
+     *      @type int          $per_page         Number of results to return. Defaults to 5.
94
+     *      @type int          $offset           The query pagination offset. Defaults to 0.
95
+     *      @type int          $orderby          Accepted values are 'hook', 'group', 'modified', 'date' or 'none'. Defaults to 'date'.
96
+     *      @type string       $order            Accepted values are 'ASC' or 'DESC'. Defaults to 'ASC'.
97
+     * }
98
+     * @param string $query_type Whether to select or count the results. Default, select.
99
+     *
100
+     * @return string|array|null The IDs of actions matching the query. Null on failure.
101
+     */
102
+    abstract public function query_actions( $query = array(), $query_type = 'select' );
103
+
104
+    /**
105
+     * Run query to get a single action ID.
106
+     *
107
+     * @since x.x.x
108
+     *
109
+     * @see ActionScheduler_Store::query_actions for $query arg usage but 'per_page' and 'offset' can't be used.
110
+     *
111
+     * @param array $query Query parameters.
112
+     *
113
+     * @return int|null
114
+     */
115
+    public function query_action( $query ) {
116
+        $query['per_page'] = 1;
117
+        $query['offset']   = 0;
118
+        $results           = $this->query_actions( $query );
119
+
120
+        if ( empty( $results ) ) {
121
+            return null;
122
+        } else {
123
+            return (int) $results[0];
124
+        }
125
+    }
126
+
127
+    /**
128
+     * Get a count of all actions in the store, grouped by status
129
+     *
130
+     * @return array
131
+     */
132
+    abstract public function action_counts();
133
+
134
+    /**
135
+     * @param string $action_id
136
+     */
137
+    abstract public function cancel_action( $action_id );
138
+
139
+    /**
140
+     * @param string $action_id
141
+     */
142
+    abstract public function delete_action( $action_id );
143
+
144
+    /**
145
+     * @param string $action_id
146
+     *
147
+     * @return DateTime The date the action is schedule to run, or the date that it ran.
148
+     */
149
+    abstract public function get_date( $action_id );
150
+
151
+
152
+    /**
153
+     * @param int      $max_actions
154
+     * @param DateTime $before_date Claim only actions schedule before the given date. Defaults to now.
155
+     * @param array    $hooks       Claim only actions with a hook or hooks.
156
+     * @param string   $group       Claim only actions in the given group.
157
+     *
158
+     * @return ActionScheduler_ActionClaim
159
+     */
160
+    abstract public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' );
161
+
162
+    /**
163
+     * @return int
164
+     */
165
+    abstract public function get_claim_count();
166
+
167
+    /**
168
+     * @param ActionScheduler_ActionClaim $claim
169
+     */
170
+    abstract public function release_claim( ActionScheduler_ActionClaim $claim );
171
+
172
+    /**
173
+     * @param string $action_id
174
+     */
175
+    abstract public function unclaim_action( $action_id );
176
+
177
+    /**
178
+     * @param string $action_id
179
+     */
180
+    abstract public function mark_failure( $action_id );
181
+
182
+    /**
183
+     * @param string $action_id
184
+     */
185
+    abstract public function log_execution( $action_id );
186
+
187
+    /**
188
+     * @param string $action_id
189
+     */
190
+    abstract public function mark_complete( $action_id );
191
+
192
+    /**
193
+     * @param string $action_id
194
+     *
195
+     * @return string
196
+     */
197
+    abstract public function get_status( $action_id );
198
+
199
+    /**
200
+     * @param string $action_id
201
+     * @return mixed
202
+     */
203
+    abstract public function get_claim_id( $action_id );
204
+
205
+    /**
206
+     * @param string $claim_id
207
+     * @return array
208
+     */
209
+    abstract public function find_actions_by_claim_id( $claim_id );
210
+
211
+    /**
212
+     * @param string $comparison_operator
213
+     * @return string
214
+     */
215
+    protected function validate_sql_comparator( $comparison_operator ) {
216
+        if ( in_array( $comparison_operator, array('!=', '>', '>=', '<', '<=', '=') ) ) {
217
+            return $comparison_operator;
218
+        }
219
+        return '=';
220
+    }
221
+
222
+    /**
223
+     * Get the time MySQL formated date/time string for an action's (next) scheduled date.
224
+     *
225
+     * @param ActionScheduler_Action $action
226
+     * @param DateTime $scheduled_date (optional)
227
+     * @return string
228
+     */
229
+    protected function get_scheduled_date_string( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
230
+        $next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
231
+        if ( ! $next ) {
232
+            return '0000-00-00 00:00:00';
233
+        }
234
+        $next->setTimezone( new DateTimeZone( 'UTC' ) );
235
+
236
+        return $next->format( 'Y-m-d H:i:s' );
237
+    }
238
+
239
+    /**
240
+     * Get the time MySQL formated date/time string for an action's (next) scheduled date.
241
+     *
242
+     * @param ActionScheduler_Action $action
243
+     * @param DateTime $scheduled_date (optional)
244
+     * @return string
245
+     */
246
+    protected function get_scheduled_date_string_local( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
247
+        $next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
248
+        if ( ! $next ) {
249
+            return '0000-00-00 00:00:00';
250
+        }
251
+
252
+        ActionScheduler_TimezoneHelper::set_local_timezone( $next );
253
+        return $next->format( 'Y-m-d H:i:s' );
254
+    }
255
+
256
+    /**
257
+     * Validate that we could decode action arguments.
258
+     *
259
+     * @param mixed $args      The decoded arguments.
260
+     * @param int   $action_id The action ID.
261
+     *
262
+     * @throws ActionScheduler_InvalidActionException When the decoded arguments are invalid.
263
+     */
264
+    protected function validate_args( $args, $action_id ) {
265
+        // Ensure we have an array of args.
266
+        if ( ! is_array( $args ) ) {
267
+            throw ActionScheduler_InvalidActionException::from_decoding_args( $action_id );
268
+        }
269
+
270
+        // Validate JSON decoding if possible.
271
+        if ( function_exists( 'json_last_error' ) && JSON_ERROR_NONE !== json_last_error() ) {
272
+            throw ActionScheduler_InvalidActionException::from_decoding_args( $action_id, $args );
273
+        }
274
+    }
275
+
276
+    /**
277
+     * Validate a ActionScheduler_Schedule object.
278
+     *
279
+     * @param mixed $schedule  The unserialized ActionScheduler_Schedule object.
280
+     * @param int   $action_id The action ID.
281
+     *
282
+     * @throws ActionScheduler_InvalidActionException When the schedule is invalid.
283
+     */
284
+    protected function validate_schedule( $schedule, $action_id ) {
285
+        if ( empty( $schedule ) || ! is_a( $schedule, 'ActionScheduler_Schedule' ) ) {
286
+            throw ActionScheduler_InvalidActionException::from_schedule( $action_id, $schedule );
287
+        }
288
+    }
289
+
290
+    /**
291
+     * InnoDB indexes have a maximum size of 767 bytes by default, which is only 191 characters with utf8mb4.
292
+     *
293
+     * Previously, AS wasn't concerned about args length, as we used the (unindex) post_content column. However,
294
+     * with custom tables, we use an indexed VARCHAR column instead.
295
+     *
296
+     * @param  ActionScheduler_Action $action Action to be validated.
297
+     * @throws InvalidArgumentException When json encoded args is too long.
298
+     */
299
+    protected function validate_action( ActionScheduler_Action $action ) {
300
+        if ( strlen( json_encode( $action->get_args() ) ) > static::$max_args_length ) {
301
+            throw new InvalidArgumentException( sprintf( __( 'ActionScheduler_Action::$args too long. To ensure the args column can be indexed, action args should not be more than %d characters when encoded as JSON.', 'woocommerce' ), static::$max_args_length ) );
302
+        }
303
+    }
304
+
305
+    /**
306
+     * Cancel pending actions by hook.
307
+     *
308
+     * @since 3.0.0
309
+     *
310
+     * @param string $hook Hook name.
311
+     *
312
+     * @return void
313
+     */
314
+    public function cancel_actions_by_hook( $hook ) {
315
+        $action_ids = true;
316
+        while ( ! empty( $action_ids ) ) {
317
+            $action_ids = $this->query_actions(
318
+                array(
319
+                    'hook'     => $hook,
320
+                    'status'   => self::STATUS_PENDING,
321
+                    'per_page' => 1000,
322
+                    'orderby'  => 'action_id',
323
+                )
324
+            );
325
+
326
+            $this->bulk_cancel_actions( $action_ids );
327
+        }
328
+    }
329
+
330
+    /**
331
+     * Cancel pending actions by group.
332
+     *
333
+     * @since 3.0.0
334
+     *
335
+     * @param string $group Group slug.
336
+     *
337
+     * @return void
338
+     */
339
+    public function cancel_actions_by_group( $group ) {
340
+        $action_ids = true;
341
+        while ( ! empty( $action_ids ) ) {
342
+            $action_ids = $this->query_actions(
343
+                array(
344
+                    'group'    => $group,
345
+                    'status'   => self::STATUS_PENDING,
346
+                    'per_page' => 1000,
347
+                    'orderby'  => 'action_id',
348
+                )
349
+            );
350
+
351
+            $this->bulk_cancel_actions( $action_ids );
352
+        }
353
+    }
354
+
355
+    /**
356
+     * Cancel a set of action IDs.
357
+     *
358
+     * @since 3.0.0
359
+     *
360
+     * @param array $action_ids List of action IDs.
361
+     *
362
+     * @return void
363
+     */
364
+    private function bulk_cancel_actions( $action_ids ) {
365
+        foreach ( $action_ids as $action_id ) {
366
+            $this->cancel_action( $action_id );
367
+        }
368
+
369
+        do_action( 'action_scheduler_bulk_cancel_actions', $action_ids );
370
+    }
371
+
372
+    /**
373
+     * @return array
374
+     */
375
+    public function get_status_labels() {
376
+        return array(
377
+            self::STATUS_COMPLETE => __( 'Complete', 'woocommerce' ),
378
+            self::STATUS_PENDING  => __( 'Pending', 'woocommerce' ),
379
+            self::STATUS_RUNNING  => __( 'In-progress', 'woocommerce' ),
380
+            self::STATUS_FAILED   => __( 'Failed', 'woocommerce' ),
381
+            self::STATUS_CANCELED => __( 'Canceled', 'woocommerce' ),
382
+        );
383
+    }
384
+
385
+    /**
386
+     * Check if there are any pending scheduled actions due to run.
387
+     *
388
+     * @param ActionScheduler_Action $action
389
+     * @param DateTime $scheduled_date (optional)
390
+     * @return string
391
+     */
392
+    public function has_pending_actions_due() {
393
+        $pending_actions = $this->query_actions( array(
394
+            'date'    => as_get_datetime_object(),
395
+            'status'  => ActionScheduler_Store::STATUS_PENDING,
396
+            'orderby' => 'none',
397
+        ) );
398
+
399
+        return ! empty( $pending_actions );
400
+    }
401
+
402
+    /**
403
+     * Callable initialization function optionally overridden in derived classes.
404
+     */
405
+    public function init() {}
406
+
407
+    /**
408
+     * Callable function to mark an action as migrated optionally overridden in derived classes.
409
+     */
410
+    public function mark_migrated( $action_id ) {}
411
+
412
+    /**
413
+     * @return ActionScheduler_Store
414
+     */
415
+    public static function instance() {
416
+        if ( empty( self::$store ) ) {
417
+            $class = apply_filters( 'action_scheduler_store_class', self::DEFAULT_CLASS );
418
+            self::$store = new $class();
419
+        }
420
+        return self::$store;
421
+    }
422 422
 }
Please login to merge, or discard this patch.
Spacing   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -26,14 +26,14 @@  discard block
 block discarded – undo
26 26
 	 *
27 27
 	 * @return int The action ID
28 28
 	 */
29
-	abstract public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = NULL );
29
+	abstract public function save_action(ActionScheduler_Action $action, DateTime $scheduled_date = NULL);
30 30
 
31 31
 	/**
32 32
 	 * @param string $action_id
33 33
 	 *
34 34
 	 * @return ActionScheduler_Action
35 35
 	 */
36
-	abstract public function fetch_action( $action_id );
36
+	abstract public function fetch_action($action_id);
37 37
 
38 38
 	/**
39 39
 	 * Find an action.
@@ -45,7 +45,7 @@  discard block
 block discarded – undo
45 45
 	 *
46 46
 	 * @return string|null ID of the next action matching the criteria or NULL if not found.
47 47
 	 */
48
-	public function find_action( $hook, $params = array() ) {
48
+	public function find_action($hook, $params = array()) {
49 49
 		$params = wp_parse_args(
50 50
 			$params,
51 51
 			array(
@@ -60,17 +60,17 @@  discard block
 block discarded – undo
60 60
 		$params['orderby']  = 'date';
61 61
 		$params['per_page'] = 1;
62 62
 
63
-		if ( ! empty( $params['status'] ) ) {
64
-			if ( self::STATUS_PENDING === $params['status'] ) {
63
+		if (!empty($params['status'])) {
64
+			if (self::STATUS_PENDING === $params['status']) {
65 65
 				$params['order'] = 'ASC'; // Find the next action that matches.
66 66
 			} else {
67 67
 				$params['order'] = 'DESC'; // Find the most recent action that matches.
68 68
 			}
69 69
 		}
70 70
 
71
-		$results = $this->query_actions( $params );
71
+		$results = $this->query_actions($params);
72 72
 
73
-		return empty( $results ) ? null : $results[0];
73
+		return empty($results) ? null : $results[0];
74 74
 	}
75 75
 
76 76
 	/**
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
 	 *
100 100
 	 * @return string|array|null The IDs of actions matching the query. Null on failure.
101 101
 	 */
102
-	abstract public function query_actions( $query = array(), $query_type = 'select' );
102
+	abstract public function query_actions($query = array(), $query_type = 'select');
103 103
 
104 104
 	/**
105 105
 	 * Run query to get a single action ID.
@@ -112,12 +112,12 @@  discard block
 block discarded – undo
112 112
 	 *
113 113
 	 * @return int|null
114 114
 	 */
115
-	public function query_action( $query ) {
115
+	public function query_action($query) {
116 116
 		$query['per_page'] = 1;
117 117
 		$query['offset']   = 0;
118
-		$results           = $this->query_actions( $query );
118
+		$results           = $this->query_actions($query);
119 119
 
120
-		if ( empty( $results ) ) {
120
+		if (empty($results)) {
121 121
 			return null;
122 122
 		} else {
123 123
 			return (int) $results[0];
@@ -134,19 +134,19 @@  discard block
 block discarded – undo
134 134
 	/**
135 135
 	 * @param string $action_id
136 136
 	 */
137
-	abstract public function cancel_action( $action_id );
137
+	abstract public function cancel_action($action_id);
138 138
 
139 139
 	/**
140 140
 	 * @param string $action_id
141 141
 	 */
142
-	abstract public function delete_action( $action_id );
142
+	abstract public function delete_action($action_id);
143 143
 
144 144
 	/**
145 145
 	 * @param string $action_id
146 146
 	 *
147 147
 	 * @return DateTime The date the action is schedule to run, or the date that it ran.
148 148
 	 */
149
-	abstract public function get_date( $action_id );
149
+	abstract public function get_date($action_id);
150 150
 
151 151
 
152 152
 	/**
@@ -157,7 +157,7 @@  discard block
 block discarded – undo
157 157
 	 *
158 158
 	 * @return ActionScheduler_ActionClaim
159 159
 	 */
160
-	abstract public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' );
160
+	abstract public function stake_claim($max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '');
161 161
 
162 162
 	/**
163 163
 	 * @return int
@@ -167,53 +167,53 @@  discard block
 block discarded – undo
167 167
 	/**
168 168
 	 * @param ActionScheduler_ActionClaim $claim
169 169
 	 */
170
-	abstract public function release_claim( ActionScheduler_ActionClaim $claim );
170
+	abstract public function release_claim(ActionScheduler_ActionClaim $claim);
171 171
 
172 172
 	/**
173 173
 	 * @param string $action_id
174 174
 	 */
175
-	abstract public function unclaim_action( $action_id );
175
+	abstract public function unclaim_action($action_id);
176 176
 
177 177
 	/**
178 178
 	 * @param string $action_id
179 179
 	 */
180
-	abstract public function mark_failure( $action_id );
180
+	abstract public function mark_failure($action_id);
181 181
 
182 182
 	/**
183 183
 	 * @param string $action_id
184 184
 	 */
185
-	abstract public function log_execution( $action_id );
185
+	abstract public function log_execution($action_id);
186 186
 
187 187
 	/**
188 188
 	 * @param string $action_id
189 189
 	 */
190
-	abstract public function mark_complete( $action_id );
190
+	abstract public function mark_complete($action_id);
191 191
 
192 192
 	/**
193 193
 	 * @param string $action_id
194 194
 	 *
195 195
 	 * @return string
196 196
 	 */
197
-	abstract public function get_status( $action_id );
197
+	abstract public function get_status($action_id);
198 198
 
199 199
 	/**
200 200
 	 * @param string $action_id
201 201
 	 * @return mixed
202 202
 	 */
203
-	abstract public function get_claim_id( $action_id );
203
+	abstract public function get_claim_id($action_id);
204 204
 
205 205
 	/**
206 206
 	 * @param string $claim_id
207 207
 	 * @return array
208 208
 	 */
209
-	abstract public function find_actions_by_claim_id( $claim_id );
209
+	abstract public function find_actions_by_claim_id($claim_id);
210 210
 
211 211
 	/**
212 212
 	 * @param string $comparison_operator
213 213
 	 * @return string
214 214
 	 */
215
-	protected function validate_sql_comparator( $comparison_operator ) {
216
-		if ( in_array( $comparison_operator, array('!=', '>', '>=', '<', '<=', '=') ) ) {
215
+	protected function validate_sql_comparator($comparison_operator) {
216
+		if (in_array($comparison_operator, array('!=', '>', '>=', '<', '<=', '='))) {
217 217
 			return $comparison_operator;
218 218
 		}
219 219
 		return '=';
@@ -226,14 +226,14 @@  discard block
 block discarded – undo
226 226
 	 * @param DateTime $scheduled_date (optional)
227 227
 	 * @return string
228 228
 	 */
229
-	protected function get_scheduled_date_string( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
229
+	protected function get_scheduled_date_string(ActionScheduler_Action $action, DateTime $scheduled_date = NULL) {
230 230
 		$next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
231
-		if ( ! $next ) {
231
+		if (!$next) {
232 232
 			return '0000-00-00 00:00:00';
233 233
 		}
234
-		$next->setTimezone( new DateTimeZone( 'UTC' ) );
234
+		$next->setTimezone(new DateTimeZone('UTC'));
235 235
 
236
-		return $next->format( 'Y-m-d H:i:s' );
236
+		return $next->format('Y-m-d H:i:s');
237 237
 	}
238 238
 
239 239
 	/**
@@ -243,14 +243,14 @@  discard block
 block discarded – undo
243 243
 	 * @param DateTime $scheduled_date (optional)
244 244
 	 * @return string
245 245
 	 */
246
-	protected function get_scheduled_date_string_local( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
246
+	protected function get_scheduled_date_string_local(ActionScheduler_Action $action, DateTime $scheduled_date = NULL) {
247 247
 		$next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
248
-		if ( ! $next ) {
248
+		if (!$next) {
249 249
 			return '0000-00-00 00:00:00';
250 250
 		}
251 251
 
252
-		ActionScheduler_TimezoneHelper::set_local_timezone( $next );
253
-		return $next->format( 'Y-m-d H:i:s' );
252
+		ActionScheduler_TimezoneHelper::set_local_timezone($next);
253
+		return $next->format('Y-m-d H:i:s');
254 254
 	}
255 255
 
256 256
 	/**
@@ -261,15 +261,15 @@  discard block
 block discarded – undo
261 261
 	 *
262 262
 	 * @throws ActionScheduler_InvalidActionException When the decoded arguments are invalid.
263 263
 	 */
264
-	protected function validate_args( $args, $action_id ) {
264
+	protected function validate_args($args, $action_id) {
265 265
 		// Ensure we have an array of args.
266
-		if ( ! is_array( $args ) ) {
267
-			throw ActionScheduler_InvalidActionException::from_decoding_args( $action_id );
266
+		if (!is_array($args)) {
267
+			throw ActionScheduler_InvalidActionException::from_decoding_args($action_id);
268 268
 		}
269 269
 
270 270
 		// Validate JSON decoding if possible.
271
-		if ( function_exists( 'json_last_error' ) && JSON_ERROR_NONE !== json_last_error() ) {
272
-			throw ActionScheduler_InvalidActionException::from_decoding_args( $action_id, $args );
271
+		if (function_exists('json_last_error') && JSON_ERROR_NONE !== json_last_error()) {
272
+			throw ActionScheduler_InvalidActionException::from_decoding_args($action_id, $args);
273 273
 		}
274 274
 	}
275 275
 
@@ -281,9 +281,9 @@  discard block
 block discarded – undo
281 281
 	 *
282 282
 	 * @throws ActionScheduler_InvalidActionException When the schedule is invalid.
283 283
 	 */
284
-	protected function validate_schedule( $schedule, $action_id ) {
285
-		if ( empty( $schedule ) || ! is_a( $schedule, 'ActionScheduler_Schedule' ) ) {
286
-			throw ActionScheduler_InvalidActionException::from_schedule( $action_id, $schedule );
284
+	protected function validate_schedule($schedule, $action_id) {
285
+		if (empty($schedule) || !is_a($schedule, 'ActionScheduler_Schedule')) {
286
+			throw ActionScheduler_InvalidActionException::from_schedule($action_id, $schedule);
287 287
 		}
288 288
 	}
289 289
 
@@ -296,9 +296,9 @@  discard block
 block discarded – undo
296 296
 	 * @param  ActionScheduler_Action $action Action to be validated.
297 297
 	 * @throws InvalidArgumentException When json encoded args is too long.
298 298
 	 */
299
-	protected function validate_action( ActionScheduler_Action $action ) {
300
-		if ( strlen( json_encode( $action->get_args() ) ) > static::$max_args_length ) {
301
-			throw new InvalidArgumentException( sprintf( __( 'ActionScheduler_Action::$args too long. To ensure the args column can be indexed, action args should not be more than %d characters when encoded as JSON.', 'woocommerce' ), static::$max_args_length ) );
299
+	protected function validate_action(ActionScheduler_Action $action) {
300
+		if (strlen(json_encode($action->get_args())) > static::$max_args_length) {
301
+			throw new InvalidArgumentException(sprintf(__('ActionScheduler_Action::$args too long. To ensure the args column can be indexed, action args should not be more than %d characters when encoded as JSON.', 'woocommerce'), static::$max_args_length));
302 302
 		}
303 303
 	}
304 304
 
@@ -311,9 +311,9 @@  discard block
 block discarded – undo
311 311
 	 *
312 312
 	 * @return void
313 313
 	 */
314
-	public function cancel_actions_by_hook( $hook ) {
314
+	public function cancel_actions_by_hook($hook) {
315 315
 		$action_ids = true;
316
-		while ( ! empty( $action_ids ) ) {
316
+		while (!empty($action_ids)) {
317 317
 			$action_ids = $this->query_actions(
318 318
 				array(
319 319
 					'hook'     => $hook,
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
 				)
324 324
 			);
325 325
 
326
-			$this->bulk_cancel_actions( $action_ids );
326
+			$this->bulk_cancel_actions($action_ids);
327 327
 		}
328 328
 	}
329 329
 
@@ -336,9 +336,9 @@  discard block
 block discarded – undo
336 336
 	 *
337 337
 	 * @return void
338 338
 	 */
339
-	public function cancel_actions_by_group( $group ) {
339
+	public function cancel_actions_by_group($group) {
340 340
 		$action_ids = true;
341
-		while ( ! empty( $action_ids ) ) {
341
+		while (!empty($action_ids)) {
342 342
 			$action_ids = $this->query_actions(
343 343
 				array(
344 344
 					'group'    => $group,
@@ -348,7 +348,7 @@  discard block
 block discarded – undo
348 348
 				)
349 349
 			);
350 350
 
351
-			$this->bulk_cancel_actions( $action_ids );
351
+			$this->bulk_cancel_actions($action_ids);
352 352
 		}
353 353
 	}
354 354
 
@@ -361,12 +361,12 @@  discard block
 block discarded – undo
361 361
 	 *
362 362
 	 * @return void
363 363
 	 */
364
-	private function bulk_cancel_actions( $action_ids ) {
365
-		foreach ( $action_ids as $action_id ) {
366
-			$this->cancel_action( $action_id );
364
+	private function bulk_cancel_actions($action_ids) {
365
+		foreach ($action_ids as $action_id) {
366
+			$this->cancel_action($action_id);
367 367
 		}
368 368
 
369
-		do_action( 'action_scheduler_bulk_cancel_actions', $action_ids );
369
+		do_action('action_scheduler_bulk_cancel_actions', $action_ids);
370 370
 	}
371 371
 
372 372
 	/**
@@ -374,11 +374,11 @@  discard block
 block discarded – undo
374 374
 	 */
375 375
 	public function get_status_labels() {
376 376
 		return array(
377
-			self::STATUS_COMPLETE => __( 'Complete', 'woocommerce' ),
378
-			self::STATUS_PENDING  => __( 'Pending', 'woocommerce' ),
379
-			self::STATUS_RUNNING  => __( 'In-progress', 'woocommerce' ),
380
-			self::STATUS_FAILED   => __( 'Failed', 'woocommerce' ),
381
-			self::STATUS_CANCELED => __( 'Canceled', 'woocommerce' ),
377
+			self::STATUS_COMPLETE => __('Complete', 'woocommerce'),
378
+			self::STATUS_PENDING  => __('Pending', 'woocommerce'),
379
+			self::STATUS_RUNNING  => __('In-progress', 'woocommerce'),
380
+			self::STATUS_FAILED   => __('Failed', 'woocommerce'),
381
+			self::STATUS_CANCELED => __('Canceled', 'woocommerce'),
382 382
 		);
383 383
 	}
384 384
 
@@ -390,13 +390,13 @@  discard block
 block discarded – undo
390 390
 	 * @return string
391 391
 	 */
392 392
 	public function has_pending_actions_due() {
393
-		$pending_actions = $this->query_actions( array(
393
+		$pending_actions = $this->query_actions(array(
394 394
 			'date'    => as_get_datetime_object(),
395 395
 			'status'  => ActionScheduler_Store::STATUS_PENDING,
396 396
 			'orderby' => 'none',
397
-		) );
397
+		));
398 398
 
399
-		return ! empty( $pending_actions );
399
+		return !empty($pending_actions);
400 400
 	}
401 401
 
402 402
 	/**
@@ -407,14 +407,14 @@  discard block
 block discarded – undo
407 407
 	/**
408 408
 	 * Callable function to mark an action as migrated optionally overridden in derived classes.
409 409
 	 */
410
-	public function mark_migrated( $action_id ) {}
410
+	public function mark_migrated($action_id) {}
411 411
 
412 412
 	/**
413 413
 	 * @return ActionScheduler_Store
414 414
 	 */
415 415
 	public static function instance() {
416
-		if ( empty( self::$store ) ) {
417
-			$class = apply_filters( 'action_scheduler_store_class', self::DEFAULT_CLASS );
416
+		if (empty(self::$store)) {
417
+			$class = apply_filters('action_scheduler_store_class', self::DEFAULT_CLASS);
418 418
 			self::$store = new $class();
419 419
 		}
420 420
 		return self::$store;
Please login to merge, or discard this patch.
woocommerce/packages/action-scheduler/classes/abstracts/ActionScheduler.php 2 patches
Indentation   +293 added lines, -293 removed lines patch added patch discarded remove patch
@@ -8,297 +8,297 @@
 block discarded – undo
8 8
  * @codeCoverageIgnore
9 9
  */
10 10
 abstract class ActionScheduler {
11
-	private static $plugin_file = '';
12
-	/** @var ActionScheduler_ActionFactory */
13
-	private static $factory = NULL;
14
-	/** @var bool */
15
-	private static $data_store_initialized = false;
16
-
17
-	public static function factory() {
18
-		if ( !isset(self::$factory) ) {
19
-			self::$factory = new ActionScheduler_ActionFactory();
20
-		}
21
-		return self::$factory;
22
-	}
23
-
24
-	public static function store() {
25
-		return ActionScheduler_Store::instance();
26
-	}
27
-
28
-	public static function lock() {
29
-		return ActionScheduler_Lock::instance();
30
-	}
31
-
32
-	public static function logger() {
33
-		return ActionScheduler_Logger::instance();
34
-	}
35
-
36
-	public static function runner() {
37
-		return ActionScheduler_QueueRunner::instance();
38
-	}
39
-
40
-	public static function admin_view() {
41
-		return ActionScheduler_AdminView::instance();
42
-	}
43
-
44
-	/**
45
-	 * Get the absolute system path to the plugin directory, or a file therein
46
-	 * @static
47
-	 * @param string $path
48
-	 * @return string
49
-	 */
50
-	public static function plugin_path( $path ) {
51
-		$base = dirname(self::$plugin_file);
52
-		if ( $path ) {
53
-			return trailingslashit($base).$path;
54
-		} else {
55
-			return untrailingslashit($base);
56
-		}
57
-	}
58
-
59
-	/**
60
-	 * Get the absolute URL to the plugin directory, or a file therein
61
-	 * @static
62
-	 * @param string $path
63
-	 * @return string
64
-	 */
65
-	public static function plugin_url( $path ) {
66
-		return plugins_url($path, self::$plugin_file);
67
-	}
68
-
69
-	public static function autoload( $class ) {
70
-		$d           = DIRECTORY_SEPARATOR;
71
-		$classes_dir = self::plugin_path( 'classes' . $d );
72
-		$separator   = strrpos( $class, '\\' );
73
-		if ( false !== $separator ) {
74
-			if ( 0 !== strpos( $class, 'Action_Scheduler' ) ) {
75
-				return;
76
-			}
77
-			$class = substr( $class, $separator + 1 );
78
-		}
79
-
80
-		if ( 'Deprecated' === substr( $class, -10 ) ) {
81
-			$dir = self::plugin_path( 'deprecated' . $d );
82
-		} elseif ( self::is_class_abstract( $class ) ) {
83
-			$dir = $classes_dir . 'abstracts' . $d;
84
-		} elseif ( self::is_class_migration( $class ) ) {
85
-			$dir = $classes_dir . 'migration' . $d;
86
-		} elseif ( 'Schedule' === substr( $class, -8 ) ) {
87
-			$dir = $classes_dir . 'schedules' . $d;
88
-		} elseif ( 'Action' === substr( $class, -6 ) ) {
89
-			$dir = $classes_dir . 'actions' . $d;
90
-		} elseif ( 'Schema' === substr( $class, -6 ) ) {
91
-			$dir = $classes_dir . 'schema' . $d;
92
-		} elseif ( strpos( $class, 'ActionScheduler' ) === 0 ) {
93
-			$segments = explode( '_', $class );
94
-			$type = isset( $segments[ 1 ] ) ? $segments[ 1 ] : '';
95
-
96
-			switch ( $type ) {
97
-				case 'WPCLI':
98
-					$dir = $classes_dir . 'WP_CLI' . $d;
99
-					break;
100
-				case 'DBLogger':
101
-				case 'DBStore':
102
-				case 'HybridStore':
103
-				case 'wpPostStore':
104
-				case 'wpCommentLogger':
105
-					$dir = $classes_dir . 'data-stores' . $d;
106
-					break;
107
-				default:
108
-					$dir = $classes_dir;
109
-					break;
110
-			}
111
-		} elseif ( self::is_class_cli( $class ) ) {
112
-			$dir = $classes_dir . 'WP_CLI' . $d;
113
-		} elseif ( strpos( $class, 'CronExpression' ) === 0 ) {
114
-			$dir = self::plugin_path( 'lib' . $d . 'cron-expression' . $d );
115
-		} elseif ( strpos( $class, 'WP_Async_Request' ) === 0 ) {
116
-			$dir = self::plugin_path( 'lib' . $d );
117
-		} else {
118
-			return;
119
-		}
120
-
121
-		if ( file_exists( $dir . "{$class}.php" ) ) {
122
-			include( $dir . "{$class}.php" );
123
-			return;
124
-		}
125
-	}
126
-
127
-	/**
128
-	 * Initialize the plugin
129
-	 *
130
-	 * @static
131
-	 * @param string $plugin_file
132
-	 */
133
-	public static function init( $plugin_file ) {
134
-		self::$plugin_file = $plugin_file;
135
-		spl_autoload_register( array( __CLASS__, 'autoload' ) );
136
-
137
-		/**
138
-		 * Fires in the early stages of Action Scheduler init hook.
139
-		 */
140
-		do_action( 'action_scheduler_pre_init' );
141
-
142
-		require_once( self::plugin_path( 'functions.php' ) );
143
-		ActionScheduler_DataController::init();
144
-
145
-		$store      = self::store();
146
-		$logger     = self::logger();
147
-		$runner     = self::runner();
148
-		$admin_view = self::admin_view();
149
-
150
-		// Ensure initialization on plugin activation.
151
-		if ( ! did_action( 'init' ) ) {
152
-			add_action( 'init', array( $admin_view, 'init' ), 0, 0 ); // run before $store::init()
153
-			add_action( 'init', array( $store, 'init' ), 1, 0 );
154
-			add_action( 'init', array( $logger, 'init' ), 1, 0 );
155
-			add_action( 'init', array( $runner, 'init' ), 1, 0 );
156
-		} else {
157
-			$admin_view->init();
158
-			$store->init();
159
-			$logger->init();
160
-			$runner->init();
161
-		}
162
-
163
-		if ( apply_filters( 'action_scheduler_load_deprecated_functions', true ) ) {
164
-			require_once( self::plugin_path( 'deprecated/functions.php' ) );
165
-		}
166
-
167
-		if ( defined( 'WP_CLI' ) && WP_CLI ) {
168
-			WP_CLI::add_command( 'action-scheduler', 'ActionScheduler_WPCLI_Scheduler_command' );
169
-			if ( ! ActionScheduler_DataController::is_migration_complete() && Controller::instance()->allow_migration() ) {
170
-				$command = new Migration_Command();
171
-				$command->register();
172
-			}
173
-		}
174
-
175
-		self::$data_store_initialized = true;
176
-
177
-		/**
178
-		 * Handle WP comment cleanup after migration.
179
-		 */
180
-		if ( is_a( $logger, 'ActionScheduler_DBLogger' ) && ActionScheduler_DataController::is_migration_complete() && ActionScheduler_WPCommentCleaner::has_logs() ) {
181
-			ActionScheduler_WPCommentCleaner::init();
182
-		}
183
-
184
-		add_action( 'action_scheduler/migration_complete', 'ActionScheduler_WPCommentCleaner::maybe_schedule_cleanup' );
185
-	}
186
-
187
-	/**
188
-	 * Check whether the AS data store has been initialized.
189
-	 *
190
-	 * @param string $function_name The name of the function being called. Optional. Default `null`.
191
-	 * @return bool
192
-	 */
193
-	public static function is_initialized( $function_name = null ) {
194
-		if ( ! self::$data_store_initialized && ! empty( $function_name ) ) {
195
-			$message = sprintf( __( '%s() was called before the Action Scheduler data store was initialized', 'woocommerce' ), esc_attr( $function_name ) );
196
-			error_log( $message, E_WARNING );
197
-		}
198
-
199
-		return self::$data_store_initialized;
200
-	}
201
-
202
-	/**
203
-	 * Determine if the class is one of our abstract classes.
204
-	 *
205
-	 * @since 3.0.0
206
-	 *
207
-	 * @param string $class The class name.
208
-	 *
209
-	 * @return bool
210
-	 */
211
-	protected static function is_class_abstract( $class ) {
212
-		static $abstracts = array(
213
-			'ActionScheduler'                            => true,
214
-			'ActionScheduler_Abstract_ListTable'         => true,
215
-			'ActionScheduler_Abstract_QueueRunner'       => true,
216
-			'ActionScheduler_Abstract_Schedule'          => true,
217
-			'ActionScheduler_Abstract_RecurringSchedule' => true,
218
-			'ActionScheduler_Lock'                       => true,
219
-			'ActionScheduler_Logger'                     => true,
220
-			'ActionScheduler_Abstract_Schema'            => true,
221
-			'ActionScheduler_Store'                      => true,
222
-			'ActionScheduler_TimezoneHelper'             => true,
223
-		);
224
-
225
-		return isset( $abstracts[ $class ] ) && $abstracts[ $class ];
226
-	}
227
-
228
-	/**
229
-	 * Determine if the class is one of our migration classes.
230
-	 *
231
-	 * @since 3.0.0
232
-	 *
233
-	 * @param string $class The class name.
234
-	 *
235
-	 * @return bool
236
-	 */
237
-	protected static function is_class_migration( $class ) {
238
-		static $migration_segments = array(
239
-			'ActionMigrator'  => true,
240
-			'BatchFetcher'    => true,
241
-			'DBStoreMigrator' => true,
242
-			'DryRun'          => true,
243
-			'LogMigrator'     => true,
244
-			'Config'          => true,
245
-			'Controller'      => true,
246
-			'Runner'          => true,
247
-			'Scheduler'       => true,
248
-		);
249
-
250
-		$segments = explode( '_', $class );
251
-		$segment = isset( $segments[ 1 ] ) ? $segments[ 1 ] : $class;
252
-
253
-		return isset( $migration_segments[ $segment ] ) && $migration_segments[ $segment ];
254
-	}
255
-
256
-	/**
257
-	 * Determine if the class is one of our WP CLI classes.
258
-	 *
259
-	 * @since 3.0.0
260
-	 *
261
-	 * @param string $class The class name.
262
-	 *
263
-	 * @return bool
264
-	 */
265
-	protected static function is_class_cli( $class ) {
266
-		static $cli_segments = array(
267
-			'QueueRunner' => true,
268
-			'Command'     => true,
269
-			'ProgressBar' => true,
270
-		);
271
-
272
-		$segments = explode( '_', $class );
273
-		$segment = isset( $segments[ 1 ] ) ? $segments[ 1 ] : $class;
274
-
275
-		return isset( $cli_segments[ $segment ] ) && $cli_segments[ $segment ];
276
-	}
277
-
278
-	final public function __clone() {
279
-		trigger_error("Singleton. No cloning allowed!", E_USER_ERROR);
280
-	}
281
-
282
-	final public function __wakeup() {
283
-		trigger_error("Singleton. No serialization allowed!", E_USER_ERROR);
284
-	}
285
-
286
-	final private function __construct() {}
287
-
288
-	/** Deprecated **/
289
-
290
-	public static function get_datetime_object( $when = null, $timezone = 'UTC' ) {
291
-		_deprecated_function( __METHOD__, '2.0', 'wcs_add_months()' );
292
-		return as_get_datetime_object( $when, $timezone );
293
-	}
294
-
295
-	/**
296
-	 * Issue deprecated warning if an Action Scheduler function is called in the shutdown hook.
297
-	 *
298
-	 * @param string $function_name The name of the function being called.
299
-	 * @deprecated 3.1.6.
300
-	 */
301
-	public static function check_shutdown_hook( $function_name ) {
302
-		_deprecated_function( __FUNCTION__, '3.1.6' );
303
-	}
11
+    private static $plugin_file = '';
12
+    /** @var ActionScheduler_ActionFactory */
13
+    private static $factory = NULL;
14
+    /** @var bool */
15
+    private static $data_store_initialized = false;
16
+
17
+    public static function factory() {
18
+        if ( !isset(self::$factory) ) {
19
+            self::$factory = new ActionScheduler_ActionFactory();
20
+        }
21
+        return self::$factory;
22
+    }
23
+
24
+    public static function store() {
25
+        return ActionScheduler_Store::instance();
26
+    }
27
+
28
+    public static function lock() {
29
+        return ActionScheduler_Lock::instance();
30
+    }
31
+
32
+    public static function logger() {
33
+        return ActionScheduler_Logger::instance();
34
+    }
35
+
36
+    public static function runner() {
37
+        return ActionScheduler_QueueRunner::instance();
38
+    }
39
+
40
+    public static function admin_view() {
41
+        return ActionScheduler_AdminView::instance();
42
+    }
43
+
44
+    /**
45
+     * Get the absolute system path to the plugin directory, or a file therein
46
+     * @static
47
+     * @param string $path
48
+     * @return string
49
+     */
50
+    public static function plugin_path( $path ) {
51
+        $base = dirname(self::$plugin_file);
52
+        if ( $path ) {
53
+            return trailingslashit($base).$path;
54
+        } else {
55
+            return untrailingslashit($base);
56
+        }
57
+    }
58
+
59
+    /**
60
+     * Get the absolute URL to the plugin directory, or a file therein
61
+     * @static
62
+     * @param string $path
63
+     * @return string
64
+     */
65
+    public static function plugin_url( $path ) {
66
+        return plugins_url($path, self::$plugin_file);
67
+    }
68
+
69
+    public static function autoload( $class ) {
70
+        $d           = DIRECTORY_SEPARATOR;
71
+        $classes_dir = self::plugin_path( 'classes' . $d );
72
+        $separator   = strrpos( $class, '\\' );
73
+        if ( false !== $separator ) {
74
+            if ( 0 !== strpos( $class, 'Action_Scheduler' ) ) {
75
+                return;
76
+            }
77
+            $class = substr( $class, $separator + 1 );
78
+        }
79
+
80
+        if ( 'Deprecated' === substr( $class, -10 ) ) {
81
+            $dir = self::plugin_path( 'deprecated' . $d );
82
+        } elseif ( self::is_class_abstract( $class ) ) {
83
+            $dir = $classes_dir . 'abstracts' . $d;
84
+        } elseif ( self::is_class_migration( $class ) ) {
85
+            $dir = $classes_dir . 'migration' . $d;
86
+        } elseif ( 'Schedule' === substr( $class, -8 ) ) {
87
+            $dir = $classes_dir . 'schedules' . $d;
88
+        } elseif ( 'Action' === substr( $class, -6 ) ) {
89
+            $dir = $classes_dir . 'actions' . $d;
90
+        } elseif ( 'Schema' === substr( $class, -6 ) ) {
91
+            $dir = $classes_dir . 'schema' . $d;
92
+        } elseif ( strpos( $class, 'ActionScheduler' ) === 0 ) {
93
+            $segments = explode( '_', $class );
94
+            $type = isset( $segments[ 1 ] ) ? $segments[ 1 ] : '';
95
+
96
+            switch ( $type ) {
97
+                case 'WPCLI':
98
+                    $dir = $classes_dir . 'WP_CLI' . $d;
99
+                    break;
100
+                case 'DBLogger':
101
+                case 'DBStore':
102
+                case 'HybridStore':
103
+                case 'wpPostStore':
104
+                case 'wpCommentLogger':
105
+                    $dir = $classes_dir . 'data-stores' . $d;
106
+                    break;
107
+                default:
108
+                    $dir = $classes_dir;
109
+                    break;
110
+            }
111
+        } elseif ( self::is_class_cli( $class ) ) {
112
+            $dir = $classes_dir . 'WP_CLI' . $d;
113
+        } elseif ( strpos( $class, 'CronExpression' ) === 0 ) {
114
+            $dir = self::plugin_path( 'lib' . $d . 'cron-expression' . $d );
115
+        } elseif ( strpos( $class, 'WP_Async_Request' ) === 0 ) {
116
+            $dir = self::plugin_path( 'lib' . $d );
117
+        } else {
118
+            return;
119
+        }
120
+
121
+        if ( file_exists( $dir . "{$class}.php" ) ) {
122
+            include( $dir . "{$class}.php" );
123
+            return;
124
+        }
125
+    }
126
+
127
+    /**
128
+     * Initialize the plugin
129
+     *
130
+     * @static
131
+     * @param string $plugin_file
132
+     */
133
+    public static function init( $plugin_file ) {
134
+        self::$plugin_file = $plugin_file;
135
+        spl_autoload_register( array( __CLASS__, 'autoload' ) );
136
+
137
+        /**
138
+         * Fires in the early stages of Action Scheduler init hook.
139
+         */
140
+        do_action( 'action_scheduler_pre_init' );
141
+
142
+        require_once( self::plugin_path( 'functions.php' ) );
143
+        ActionScheduler_DataController::init();
144
+
145
+        $store      = self::store();
146
+        $logger     = self::logger();
147
+        $runner     = self::runner();
148
+        $admin_view = self::admin_view();
149
+
150
+        // Ensure initialization on plugin activation.
151
+        if ( ! did_action( 'init' ) ) {
152
+            add_action( 'init', array( $admin_view, 'init' ), 0, 0 ); // run before $store::init()
153
+            add_action( 'init', array( $store, 'init' ), 1, 0 );
154
+            add_action( 'init', array( $logger, 'init' ), 1, 0 );
155
+            add_action( 'init', array( $runner, 'init' ), 1, 0 );
156
+        } else {
157
+            $admin_view->init();
158
+            $store->init();
159
+            $logger->init();
160
+            $runner->init();
161
+        }
162
+
163
+        if ( apply_filters( 'action_scheduler_load_deprecated_functions', true ) ) {
164
+            require_once( self::plugin_path( 'deprecated/functions.php' ) );
165
+        }
166
+
167
+        if ( defined( 'WP_CLI' ) && WP_CLI ) {
168
+            WP_CLI::add_command( 'action-scheduler', 'ActionScheduler_WPCLI_Scheduler_command' );
169
+            if ( ! ActionScheduler_DataController::is_migration_complete() && Controller::instance()->allow_migration() ) {
170
+                $command = new Migration_Command();
171
+                $command->register();
172
+            }
173
+        }
174
+
175
+        self::$data_store_initialized = true;
176
+
177
+        /**
178
+         * Handle WP comment cleanup after migration.
179
+         */
180
+        if ( is_a( $logger, 'ActionScheduler_DBLogger' ) && ActionScheduler_DataController::is_migration_complete() && ActionScheduler_WPCommentCleaner::has_logs() ) {
181
+            ActionScheduler_WPCommentCleaner::init();
182
+        }
183
+
184
+        add_action( 'action_scheduler/migration_complete', 'ActionScheduler_WPCommentCleaner::maybe_schedule_cleanup' );
185
+    }
186
+
187
+    /**
188
+     * Check whether the AS data store has been initialized.
189
+     *
190
+     * @param string $function_name The name of the function being called. Optional. Default `null`.
191
+     * @return bool
192
+     */
193
+    public static function is_initialized( $function_name = null ) {
194
+        if ( ! self::$data_store_initialized && ! empty( $function_name ) ) {
195
+            $message = sprintf( __( '%s() was called before the Action Scheduler data store was initialized', 'woocommerce' ), esc_attr( $function_name ) );
196
+            error_log( $message, E_WARNING );
197
+        }
198
+
199
+        return self::$data_store_initialized;
200
+    }
201
+
202
+    /**
203
+     * Determine if the class is one of our abstract classes.
204
+     *
205
+     * @since 3.0.0
206
+     *
207
+     * @param string $class The class name.
208
+     *
209
+     * @return bool
210
+     */
211
+    protected static function is_class_abstract( $class ) {
212
+        static $abstracts = array(
213
+            'ActionScheduler'                            => true,
214
+            'ActionScheduler_Abstract_ListTable'         => true,
215
+            'ActionScheduler_Abstract_QueueRunner'       => true,
216
+            'ActionScheduler_Abstract_Schedule'          => true,
217
+            'ActionScheduler_Abstract_RecurringSchedule' => true,
218
+            'ActionScheduler_Lock'                       => true,
219
+            'ActionScheduler_Logger'                     => true,
220
+            'ActionScheduler_Abstract_Schema'            => true,
221
+            'ActionScheduler_Store'                      => true,
222
+            'ActionScheduler_TimezoneHelper'             => true,
223
+        );
224
+
225
+        return isset( $abstracts[ $class ] ) && $abstracts[ $class ];
226
+    }
227
+
228
+    /**
229
+     * Determine if the class is one of our migration classes.
230
+     *
231
+     * @since 3.0.0
232
+     *
233
+     * @param string $class The class name.
234
+     *
235
+     * @return bool
236
+     */
237
+    protected static function is_class_migration( $class ) {
238
+        static $migration_segments = array(
239
+            'ActionMigrator'  => true,
240
+            'BatchFetcher'    => true,
241
+            'DBStoreMigrator' => true,
242
+            'DryRun'          => true,
243
+            'LogMigrator'     => true,
244
+            'Config'          => true,
245
+            'Controller'      => true,
246
+            'Runner'          => true,
247
+            'Scheduler'       => true,
248
+        );
249
+
250
+        $segments = explode( '_', $class );
251
+        $segment = isset( $segments[ 1 ] ) ? $segments[ 1 ] : $class;
252
+
253
+        return isset( $migration_segments[ $segment ] ) && $migration_segments[ $segment ];
254
+    }
255
+
256
+    /**
257
+     * Determine if the class is one of our WP CLI classes.
258
+     *
259
+     * @since 3.0.0
260
+     *
261
+     * @param string $class The class name.
262
+     *
263
+     * @return bool
264
+     */
265
+    protected static function is_class_cli( $class ) {
266
+        static $cli_segments = array(
267
+            'QueueRunner' => true,
268
+            'Command'     => true,
269
+            'ProgressBar' => true,
270
+        );
271
+
272
+        $segments = explode( '_', $class );
273
+        $segment = isset( $segments[ 1 ] ) ? $segments[ 1 ] : $class;
274
+
275
+        return isset( $cli_segments[ $segment ] ) && $cli_segments[ $segment ];
276
+    }
277
+
278
+    final public function __clone() {
279
+        trigger_error("Singleton. No cloning allowed!", E_USER_ERROR);
280
+    }
281
+
282
+    final public function __wakeup() {
283
+        trigger_error("Singleton. No serialization allowed!", E_USER_ERROR);
284
+    }
285
+
286
+    final private function __construct() {}
287
+
288
+    /** Deprecated **/
289
+
290
+    public static function get_datetime_object( $when = null, $timezone = 'UTC' ) {
291
+        _deprecated_function( __METHOD__, '2.0', 'wcs_add_months()' );
292
+        return as_get_datetime_object( $when, $timezone );
293
+    }
294
+
295
+    /**
296
+     * Issue deprecated warning if an Action Scheduler function is called in the shutdown hook.
297
+     *
298
+     * @param string $function_name The name of the function being called.
299
+     * @deprecated 3.1.6.
300
+     */
301
+    public static function check_shutdown_hook( $function_name ) {
302
+        _deprecated_function( __FUNCTION__, '3.1.6' );
303
+    }
304 304
 }
Please login to merge, or discard this patch.
Spacing   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -15,7 +15,7 @@  discard block
 block discarded – undo
15 15
 	private static $data_store_initialized = false;
16 16
 
17 17
 	public static function factory() {
18
-		if ( !isset(self::$factory) ) {
18
+		if (!isset(self::$factory)) {
19 19
 			self::$factory = new ActionScheduler_ActionFactory();
20 20
 		}
21 21
 		return self::$factory;
@@ -47,10 +47,10 @@  discard block
 block discarded – undo
47 47
 	 * @param string $path
48 48
 	 * @return string
49 49
 	 */
50
-	public static function plugin_path( $path ) {
50
+	public static function plugin_path($path) {
51 51
 		$base = dirname(self::$plugin_file);
52
-		if ( $path ) {
53
-			return trailingslashit($base).$path;
52
+		if ($path) {
53
+			return trailingslashit($base) . $path;
54 54
 		} else {
55 55
 			return untrailingslashit($base);
56 56
 		}
@@ -62,38 +62,38 @@  discard block
 block discarded – undo
62 62
 	 * @param string $path
63 63
 	 * @return string
64 64
 	 */
65
-	public static function plugin_url( $path ) {
65
+	public static function plugin_url($path) {
66 66
 		return plugins_url($path, self::$plugin_file);
67 67
 	}
68 68
 
69
-	public static function autoload( $class ) {
69
+	public static function autoload($class) {
70 70
 		$d           = DIRECTORY_SEPARATOR;
71
-		$classes_dir = self::plugin_path( 'classes' . $d );
72
-		$separator   = strrpos( $class, '\\' );
73
-		if ( false !== $separator ) {
74
-			if ( 0 !== strpos( $class, 'Action_Scheduler' ) ) {
71
+		$classes_dir = self::plugin_path('classes' . $d);
72
+		$separator   = strrpos($class, '\\');
73
+		if (false !== $separator) {
74
+			if (0 !== strpos($class, 'Action_Scheduler')) {
75 75
 				return;
76 76
 			}
77
-			$class = substr( $class, $separator + 1 );
77
+			$class = substr($class, $separator + 1);
78 78
 		}
79 79
 
80
-		if ( 'Deprecated' === substr( $class, -10 ) ) {
81
-			$dir = self::plugin_path( 'deprecated' . $d );
82
-		} elseif ( self::is_class_abstract( $class ) ) {
80
+		if ('Deprecated' === substr($class, -10)) {
81
+			$dir = self::plugin_path('deprecated' . $d);
82
+		} elseif (self::is_class_abstract($class)) {
83 83
 			$dir = $classes_dir . 'abstracts' . $d;
84
-		} elseif ( self::is_class_migration( $class ) ) {
84
+		} elseif (self::is_class_migration($class)) {
85 85
 			$dir = $classes_dir . 'migration' . $d;
86
-		} elseif ( 'Schedule' === substr( $class, -8 ) ) {
86
+		} elseif ('Schedule' === substr($class, -8)) {
87 87
 			$dir = $classes_dir . 'schedules' . $d;
88
-		} elseif ( 'Action' === substr( $class, -6 ) ) {
88
+		} elseif ('Action' === substr($class, -6)) {
89 89
 			$dir = $classes_dir . 'actions' . $d;
90
-		} elseif ( 'Schema' === substr( $class, -6 ) ) {
90
+		} elseif ('Schema' === substr($class, -6)) {
91 91
 			$dir = $classes_dir . 'schema' . $d;
92
-		} elseif ( strpos( $class, 'ActionScheduler' ) === 0 ) {
93
-			$segments = explode( '_', $class );
94
-			$type = isset( $segments[ 1 ] ) ? $segments[ 1 ] : '';
92
+		} elseif (strpos($class, 'ActionScheduler') === 0) {
93
+			$segments = explode('_', $class);
94
+			$type = isset($segments[1]) ? $segments[1] : '';
95 95
 
96
-			switch ( $type ) {
96
+			switch ($type) {
97 97
 				case 'WPCLI':
98 98
 					$dir = $classes_dir . 'WP_CLI' . $d;
99 99
 					break;
@@ -108,18 +108,18 @@  discard block
 block discarded – undo
108 108
 					$dir = $classes_dir;
109 109
 					break;
110 110
 			}
111
-		} elseif ( self::is_class_cli( $class ) ) {
111
+		} elseif (self::is_class_cli($class)) {
112 112
 			$dir = $classes_dir . 'WP_CLI' . $d;
113
-		} elseif ( strpos( $class, 'CronExpression' ) === 0 ) {
114
-			$dir = self::plugin_path( 'lib' . $d . 'cron-expression' . $d );
115
-		} elseif ( strpos( $class, 'WP_Async_Request' ) === 0 ) {
116
-			$dir = self::plugin_path( 'lib' . $d );
113
+		} elseif (strpos($class, 'CronExpression') === 0) {
114
+			$dir = self::plugin_path('lib' . $d . 'cron-expression' . $d);
115
+		} elseif (strpos($class, 'WP_Async_Request') === 0) {
116
+			$dir = self::plugin_path('lib' . $d);
117 117
 		} else {
118 118
 			return;
119 119
 		}
120 120
 
121
-		if ( file_exists( $dir . "{$class}.php" ) ) {
122
-			include( $dir . "{$class}.php" );
121
+		if (file_exists($dir . "{$class}.php")) {
122
+			include($dir . "{$class}.php");
123 123
 			return;
124 124
 		}
125 125
 	}
@@ -130,16 +130,16 @@  discard block
 block discarded – undo
130 130
 	 * @static
131 131
 	 * @param string $plugin_file
132 132
 	 */
133
-	public static function init( $plugin_file ) {
133
+	public static function init($plugin_file) {
134 134
 		self::$plugin_file = $plugin_file;
135
-		spl_autoload_register( array( __CLASS__, 'autoload' ) );
135
+		spl_autoload_register(array(__CLASS__, 'autoload'));
136 136
 
137 137
 		/**
138 138
 		 * Fires in the early stages of Action Scheduler init hook.
139 139
 		 */
140
-		do_action( 'action_scheduler_pre_init' );
140
+		do_action('action_scheduler_pre_init');
141 141
 
142
-		require_once( self::plugin_path( 'functions.php' ) );
142
+		require_once(self::plugin_path('functions.php'));
143 143
 		ActionScheduler_DataController::init();
144 144
 
145 145
 		$store      = self::store();
@@ -148,11 +148,11 @@  discard block
 block discarded – undo
148 148
 		$admin_view = self::admin_view();
149 149
 
150 150
 		// Ensure initialization on plugin activation.
151
-		if ( ! did_action( 'init' ) ) {
152
-			add_action( 'init', array( $admin_view, 'init' ), 0, 0 ); // run before $store::init()
153
-			add_action( 'init', array( $store, 'init' ), 1, 0 );
154
-			add_action( 'init', array( $logger, 'init' ), 1, 0 );
155
-			add_action( 'init', array( $runner, 'init' ), 1, 0 );
151
+		if (!did_action('init')) {
152
+			add_action('init', array($admin_view, 'init'), 0, 0); // run before $store::init()
153
+			add_action('init', array($store, 'init'), 1, 0);
154
+			add_action('init', array($logger, 'init'), 1, 0);
155
+			add_action('init', array($runner, 'init'), 1, 0);
156 156
 		} else {
157 157
 			$admin_view->init();
158 158
 			$store->init();
@@ -160,13 +160,13 @@  discard block
 block discarded – undo
160 160
 			$runner->init();
161 161
 		}
162 162
 
163
-		if ( apply_filters( 'action_scheduler_load_deprecated_functions', true ) ) {
164
-			require_once( self::plugin_path( 'deprecated/functions.php' ) );
163
+		if (apply_filters('action_scheduler_load_deprecated_functions', true)) {
164
+			require_once(self::plugin_path('deprecated/functions.php'));
165 165
 		}
166 166
 
167
-		if ( defined( 'WP_CLI' ) && WP_CLI ) {
168
-			WP_CLI::add_command( 'action-scheduler', 'ActionScheduler_WPCLI_Scheduler_command' );
169
-			if ( ! ActionScheduler_DataController::is_migration_complete() && Controller::instance()->allow_migration() ) {
167
+		if (defined('WP_CLI') && WP_CLI) {
168
+			WP_CLI::add_command('action-scheduler', 'ActionScheduler_WPCLI_Scheduler_command');
169
+			if (!ActionScheduler_DataController::is_migration_complete() && Controller::instance()->allow_migration()) {
170 170
 				$command = new Migration_Command();
171 171
 				$command->register();
172 172
 			}
@@ -177,11 +177,11 @@  discard block
 block discarded – undo
177 177
 		/**
178 178
 		 * Handle WP comment cleanup after migration.
179 179
 		 */
180
-		if ( is_a( $logger, 'ActionScheduler_DBLogger' ) && ActionScheduler_DataController::is_migration_complete() && ActionScheduler_WPCommentCleaner::has_logs() ) {
180
+		if (is_a($logger, 'ActionScheduler_DBLogger') && ActionScheduler_DataController::is_migration_complete() && ActionScheduler_WPCommentCleaner::has_logs()) {
181 181
 			ActionScheduler_WPCommentCleaner::init();
182 182
 		}
183 183
 
184
-		add_action( 'action_scheduler/migration_complete', 'ActionScheduler_WPCommentCleaner::maybe_schedule_cleanup' );
184
+		add_action('action_scheduler/migration_complete', 'ActionScheduler_WPCommentCleaner::maybe_schedule_cleanup');
185 185
 	}
186 186
 
187 187
 	/**
@@ -190,10 +190,10 @@  discard block
 block discarded – undo
190 190
 	 * @param string $function_name The name of the function being called. Optional. Default `null`.
191 191
 	 * @return bool
192 192
 	 */
193
-	public static function is_initialized( $function_name = null ) {
194
-		if ( ! self::$data_store_initialized && ! empty( $function_name ) ) {
195
-			$message = sprintf( __( '%s() was called before the Action Scheduler data store was initialized', 'woocommerce' ), esc_attr( $function_name ) );
196
-			error_log( $message, E_WARNING );
193
+	public static function is_initialized($function_name = null) {
194
+		if (!self::$data_store_initialized && !empty($function_name)) {
195
+			$message = sprintf(__('%s() was called before the Action Scheduler data store was initialized', 'woocommerce'), esc_attr($function_name));
196
+			error_log($message, E_WARNING);
197 197
 		}
198 198
 
199 199
 		return self::$data_store_initialized;
@@ -208,7 +208,7 @@  discard block
 block discarded – undo
208 208
 	 *
209 209
 	 * @return bool
210 210
 	 */
211
-	protected static function is_class_abstract( $class ) {
211
+	protected static function is_class_abstract($class) {
212 212
 		static $abstracts = array(
213 213
 			'ActionScheduler'                            => true,
214 214
 			'ActionScheduler_Abstract_ListTable'         => true,
@@ -222,7 +222,7 @@  discard block
 block discarded – undo
222 222
 			'ActionScheduler_TimezoneHelper'             => true,
223 223
 		);
224 224
 
225
-		return isset( $abstracts[ $class ] ) && $abstracts[ $class ];
225
+		return isset($abstracts[$class]) && $abstracts[$class];
226 226
 	}
227 227
 
228 228
 	/**
@@ -234,7 +234,7 @@  discard block
 block discarded – undo
234 234
 	 *
235 235
 	 * @return bool
236 236
 	 */
237
-	protected static function is_class_migration( $class ) {
237
+	protected static function is_class_migration($class) {
238 238
 		static $migration_segments = array(
239 239
 			'ActionMigrator'  => true,
240 240
 			'BatchFetcher'    => true,
@@ -247,10 +247,10 @@  discard block
 block discarded – undo
247 247
 			'Scheduler'       => true,
248 248
 		);
249 249
 
250
-		$segments = explode( '_', $class );
251
-		$segment = isset( $segments[ 1 ] ) ? $segments[ 1 ] : $class;
250
+		$segments = explode('_', $class);
251
+		$segment = isset($segments[1]) ? $segments[1] : $class;
252 252
 
253
-		return isset( $migration_segments[ $segment ] ) && $migration_segments[ $segment ];
253
+		return isset($migration_segments[$segment]) && $migration_segments[$segment];
254 254
 	}
255 255
 
256 256
 	/**
@@ -262,17 +262,17 @@  discard block
 block discarded – undo
262 262
 	 *
263 263
 	 * @return bool
264 264
 	 */
265
-	protected static function is_class_cli( $class ) {
265
+	protected static function is_class_cli($class) {
266 266
 		static $cli_segments = array(
267 267
 			'QueueRunner' => true,
268 268
 			'Command'     => true,
269 269
 			'ProgressBar' => true,
270 270
 		);
271 271
 
272
-		$segments = explode( '_', $class );
273
-		$segment = isset( $segments[ 1 ] ) ? $segments[ 1 ] : $class;
272
+		$segments = explode('_', $class);
273
+		$segment = isset($segments[1]) ? $segments[1] : $class;
274 274
 
275
-		return isset( $cli_segments[ $segment ] ) && $cli_segments[ $segment ];
275
+		return isset($cli_segments[$segment]) && $cli_segments[$segment];
276 276
 	}
277 277
 
278 278
 	final public function __clone() {
@@ -287,9 +287,9 @@  discard block
 block discarded – undo
287 287
 
288 288
 	/** Deprecated **/
289 289
 
290
-	public static function get_datetime_object( $when = null, $timezone = 'UTC' ) {
291
-		_deprecated_function( __METHOD__, '2.0', 'wcs_add_months()' );
292
-		return as_get_datetime_object( $when, $timezone );
290
+	public static function get_datetime_object($when = null, $timezone = 'UTC') {
291
+		_deprecated_function(__METHOD__, '2.0', 'wcs_add_months()');
292
+		return as_get_datetime_object($when, $timezone);
293 293
 	}
294 294
 
295 295
 	/**
@@ -298,7 +298,7 @@  discard block
 block discarded – undo
298 298
 	 * @param string $function_name The name of the function being called.
299 299
 	 * @deprecated 3.1.6.
300 300
 	 */
301
-	public static function check_shutdown_hook( $function_name ) {
302
-		_deprecated_function( __FUNCTION__, '3.1.6' );
301
+	public static function check_shutdown_hook($function_name) {
302
+		_deprecated_function(__FUNCTION__, '3.1.6');
303 303
 	}
304 304
 }
Please login to merge, or discard this patch.
action-scheduler/classes/abstracts/ActionScheduler_Abstract_ListTable.php 2 patches
Indentation   +741 added lines, -741 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if ( ! class_exists( 'WP_List_Table' ) ) {
4
-	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
4
+    require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
5 5
 }
6 6
 
7 7
 /**
@@ -23,744 +23,744 @@  discard block
 block discarded – undo
23 23
  */
24 24
 abstract class ActionScheduler_Abstract_ListTable extends WP_List_Table {
25 25
 
26
-	/**
27
-	 * The table name
28
-	 *
29
-	 * @var string
30
-	 */
31
-	protected $table_name;
32
-
33
-	/**
34
-	 * Package name, used to get options from WP_List_Table::get_items_per_page.
35
-	 *
36
-	 * @var string
37
-	 */
38
-	protected $package;
39
-
40
-	/**
41
-	 * How many items do we render per page?
42
-	 *
43
-	 * @var int
44
-	 */
45
-	protected $items_per_page = 10;
46
-
47
-	/**
48
-	 * Enables search in this table listing. If this array
49
-	 * is empty it means the listing is not searchable.
50
-	 *
51
-	 * @var array
52
-	 */
53
-	protected $search_by = array();
54
-
55
-	/**
56
-	 * Columns to show in the table listing. It is a key => value pair. The
57
-	 * key must much the table column name and the value is the label, which is
58
-	 * automatically translated.
59
-	 *
60
-	 * @var array
61
-	 */
62
-	protected $columns = array();
63
-
64
-	/**
65
-	 * Defines the row-actions. It expects an array where the key
66
-	 * is the column name and the value is an array of actions.
67
-	 *
68
-	 * The array of actions are key => value, where key is the method name
69
-	 * (with the prefix row_action_<key>) and the value is the label
70
-	 * and title.
71
-	 *
72
-	 * @var array
73
-	 */
74
-	protected $row_actions = array();
75
-
76
-	/**
77
-	 * The Primary key of our table
78
-	 *
79
-	 * @var string
80
-	 */
81
-	protected $ID = 'ID';
82
-
83
-	/**
84
-	 * Enables sorting, it expects an array
85
-	 * of columns (the column names are the values)
86
-	 *
87
-	 * @var array
88
-	 */
89
-	protected $sort_by = array();
90
-
91
-	/**
92
-	 * The default sort order
93
-	 *
94
-	 * @var string
95
-	 */
96
-	protected $filter_by = array();
97
-
98
-	/**
99
-	 * The status name => count combinations for this table's items. Used to display status filters.
100
-	 *
101
-	 * @var array
102
-	 */
103
-	protected $status_counts = array();
104
-
105
-	/**
106
-	 * Notices to display when loading the table. Array of arrays of form array( 'class' => {updated|error}, 'message' => 'This is the notice text display.' ).
107
-	 *
108
-	 * @var array
109
-	 */
110
-	protected $admin_notices = array();
111
-
112
-	/**
113
-	 * Localised string displayed in the <h1> element above the able.
114
-	 *
115
-	 * @var string
116
-	 */
117
-	protected $table_header;
118
-
119
-	/**
120
-	 * Enables bulk actions. It must be an array where the key is the action name
121
-	 * and the value is the label (which is translated automatically). It is important
122
-	 * to notice that it will check that the method exists (`bulk_$name`) and will throw
123
-	 * an exception if it does not exists.
124
-	 *
125
-	 * This class will automatically check if the current request has a bulk action, will do the
126
-	 * validations and afterwards will execute the bulk method, with two arguments. The first argument
127
-	 * is the array with primary keys, the second argument is a string with a list of the primary keys,
128
-	 * escaped and ready to use (with `IN`).
129
-	 *
130
-	 * @var array
131
-	 */
132
-	protected $bulk_actions = array();
133
-
134
-	/**
135
-	 * Makes translation easier, it basically just wraps
136
-	 * `_x` with some default (the package name).
137
-	 *
138
-	 * @param string $text The new text to translate.
139
-	 * @param string $context The context of the text.
140
-	 * @return string|void The translated text.
141
-	 *
142
-	 * @deprecated 3.0.0 Use `_x()` instead.
143
-	 */
144
-	protected function translate( $text, $context = '' ) {
145
-		return $text;
146
-	}
147
-
148
-	/**
149
-	 * Reads `$this->bulk_actions` and returns an array that WP_List_Table understands. It
150
-	 * also validates that the bulk method handler exists. It throws an exception because
151
-	 * this is a library meant for developers and missing a bulk method is a development-time error.
152
-	 *
153
-	 * @return array
154
-	 *
155
-	 * @throws RuntimeException Throws RuntimeException when the bulk action does not have a callback method.
156
-	 */
157
-	protected function get_bulk_actions() {
158
-		$actions = array();
159
-
160
-		foreach ( $this->bulk_actions as $action => $label ) {
161
-			if ( ! is_callable( array( $this, 'bulk_' . $action ) ) ) {
162
-				throw new RuntimeException( "The bulk action $action does not have a callback method" );
163
-			}
164
-
165
-			$actions[ $action ] = $label;
166
-		}
167
-
168
-		return $actions;
169
-	}
170
-
171
-	/**
172
-	 * Checks if the current request has a bulk action. If that is the case it will validate and will
173
-	 * execute the bulk method handler. Regardless if the action is valid or not it will redirect to
174
-	 * the previous page removing the current arguments that makes this request a bulk action.
175
-	 */
176
-	protected function process_bulk_action() {
177
-		global $wpdb;
178
-		// Detect when a bulk action is being triggered.
179
-		$action = $this->current_action();
180
-		if ( ! $action ) {
181
-			return;
182
-		}
183
-
184
-		check_admin_referer( 'bulk-' . $this->_args['plural'] );
185
-
186
-		$method = 'bulk_' . $action;
187
-		if ( array_key_exists( $action, $this->bulk_actions ) && is_callable( array( $this, $method ) ) && ! empty( $_GET['ID'] ) && is_array( $_GET['ID'] ) ) {
188
-			$ids_sql = '(' . implode( ',', array_fill( 0, count( $_GET['ID'] ), '%s' ) ) . ')';
189
-			$id      = array_map( 'absint', $_GET['ID'] );
190
-			$this->$method( $id, $wpdb->prepare( $ids_sql, $id ) ); //phpcs:ignore WordPress.DB.PreparedSQL
191
-		}
192
-
193
-		if ( isset( $_SERVER['REQUEST_URI'] ) ) {
194
-			wp_safe_redirect(
195
-				remove_query_arg(
196
-					array( '_wp_http_referer', '_wpnonce', 'ID', 'action', 'action2' ),
197
-					esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) )
198
-				)
199
-			);
200
-			exit;
201
-		}
202
-	}
203
-
204
-	/**
205
-	 * Default code for deleting entries.
206
-	 * validated already by process_bulk_action()
207
-	 *
208
-	 * @param array  $ids ids of the items to delete.
209
-	 * @param string $ids_sql the sql for the ids.
210
-	 * @return void
211
-	 */
212
-	protected function bulk_delete( array $ids, $ids_sql ) {
213
-		$store = ActionScheduler::store();
214
-		foreach ( $ids as $action_id ) {
215
-			$store->delete( $action_id );
216
-		}
217
-	}
218
-
219
-	/**
220
-	 * Prepares the _column_headers property which is used by WP_Table_List at rendering.
221
-	 * It merges the columns and the sortable columns.
222
-	 */
223
-	protected function prepare_column_headers() {
224
-		$this->_column_headers = array(
225
-			$this->get_columns(),
226
-			get_hidden_columns( $this->screen ),
227
-			$this->get_sortable_columns(),
228
-		);
229
-	}
230
-
231
-	/**
232
-	 * Reads $this->sort_by and returns the columns name in a format that WP_Table_List
233
-	 * expects
234
-	 */
235
-	public function get_sortable_columns() {
236
-		$sort_by = array();
237
-		foreach ( $this->sort_by as $column ) {
238
-			$sort_by[ $column ] = array( $column, true );
239
-		}
240
-		return $sort_by;
241
-	}
242
-
243
-	/**
244
-	 * Returns the columns names for rendering. It adds a checkbox for selecting everything
245
-	 * as the first column
246
-	 */
247
-	public function get_columns() {
248
-		$columns = array_merge(
249
-			array( 'cb' => '<input type="checkbox" />' ),
250
-			$this->columns
251
-		);
252
-
253
-		return $columns;
254
-	}
255
-
256
-	/**
257
-	 * Get prepared LIMIT clause for items query
258
-	 *
259
-	 * @global wpdb $wpdb
260
-	 *
261
-	 * @return string Prepared LIMIT clause for items query.
262
-	 */
263
-	protected function get_items_query_limit() {
264
-		global $wpdb;
265
-
266
-		$per_page = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
267
-		return $wpdb->prepare( 'LIMIT %d', $per_page );
268
-	}
269
-
270
-	/**
271
-	 * Returns the number of items to offset/skip for this current view.
272
-	 *
273
-	 * @return int
274
-	 */
275
-	protected function get_items_offset() {
276
-		$per_page     = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
277
-		$current_page = $this->get_pagenum();
278
-		if ( 1 < $current_page ) {
279
-			$offset = $per_page * ( $current_page - 1 );
280
-		} else {
281
-			$offset = 0;
282
-		}
283
-
284
-		return $offset;
285
-	}
286
-
287
-	/**
288
-	 * Get prepared OFFSET clause for items query
289
-	 *
290
-	 * @global wpdb $wpdb
291
-	 *
292
-	 * @return string Prepared OFFSET clause for items query.
293
-	 */
294
-	protected function get_items_query_offset() {
295
-		global $wpdb;
296
-
297
-		return $wpdb->prepare( 'OFFSET %d', $this->get_items_offset() );
298
-	}
299
-
300
-	/**
301
-	 * Prepares the ORDER BY sql statement. It uses `$this->sort_by` to know which
302
-	 * columns are sortable. This requests validates the orderby $_GET parameter is a valid
303
-	 * column and sortable. It will also use order (ASC|DESC) using DESC by default.
304
-	 */
305
-	protected function get_items_query_order() {
306
-		if ( empty( $this->sort_by ) ) {
307
-			return '';
308
-		}
309
-
310
-		$orderby = esc_sql( $this->get_request_orderby() );
311
-		$order   = esc_sql( $this->get_request_order() );
312
-
313
-		return "ORDER BY {$orderby} {$order}";
314
-	}
315
-
316
-	/**
317
-	 * Return the sortable column specified for this request to order the results by, if any.
318
-	 *
319
-	 * @return string
320
-	 */
321
-	protected function get_request_orderby() {
322
-
323
-		$valid_sortable_columns = array_values( $this->sort_by );
324
-
325
-		if ( ! empty( $_GET['orderby'] ) && in_array( $_GET['orderby'], $valid_sortable_columns, true ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
326
-			$orderby = sanitize_text_field( wp_unslash( $_GET['orderby'] ) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
327
-		} else {
328
-			$orderby = $valid_sortable_columns[0];
329
-		}
330
-
331
-		return $orderby;
332
-	}
333
-
334
-	/**
335
-	 * Return the sortable column order specified for this request.
336
-	 *
337
-	 * @return string
338
-	 */
339
-	protected function get_request_order() {
340
-
341
-		if ( ! empty( $_GET['order'] ) && 'desc' === strtolower( sanitize_text_field( wp_unslash( $_GET['order'] ) ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
342
-			$order = 'DESC';
343
-		} else {
344
-			$order = 'ASC';
345
-		}
346
-
347
-		return $order;
348
-	}
349
-
350
-	/**
351
-	 * Return the status filter for this request, if any.
352
-	 *
353
-	 * @return string
354
-	 */
355
-	protected function get_request_status() {
356
-		$status = ( ! empty( $_GET['status'] ) ) ? sanitize_text_field( wp_unslash( $_GET['status'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
357
-		return $status;
358
-	}
359
-
360
-	/**
361
-	 * Return the search filter for this request, if any.
362
-	 *
363
-	 * @return string
364
-	 */
365
-	protected function get_request_search_query() {
366
-		$search_query = ( ! empty( $_GET['s'] ) ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
367
-		return $search_query;
368
-	}
369
-
370
-	/**
371
-	 * Process and return the columns name. This is meant for using with SQL, this means it
372
-	 * always includes the primary key.
373
-	 *
374
-	 * @return array
375
-	 */
376
-	protected function get_table_columns() {
377
-		$columns = array_keys( $this->columns );
378
-		if ( ! in_array( $this->ID, $columns, true ) ) {
379
-			$columns[] = $this->ID;
380
-		}
381
-
382
-		return $columns;
383
-	}
384
-
385
-	/**
386
-	 * Check if the current request is doing a "full text" search. If that is the case
387
-	 * prepares the SQL to search texts using LIKE.
388
-	 *
389
-	 * If the current request does not have any search or if this list table does not support
390
-	 * that feature it will return an empty string.
391
-	 *
392
-	 * @return string
393
-	 */
394
-	protected function get_items_query_search() {
395
-		global $wpdb;
396
-
397
-		if ( empty( $_GET['s'] ) || empty( $this->search_by ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
398
-			return '';
399
-		}
400
-
401
-		$search_string = sanitize_text_field( wp_unslash( $_GET['s'] ) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
402
-
403
-		$filter = array();
404
-		foreach ( $this->search_by as $column ) {
405
-			$wild     = '%';
406
-			$sql_like = $wild . $wpdb->esc_like( $search_string ) . $wild;
407
-			$filter[] = $wpdb->prepare( '`' . $column . '` LIKE %s', $sql_like ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQL.NotPrepared
408
-		}
409
-		return implode( ' OR ', $filter );
410
-	}
411
-
412
-	/**
413
-	 * Prepares the SQL to filter rows by the options defined at `$this->filter_by`. Before trusting
414
-	 * any data sent by the user it validates that it is a valid option.
415
-	 */
416
-	protected function get_items_query_filters() {
417
-		global $wpdb;
418
-
419
-		if ( ! $this->filter_by || empty( $_GET['filter_by'] ) || ! is_array( $_GET['filter_by'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
420
-			return '';
421
-		}
422
-
423
-		$filter = array();
424
-
425
-		foreach ( $this->filter_by as $column => $options ) {
426
-			if ( empty( $_GET['filter_by'][ $column ] ) || empty( $options[ $_GET['filter_by'][ $column ] ] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
427
-				continue;
428
-			}
429
-
430
-			$filter[] = $wpdb->prepare( "`$column` = %s", sanitize_text_field( wp_unslash( $_GET['filter_by'][ $column ] ) ) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
431
-		}
432
-
433
-		return implode( ' AND ', $filter );
434
-
435
-	}
436
-
437
-	/**
438
-	 * Prepares the data to feed WP_Table_List.
439
-	 *
440
-	 * This has the core for selecting, sorting and filting data. To keep the code simple
441
-	 * its logic is split among many methods (get_items_query_*).
442
-	 *
443
-	 * Beside populating the items this function will also count all the records that matches
444
-	 * the filtering criteria and will do fill the pagination variables.
445
-	 */
446
-	public function prepare_items() {
447
-		global $wpdb;
448
-
449
-		$this->process_bulk_action();
450
-
451
-		$this->process_row_actions();
452
-
453
-		if ( ! empty( $_REQUEST['_wp_http_referer'] && ! empty( $_SERVER['REQUEST_URI'] ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
454
-			// _wp_http_referer is used only on bulk actions, we remove it to keep the $_GET shorter
455
-			wp_safe_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
456
-			exit;
457
-		}
458
-
459
-		$this->prepare_column_headers();
460
-
461
-		$limit   = $this->get_items_query_limit();
462
-		$offset  = $this->get_items_query_offset();
463
-		$order   = $this->get_items_query_order();
464
-		$where   = array_filter(
465
-			array(
466
-				$this->get_items_query_search(),
467
-				$this->get_items_query_filters(),
468
-			)
469
-		);
470
-		$columns = '`' . implode( '`, `', $this->get_table_columns() ) . '`';
471
-
472
-		if ( ! empty( $where ) ) {
473
-			$where = 'WHERE (' . implode( ') AND (', $where ) . ')';
474
-		} else {
475
-			$where = '';
476
-		}
477
-
478
-		$sql = "SELECT $columns FROM {$this->table_name} {$where} {$order} {$limit} {$offset}";
479
-
480
-		$this->set_items( $wpdb->get_results( $sql, ARRAY_A ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
481
-
482
-		$query_count = "SELECT COUNT({$this->ID}) FROM {$this->table_name} {$where}";
483
-		$total_items = $wpdb->get_var( $query_count ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
484
-		$per_page    = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
485
-		$this->set_pagination_args(
486
-			array(
487
-				'total_items' => $total_items,
488
-				'per_page'    => $per_page,
489
-				'total_pages' => ceil( $total_items / $per_page ),
490
-			)
491
-		);
492
-	}
493
-
494
-	/**
495
-	 * Display the table.
496
-	 *
497
-	 * @param string $which The name of the table.
498
-	 */
499
-	public function extra_tablenav( $which ) {
500
-		if ( ! $this->filter_by || 'top' !== $which ) {
501
-			return;
502
-		}
503
-
504
-		echo '<div class="alignleft actions">';
505
-
506
-		foreach ( $this->filter_by as $id => $options ) {
507
-			$default = ! empty( $_GET['filter_by'][ $id ] ) ? sanitize_text_field( wp_unslash( $_GET['filter_by'][ $id ] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
508
-			if ( empty( $options[ $default ] ) ) {
509
-				$default = '';
510
-			}
511
-
512
-			echo '<select name="filter_by[' . esc_attr( $id ) . ']" class="first" id="filter-by-' . esc_attr( $id ) . '">';
513
-
514
-			foreach ( $options as $value => $label ) {
515
-				echo '<option value="' . esc_attr( $value ) . '" ' . esc_html( $value === $default ? 'selected' : '' ) . '>'
516
-					. esc_html( $label )
517
-				. '</option>';
518
-			}
519
-
520
-			echo '</select>';
521
-		}
522
-
523
-		submit_button( esc_html__( 'Filter', 'woocommerce' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
524
-		echo '</div>';
525
-	}
526
-
527
-	/**
528
-	 * Set the data for displaying. It will attempt to unserialize (There is a chance that some columns
529
-	 * are serialized). This can be override in child classes for futher data transformation.
530
-	 *
531
-	 * @param array $items Items array.
532
-	 */
533
-	protected function set_items( array $items ) {
534
-		$this->items = array();
535
-		foreach ( $items as $item ) {
536
-			$this->items[ $item[ $this->ID ] ] = array_map( 'maybe_unserialize', $item );
537
-		}
538
-	}
539
-
540
-	/**
541
-	 * Renders the checkbox for each row, this is the first column and it is named ID regardless
542
-	 * of how the primary key is named (to keep the code simpler). The bulk actions will do the proper
543
-	 * name transformation though using `$this->ID`.
544
-	 *
545
-	 * @param array $row The row to render.
546
-	 */
547
-	public function column_cb( $row ) {
548
-		return '<input name="ID[]" type="checkbox" value="' . esc_attr( $row[ $this->ID ] ) . '" />';
549
-	}
550
-
551
-	/**
552
-	 * Renders the row-actions.
553
-	 *
554
-	 * This method renders the action menu, it reads the definition from the $row_actions property,
555
-	 * and it checks that the row action method exists before rendering it.
556
-	 *
557
-	 * @param array  $row Row to be rendered.
558
-	 * @param string $column_name Column name.
559
-	 * @return string
560
-	 */
561
-	protected function maybe_render_actions( $row, $column_name ) {
562
-		if ( empty( $this->row_actions[ $column_name ] ) ) {
563
-			return;
564
-		}
565
-
566
-		$row_id = $row[ $this->ID ];
567
-
568
-		$actions      = '<div class="row-actions">';
569
-		$action_count = 0;
570
-		foreach ( $this->row_actions[ $column_name ] as $action_key => $action ) {
571
-
572
-			$action_count++;
573
-
574
-			if ( ! method_exists( $this, 'row_action_' . $action_key ) ) {
575
-				continue;
576
-			}
577
-
578
-			$action_link = ! empty( $action['link'] ) ? $action['link'] : add_query_arg(
579
-				array(
580
-					'row_action' => $action_key,
581
-					'row_id'     => $row_id,
582
-					'nonce'      => wp_create_nonce( $action_key . '::' . $row_id ),
583
-				)
584
-			);
585
-			$span_class  = ! empty( $action['class'] ) ? $action['class'] : $action_key;
586
-			$separator   = ( $action_count < count( $this->row_actions[ $column_name ] ) ) ? ' | ' : '';
587
-
588
-			$actions .= sprintf( '<span class="%s">', esc_attr( $span_class ) );
589
-			$actions .= sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', esc_url( $action_link ), esc_attr( $action['desc'] ), esc_html( $action['name'] ) );
590
-			$actions .= sprintf( '%s</span>', $separator );
591
-		}
592
-		$actions .= '</div>';
593
-		return $actions;
594
-	}
595
-
596
-	/**
597
-	 * Process the bulk actions.
598
-	 *
599
-	 * @return void
600
-	 */
601
-	protected function process_row_actions() {
602
-		$parameters = array( 'row_action', 'row_id', 'nonce' );
603
-		foreach ( $parameters as $parameter ) {
604
-			if ( empty( $_REQUEST[ $parameter ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
605
-				return;
606
-			}
607
-		}
608
-
609
-		$action = sanitize_text_field( wp_unslash( $_REQUEST['row_action'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
610
-		$row_id = sanitize_text_field( wp_unslash( $_REQUEST['row_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
611
-		$nonce  = sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
612
-		$method = 'row_action_' . $action; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
613
-
614
-		if ( wp_verify_nonce( $nonce, $action . '::' . $row_id ) && method_exists( $this, $method ) ) {
615
-			$this->$method( sanitize_text_field( wp_unslash( $row_id ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
616
-		}
617
-
618
-		if ( isset( $_SERVER['REQUEST_URI'] ) ) {
619
-			wp_safe_redirect(
620
-				remove_query_arg(
621
-					array( 'row_id', 'row_action', 'nonce' ),
622
-					esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) )
623
-				)
624
-			);
625
-			exit;
626
-		}
627
-	}
628
-
629
-	/**
630
-	 * Default column formatting, it will escape everythig for security.
631
-	 *
632
-	 * @param array  $item The item array.
633
-	 * @param string $column_name Column name to display.
634
-	 *
635
-	 * @return string
636
-	 */
637
-	public function column_default( $item, $column_name ) {
638
-		$column_html  = esc_html( $item[ $column_name ] );
639
-		$column_html .= $this->maybe_render_actions( $item, $column_name );
640
-		return $column_html;
641
-	}
642
-
643
-	/**
644
-	 * Display the table heading and search query, if any
645
-	 */
646
-	protected function display_header() {
647
-		echo '<h1 class="wp-heading-inline">' . esc_attr( $this->table_header ) . '</h1>';
648
-		if ( $this->get_request_search_query() ) {
649
-			/* translators: %s: search query */
650
-			echo '<span class="subtitle">' . esc_attr( sprintf( __( 'Search results for "%s"', 'woocommerce' ), $this->get_request_search_query() ) ) . '</span>';
651
-		}
652
-		echo '<hr class="wp-header-end">';
653
-	}
654
-
655
-	/**
656
-	 * Display the table heading and search query, if any
657
-	 */
658
-	protected function display_admin_notices() {
659
-		foreach ( $this->admin_notices as $notice ) {
660
-			echo '<div id="message" class="' . esc_attr( $notice['class'] ) . '">';
661
-			echo '	<p>' . wp_kses_post( $notice['message'] ) . '</p>';
662
-			echo '</div>';
663
-		}
664
-	}
665
-
666
-	/**
667
-	 * Prints the available statuses so the user can click to filter.
668
-	 */
669
-	protected function display_filter_by_status() {
670
-
671
-		$status_list_items = array();
672
-		$request_status    = $this->get_request_status();
673
-
674
-		// Helper to set 'all' filter when not set on status counts passed in.
675
-		if ( ! isset( $this->status_counts['all'] ) ) {
676
-			$this->status_counts = array( 'all' => array_sum( $this->status_counts ) ) + $this->status_counts;
677
-		}
678
-
679
-		foreach ( $this->status_counts as $status_name => $count ) {
680
-
681
-			if ( 0 === $count ) {
682
-				continue;
683
-			}
684
-
685
-			if ( $status_name === $request_status || ( empty( $request_status ) && 'all' === $status_name ) ) {
686
-				$status_list_item = '<li class="%1$s"><strong>%3$s</strong> (%4$d)</li>';
687
-			} else {
688
-				$status_list_item = '<li class="%1$s"><a href="%2$s">%3$s</a> (%4$d)</li>';
689
-			}
690
-
691
-			$status_filter_url   = ( 'all' === $status_name ) ? remove_query_arg( 'status' ) : add_query_arg( 'status', $status_name );
692
-			$status_filter_url   = remove_query_arg( array( 'paged', 's' ), $status_filter_url );
693
-			$status_list_items[] = sprintf( $status_list_item, esc_attr( $status_name ), esc_url( $status_filter_url ), esc_html( ucfirst( $status_name ) ), absint( $count ) );
694
-		}
695
-
696
-		if ( $status_list_items ) {
697
-			echo '<ul class="subsubsub">';
698
-			echo implode( " | \n", $status_list_items ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
699
-			echo '</ul>';
700
-		}
701
-	}
702
-
703
-	/**
704
-	 * Renders the table list, we override the original class to render the table inside a form
705
-	 * and to render any needed HTML (like the search box). By doing so the callee of a function can simple
706
-	 * forget about any extra HTML.
707
-	 */
708
-	protected function display_table() {
709
-		echo '<form id="' . esc_attr( $this->_args['plural'] ) . '-filter" method="get">';
710
-		foreach ( $_GET as $key => $value ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
711
-			if ( '_' === $key[0] || 'paged' === $key || 'ID' === $key ) {
712
-				continue;
713
-			}
714
-			echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '" />';
715
-		}
716
-		if ( ! empty( $this->search_by ) ) {
717
-			echo $this->search_box( $this->get_search_box_button_text(), 'plugin' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
718
-		}
719
-		parent::display();
720
-		echo '</form>';
721
-	}
722
-
723
-	/**
724
-	 * Process any pending actions.
725
-	 */
726
-	public function process_actions() {
727
-		$this->process_bulk_action();
728
-		$this->process_row_actions();
729
-
730
-		if ( ! empty( $_REQUEST['_wp_http_referer'] ) && ! empty( $_SERVER['REQUEST_URI'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
731
-			// _wp_http_referer is used only on bulk actions, we remove it to keep the $_GET shorter
732
-			wp_safe_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
733
-			exit;
734
-		}
735
-	}
736
-
737
-	/**
738
-	 * Render the list table page, including header, notices, status filters and table.
739
-	 */
740
-	public function display_page() {
741
-		$this->prepare_items();
742
-
743
-		echo '<div class="wrap">';
744
-		$this->display_header();
745
-		$this->display_admin_notices();
746
-		$this->display_filter_by_status();
747
-		$this->display_table();
748
-		echo '</div>';
749
-	}
750
-
751
-	/**
752
-	 * Get the text to display in the search box on the list table.
753
-	 */
754
-	protected function get_search_box_placeholder() {
755
-		return esc_html__( 'Search', 'woocommerce' );
756
-	}
757
-
758
-	/**
759
-	 * Gets the screen per_page option name.
760
-	 *
761
-	 * @return string
762
-	 */
763
-	protected function get_per_page_option_name() {
764
-		return $this->package . '_items_per_page';
765
-	}
26
+    /**
27
+     * The table name
28
+     *
29
+     * @var string
30
+     */
31
+    protected $table_name;
32
+
33
+    /**
34
+     * Package name, used to get options from WP_List_Table::get_items_per_page.
35
+     *
36
+     * @var string
37
+     */
38
+    protected $package;
39
+
40
+    /**
41
+     * How many items do we render per page?
42
+     *
43
+     * @var int
44
+     */
45
+    protected $items_per_page = 10;
46
+
47
+    /**
48
+     * Enables search in this table listing. If this array
49
+     * is empty it means the listing is not searchable.
50
+     *
51
+     * @var array
52
+     */
53
+    protected $search_by = array();
54
+
55
+    /**
56
+     * Columns to show in the table listing. It is a key => value pair. The
57
+     * key must much the table column name and the value is the label, which is
58
+     * automatically translated.
59
+     *
60
+     * @var array
61
+     */
62
+    protected $columns = array();
63
+
64
+    /**
65
+     * Defines the row-actions. It expects an array where the key
66
+     * is the column name and the value is an array of actions.
67
+     *
68
+     * The array of actions are key => value, where key is the method name
69
+     * (with the prefix row_action_<key>) and the value is the label
70
+     * and title.
71
+     *
72
+     * @var array
73
+     */
74
+    protected $row_actions = array();
75
+
76
+    /**
77
+     * The Primary key of our table
78
+     *
79
+     * @var string
80
+     */
81
+    protected $ID = 'ID';
82
+
83
+    /**
84
+     * Enables sorting, it expects an array
85
+     * of columns (the column names are the values)
86
+     *
87
+     * @var array
88
+     */
89
+    protected $sort_by = array();
90
+
91
+    /**
92
+     * The default sort order
93
+     *
94
+     * @var string
95
+     */
96
+    protected $filter_by = array();
97
+
98
+    /**
99
+     * The status name => count combinations for this table's items. Used to display status filters.
100
+     *
101
+     * @var array
102
+     */
103
+    protected $status_counts = array();
104
+
105
+    /**
106
+     * Notices to display when loading the table. Array of arrays of form array( 'class' => {updated|error}, 'message' => 'This is the notice text display.' ).
107
+     *
108
+     * @var array
109
+     */
110
+    protected $admin_notices = array();
111
+
112
+    /**
113
+     * Localised string displayed in the <h1> element above the able.
114
+     *
115
+     * @var string
116
+     */
117
+    protected $table_header;
118
+
119
+    /**
120
+     * Enables bulk actions. It must be an array where the key is the action name
121
+     * and the value is the label (which is translated automatically). It is important
122
+     * to notice that it will check that the method exists (`bulk_$name`) and will throw
123
+     * an exception if it does not exists.
124
+     *
125
+     * This class will automatically check if the current request has a bulk action, will do the
126
+     * validations and afterwards will execute the bulk method, with two arguments. The first argument
127
+     * is the array with primary keys, the second argument is a string with a list of the primary keys,
128
+     * escaped and ready to use (with `IN`).
129
+     *
130
+     * @var array
131
+     */
132
+    protected $bulk_actions = array();
133
+
134
+    /**
135
+     * Makes translation easier, it basically just wraps
136
+     * `_x` with some default (the package name).
137
+     *
138
+     * @param string $text The new text to translate.
139
+     * @param string $context The context of the text.
140
+     * @return string|void The translated text.
141
+     *
142
+     * @deprecated 3.0.0 Use `_x()` instead.
143
+     */
144
+    protected function translate( $text, $context = '' ) {
145
+        return $text;
146
+    }
147
+
148
+    /**
149
+     * Reads `$this->bulk_actions` and returns an array that WP_List_Table understands. It
150
+     * also validates that the bulk method handler exists. It throws an exception because
151
+     * this is a library meant for developers and missing a bulk method is a development-time error.
152
+     *
153
+     * @return array
154
+     *
155
+     * @throws RuntimeException Throws RuntimeException when the bulk action does not have a callback method.
156
+     */
157
+    protected function get_bulk_actions() {
158
+        $actions = array();
159
+
160
+        foreach ( $this->bulk_actions as $action => $label ) {
161
+            if ( ! is_callable( array( $this, 'bulk_' . $action ) ) ) {
162
+                throw new RuntimeException( "The bulk action $action does not have a callback method" );
163
+            }
164
+
165
+            $actions[ $action ] = $label;
166
+        }
167
+
168
+        return $actions;
169
+    }
170
+
171
+    /**
172
+     * Checks if the current request has a bulk action. If that is the case it will validate and will
173
+     * execute the bulk method handler. Regardless if the action is valid or not it will redirect to
174
+     * the previous page removing the current arguments that makes this request a bulk action.
175
+     */
176
+    protected function process_bulk_action() {
177
+        global $wpdb;
178
+        // Detect when a bulk action is being triggered.
179
+        $action = $this->current_action();
180
+        if ( ! $action ) {
181
+            return;
182
+        }
183
+
184
+        check_admin_referer( 'bulk-' . $this->_args['plural'] );
185
+
186
+        $method = 'bulk_' . $action;
187
+        if ( array_key_exists( $action, $this->bulk_actions ) && is_callable( array( $this, $method ) ) && ! empty( $_GET['ID'] ) && is_array( $_GET['ID'] ) ) {
188
+            $ids_sql = '(' . implode( ',', array_fill( 0, count( $_GET['ID'] ), '%s' ) ) . ')';
189
+            $id      = array_map( 'absint', $_GET['ID'] );
190
+            $this->$method( $id, $wpdb->prepare( $ids_sql, $id ) ); //phpcs:ignore WordPress.DB.PreparedSQL
191
+        }
192
+
193
+        if ( isset( $_SERVER['REQUEST_URI'] ) ) {
194
+            wp_safe_redirect(
195
+                remove_query_arg(
196
+                    array( '_wp_http_referer', '_wpnonce', 'ID', 'action', 'action2' ),
197
+                    esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) )
198
+                )
199
+            );
200
+            exit;
201
+        }
202
+    }
203
+
204
+    /**
205
+     * Default code for deleting entries.
206
+     * validated already by process_bulk_action()
207
+     *
208
+     * @param array  $ids ids of the items to delete.
209
+     * @param string $ids_sql the sql for the ids.
210
+     * @return void
211
+     */
212
+    protected function bulk_delete( array $ids, $ids_sql ) {
213
+        $store = ActionScheduler::store();
214
+        foreach ( $ids as $action_id ) {
215
+            $store->delete( $action_id );
216
+        }
217
+    }
218
+
219
+    /**
220
+     * Prepares the _column_headers property which is used by WP_Table_List at rendering.
221
+     * It merges the columns and the sortable columns.
222
+     */
223
+    protected function prepare_column_headers() {
224
+        $this->_column_headers = array(
225
+            $this->get_columns(),
226
+            get_hidden_columns( $this->screen ),
227
+            $this->get_sortable_columns(),
228
+        );
229
+    }
230
+
231
+    /**
232
+     * Reads $this->sort_by and returns the columns name in a format that WP_Table_List
233
+     * expects
234
+     */
235
+    public function get_sortable_columns() {
236
+        $sort_by = array();
237
+        foreach ( $this->sort_by as $column ) {
238
+            $sort_by[ $column ] = array( $column, true );
239
+        }
240
+        return $sort_by;
241
+    }
242
+
243
+    /**
244
+     * Returns the columns names for rendering. It adds a checkbox for selecting everything
245
+     * as the first column
246
+     */
247
+    public function get_columns() {
248
+        $columns = array_merge(
249
+            array( 'cb' => '<input type="checkbox" />' ),
250
+            $this->columns
251
+        );
252
+
253
+        return $columns;
254
+    }
255
+
256
+    /**
257
+     * Get prepared LIMIT clause for items query
258
+     *
259
+     * @global wpdb $wpdb
260
+     *
261
+     * @return string Prepared LIMIT clause for items query.
262
+     */
263
+    protected function get_items_query_limit() {
264
+        global $wpdb;
265
+
266
+        $per_page = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
267
+        return $wpdb->prepare( 'LIMIT %d', $per_page );
268
+    }
269
+
270
+    /**
271
+     * Returns the number of items to offset/skip for this current view.
272
+     *
273
+     * @return int
274
+     */
275
+    protected function get_items_offset() {
276
+        $per_page     = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
277
+        $current_page = $this->get_pagenum();
278
+        if ( 1 < $current_page ) {
279
+            $offset = $per_page * ( $current_page - 1 );
280
+        } else {
281
+            $offset = 0;
282
+        }
283
+
284
+        return $offset;
285
+    }
286
+
287
+    /**
288
+     * Get prepared OFFSET clause for items query
289
+     *
290
+     * @global wpdb $wpdb
291
+     *
292
+     * @return string Prepared OFFSET clause for items query.
293
+     */
294
+    protected function get_items_query_offset() {
295
+        global $wpdb;
296
+
297
+        return $wpdb->prepare( 'OFFSET %d', $this->get_items_offset() );
298
+    }
299
+
300
+    /**
301
+     * Prepares the ORDER BY sql statement. It uses `$this->sort_by` to know which
302
+     * columns are sortable. This requests validates the orderby $_GET parameter is a valid
303
+     * column and sortable. It will also use order (ASC|DESC) using DESC by default.
304
+     */
305
+    protected function get_items_query_order() {
306
+        if ( empty( $this->sort_by ) ) {
307
+            return '';
308
+        }
309
+
310
+        $orderby = esc_sql( $this->get_request_orderby() );
311
+        $order   = esc_sql( $this->get_request_order() );
312
+
313
+        return "ORDER BY {$orderby} {$order}";
314
+    }
315
+
316
+    /**
317
+     * Return the sortable column specified for this request to order the results by, if any.
318
+     *
319
+     * @return string
320
+     */
321
+    protected function get_request_orderby() {
322
+
323
+        $valid_sortable_columns = array_values( $this->sort_by );
324
+
325
+        if ( ! empty( $_GET['orderby'] ) && in_array( $_GET['orderby'], $valid_sortable_columns, true ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
326
+            $orderby = sanitize_text_field( wp_unslash( $_GET['orderby'] ) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
327
+        } else {
328
+            $orderby = $valid_sortable_columns[0];
329
+        }
330
+
331
+        return $orderby;
332
+    }
333
+
334
+    /**
335
+     * Return the sortable column order specified for this request.
336
+     *
337
+     * @return string
338
+     */
339
+    protected function get_request_order() {
340
+
341
+        if ( ! empty( $_GET['order'] ) && 'desc' === strtolower( sanitize_text_field( wp_unslash( $_GET['order'] ) ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
342
+            $order = 'DESC';
343
+        } else {
344
+            $order = 'ASC';
345
+        }
346
+
347
+        return $order;
348
+    }
349
+
350
+    /**
351
+     * Return the status filter for this request, if any.
352
+     *
353
+     * @return string
354
+     */
355
+    protected function get_request_status() {
356
+        $status = ( ! empty( $_GET['status'] ) ) ? sanitize_text_field( wp_unslash( $_GET['status'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
357
+        return $status;
358
+    }
359
+
360
+    /**
361
+     * Return the search filter for this request, if any.
362
+     *
363
+     * @return string
364
+     */
365
+    protected function get_request_search_query() {
366
+        $search_query = ( ! empty( $_GET['s'] ) ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
367
+        return $search_query;
368
+    }
369
+
370
+    /**
371
+     * Process and return the columns name. This is meant for using with SQL, this means it
372
+     * always includes the primary key.
373
+     *
374
+     * @return array
375
+     */
376
+    protected function get_table_columns() {
377
+        $columns = array_keys( $this->columns );
378
+        if ( ! in_array( $this->ID, $columns, true ) ) {
379
+            $columns[] = $this->ID;
380
+        }
381
+
382
+        return $columns;
383
+    }
384
+
385
+    /**
386
+     * Check if the current request is doing a "full text" search. If that is the case
387
+     * prepares the SQL to search texts using LIKE.
388
+     *
389
+     * If the current request does not have any search or if this list table does not support
390
+     * that feature it will return an empty string.
391
+     *
392
+     * @return string
393
+     */
394
+    protected function get_items_query_search() {
395
+        global $wpdb;
396
+
397
+        if ( empty( $_GET['s'] ) || empty( $this->search_by ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
398
+            return '';
399
+        }
400
+
401
+        $search_string = sanitize_text_field( wp_unslash( $_GET['s'] ) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
402
+
403
+        $filter = array();
404
+        foreach ( $this->search_by as $column ) {
405
+            $wild     = '%';
406
+            $sql_like = $wild . $wpdb->esc_like( $search_string ) . $wild;
407
+            $filter[] = $wpdb->prepare( '`' . $column . '` LIKE %s', $sql_like ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQL.NotPrepared
408
+        }
409
+        return implode( ' OR ', $filter );
410
+    }
411
+
412
+    /**
413
+     * Prepares the SQL to filter rows by the options defined at `$this->filter_by`. Before trusting
414
+     * any data sent by the user it validates that it is a valid option.
415
+     */
416
+    protected function get_items_query_filters() {
417
+        global $wpdb;
418
+
419
+        if ( ! $this->filter_by || empty( $_GET['filter_by'] ) || ! is_array( $_GET['filter_by'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
420
+            return '';
421
+        }
422
+
423
+        $filter = array();
424
+
425
+        foreach ( $this->filter_by as $column => $options ) {
426
+            if ( empty( $_GET['filter_by'][ $column ] ) || empty( $options[ $_GET['filter_by'][ $column ] ] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
427
+                continue;
428
+            }
429
+
430
+            $filter[] = $wpdb->prepare( "`$column` = %s", sanitize_text_field( wp_unslash( $_GET['filter_by'][ $column ] ) ) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
431
+        }
432
+
433
+        return implode( ' AND ', $filter );
434
+
435
+    }
436
+
437
+    /**
438
+     * Prepares the data to feed WP_Table_List.
439
+     *
440
+     * This has the core for selecting, sorting and filting data. To keep the code simple
441
+     * its logic is split among many methods (get_items_query_*).
442
+     *
443
+     * Beside populating the items this function will also count all the records that matches
444
+     * the filtering criteria and will do fill the pagination variables.
445
+     */
446
+    public function prepare_items() {
447
+        global $wpdb;
448
+
449
+        $this->process_bulk_action();
450
+
451
+        $this->process_row_actions();
452
+
453
+        if ( ! empty( $_REQUEST['_wp_http_referer'] && ! empty( $_SERVER['REQUEST_URI'] ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
454
+            // _wp_http_referer is used only on bulk actions, we remove it to keep the $_GET shorter
455
+            wp_safe_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
456
+            exit;
457
+        }
458
+
459
+        $this->prepare_column_headers();
460
+
461
+        $limit   = $this->get_items_query_limit();
462
+        $offset  = $this->get_items_query_offset();
463
+        $order   = $this->get_items_query_order();
464
+        $where   = array_filter(
465
+            array(
466
+                $this->get_items_query_search(),
467
+                $this->get_items_query_filters(),
468
+            )
469
+        );
470
+        $columns = '`' . implode( '`, `', $this->get_table_columns() ) . '`';
471
+
472
+        if ( ! empty( $where ) ) {
473
+            $where = 'WHERE (' . implode( ') AND (', $where ) . ')';
474
+        } else {
475
+            $where = '';
476
+        }
477
+
478
+        $sql = "SELECT $columns FROM {$this->table_name} {$where} {$order} {$limit} {$offset}";
479
+
480
+        $this->set_items( $wpdb->get_results( $sql, ARRAY_A ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
481
+
482
+        $query_count = "SELECT COUNT({$this->ID}) FROM {$this->table_name} {$where}";
483
+        $total_items = $wpdb->get_var( $query_count ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
484
+        $per_page    = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
485
+        $this->set_pagination_args(
486
+            array(
487
+                'total_items' => $total_items,
488
+                'per_page'    => $per_page,
489
+                'total_pages' => ceil( $total_items / $per_page ),
490
+            )
491
+        );
492
+    }
493
+
494
+    /**
495
+     * Display the table.
496
+     *
497
+     * @param string $which The name of the table.
498
+     */
499
+    public function extra_tablenav( $which ) {
500
+        if ( ! $this->filter_by || 'top' !== $which ) {
501
+            return;
502
+        }
503
+
504
+        echo '<div class="alignleft actions">';
505
+
506
+        foreach ( $this->filter_by as $id => $options ) {
507
+            $default = ! empty( $_GET['filter_by'][ $id ] ) ? sanitize_text_field( wp_unslash( $_GET['filter_by'][ $id ] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
508
+            if ( empty( $options[ $default ] ) ) {
509
+                $default = '';
510
+            }
511
+
512
+            echo '<select name="filter_by[' . esc_attr( $id ) . ']" class="first" id="filter-by-' . esc_attr( $id ) . '">';
513
+
514
+            foreach ( $options as $value => $label ) {
515
+                echo '<option value="' . esc_attr( $value ) . '" ' . esc_html( $value === $default ? 'selected' : '' ) . '>'
516
+                    . esc_html( $label )
517
+                . '</option>';
518
+            }
519
+
520
+            echo '</select>';
521
+        }
522
+
523
+        submit_button( esc_html__( 'Filter', 'woocommerce' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
524
+        echo '</div>';
525
+    }
526
+
527
+    /**
528
+     * Set the data for displaying. It will attempt to unserialize (There is a chance that some columns
529
+     * are serialized). This can be override in child classes for futher data transformation.
530
+     *
531
+     * @param array $items Items array.
532
+     */
533
+    protected function set_items( array $items ) {
534
+        $this->items = array();
535
+        foreach ( $items as $item ) {
536
+            $this->items[ $item[ $this->ID ] ] = array_map( 'maybe_unserialize', $item );
537
+        }
538
+    }
539
+
540
+    /**
541
+     * Renders the checkbox for each row, this is the first column and it is named ID regardless
542
+     * of how the primary key is named (to keep the code simpler). The bulk actions will do the proper
543
+     * name transformation though using `$this->ID`.
544
+     *
545
+     * @param array $row The row to render.
546
+     */
547
+    public function column_cb( $row ) {
548
+        return '<input name="ID[]" type="checkbox" value="' . esc_attr( $row[ $this->ID ] ) . '" />';
549
+    }
550
+
551
+    /**
552
+     * Renders the row-actions.
553
+     *
554
+     * This method renders the action menu, it reads the definition from the $row_actions property,
555
+     * and it checks that the row action method exists before rendering it.
556
+     *
557
+     * @param array  $row Row to be rendered.
558
+     * @param string $column_name Column name.
559
+     * @return string
560
+     */
561
+    protected function maybe_render_actions( $row, $column_name ) {
562
+        if ( empty( $this->row_actions[ $column_name ] ) ) {
563
+            return;
564
+        }
565
+
566
+        $row_id = $row[ $this->ID ];
567
+
568
+        $actions      = '<div class="row-actions">';
569
+        $action_count = 0;
570
+        foreach ( $this->row_actions[ $column_name ] as $action_key => $action ) {
571
+
572
+            $action_count++;
573
+
574
+            if ( ! method_exists( $this, 'row_action_' . $action_key ) ) {
575
+                continue;
576
+            }
577
+
578
+            $action_link = ! empty( $action['link'] ) ? $action['link'] : add_query_arg(
579
+                array(
580
+                    'row_action' => $action_key,
581
+                    'row_id'     => $row_id,
582
+                    'nonce'      => wp_create_nonce( $action_key . '::' . $row_id ),
583
+                )
584
+            );
585
+            $span_class  = ! empty( $action['class'] ) ? $action['class'] : $action_key;
586
+            $separator   = ( $action_count < count( $this->row_actions[ $column_name ] ) ) ? ' | ' : '';
587
+
588
+            $actions .= sprintf( '<span class="%s">', esc_attr( $span_class ) );
589
+            $actions .= sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', esc_url( $action_link ), esc_attr( $action['desc'] ), esc_html( $action['name'] ) );
590
+            $actions .= sprintf( '%s</span>', $separator );
591
+        }
592
+        $actions .= '</div>';
593
+        return $actions;
594
+    }
595
+
596
+    /**
597
+     * Process the bulk actions.
598
+     *
599
+     * @return void
600
+     */
601
+    protected function process_row_actions() {
602
+        $parameters = array( 'row_action', 'row_id', 'nonce' );
603
+        foreach ( $parameters as $parameter ) {
604
+            if ( empty( $_REQUEST[ $parameter ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
605
+                return;
606
+            }
607
+        }
608
+
609
+        $action = sanitize_text_field( wp_unslash( $_REQUEST['row_action'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
610
+        $row_id = sanitize_text_field( wp_unslash( $_REQUEST['row_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
611
+        $nonce  = sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
612
+        $method = 'row_action_' . $action; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
613
+
614
+        if ( wp_verify_nonce( $nonce, $action . '::' . $row_id ) && method_exists( $this, $method ) ) {
615
+            $this->$method( sanitize_text_field( wp_unslash( $row_id ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
616
+        }
617
+
618
+        if ( isset( $_SERVER['REQUEST_URI'] ) ) {
619
+            wp_safe_redirect(
620
+                remove_query_arg(
621
+                    array( 'row_id', 'row_action', 'nonce' ),
622
+                    esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) )
623
+                )
624
+            );
625
+            exit;
626
+        }
627
+    }
628
+
629
+    /**
630
+     * Default column formatting, it will escape everythig for security.
631
+     *
632
+     * @param array  $item The item array.
633
+     * @param string $column_name Column name to display.
634
+     *
635
+     * @return string
636
+     */
637
+    public function column_default( $item, $column_name ) {
638
+        $column_html  = esc_html( $item[ $column_name ] );
639
+        $column_html .= $this->maybe_render_actions( $item, $column_name );
640
+        return $column_html;
641
+    }
642
+
643
+    /**
644
+     * Display the table heading and search query, if any
645
+     */
646
+    protected function display_header() {
647
+        echo '<h1 class="wp-heading-inline">' . esc_attr( $this->table_header ) . '</h1>';
648
+        if ( $this->get_request_search_query() ) {
649
+            /* translators: %s: search query */
650
+            echo '<span class="subtitle">' . esc_attr( sprintf( __( 'Search results for "%s"', 'woocommerce' ), $this->get_request_search_query() ) ) . '</span>';
651
+        }
652
+        echo '<hr class="wp-header-end">';
653
+    }
654
+
655
+    /**
656
+     * Display the table heading and search query, if any
657
+     */
658
+    protected function display_admin_notices() {
659
+        foreach ( $this->admin_notices as $notice ) {
660
+            echo '<div id="message" class="' . esc_attr( $notice['class'] ) . '">';
661
+            echo '	<p>' . wp_kses_post( $notice['message'] ) . '</p>';
662
+            echo '</div>';
663
+        }
664
+    }
665
+
666
+    /**
667
+     * Prints the available statuses so the user can click to filter.
668
+     */
669
+    protected function display_filter_by_status() {
670
+
671
+        $status_list_items = array();
672
+        $request_status    = $this->get_request_status();
673
+
674
+        // Helper to set 'all' filter when not set on status counts passed in.
675
+        if ( ! isset( $this->status_counts['all'] ) ) {
676
+            $this->status_counts = array( 'all' => array_sum( $this->status_counts ) ) + $this->status_counts;
677
+        }
678
+
679
+        foreach ( $this->status_counts as $status_name => $count ) {
680
+
681
+            if ( 0 === $count ) {
682
+                continue;
683
+            }
684
+
685
+            if ( $status_name === $request_status || ( empty( $request_status ) && 'all' === $status_name ) ) {
686
+                $status_list_item = '<li class="%1$s"><strong>%3$s</strong> (%4$d)</li>';
687
+            } else {
688
+                $status_list_item = '<li class="%1$s"><a href="%2$s">%3$s</a> (%4$d)</li>';
689
+            }
690
+
691
+            $status_filter_url   = ( 'all' === $status_name ) ? remove_query_arg( 'status' ) : add_query_arg( 'status', $status_name );
692
+            $status_filter_url   = remove_query_arg( array( 'paged', 's' ), $status_filter_url );
693
+            $status_list_items[] = sprintf( $status_list_item, esc_attr( $status_name ), esc_url( $status_filter_url ), esc_html( ucfirst( $status_name ) ), absint( $count ) );
694
+        }
695
+
696
+        if ( $status_list_items ) {
697
+            echo '<ul class="subsubsub">';
698
+            echo implode( " | \n", $status_list_items ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
699
+            echo '</ul>';
700
+        }
701
+    }
702
+
703
+    /**
704
+     * Renders the table list, we override the original class to render the table inside a form
705
+     * and to render any needed HTML (like the search box). By doing so the callee of a function can simple
706
+     * forget about any extra HTML.
707
+     */
708
+    protected function display_table() {
709
+        echo '<form id="' . esc_attr( $this->_args['plural'] ) . '-filter" method="get">';
710
+        foreach ( $_GET as $key => $value ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
711
+            if ( '_' === $key[0] || 'paged' === $key || 'ID' === $key ) {
712
+                continue;
713
+            }
714
+            echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '" />';
715
+        }
716
+        if ( ! empty( $this->search_by ) ) {
717
+            echo $this->search_box( $this->get_search_box_button_text(), 'plugin' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
718
+        }
719
+        parent::display();
720
+        echo '</form>';
721
+    }
722
+
723
+    /**
724
+     * Process any pending actions.
725
+     */
726
+    public function process_actions() {
727
+        $this->process_bulk_action();
728
+        $this->process_row_actions();
729
+
730
+        if ( ! empty( $_REQUEST['_wp_http_referer'] ) && ! empty( $_SERVER['REQUEST_URI'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
731
+            // _wp_http_referer is used only on bulk actions, we remove it to keep the $_GET shorter
732
+            wp_safe_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
733
+            exit;
734
+        }
735
+    }
736
+
737
+    /**
738
+     * Render the list table page, including header, notices, status filters and table.
739
+     */
740
+    public function display_page() {
741
+        $this->prepare_items();
742
+
743
+        echo '<div class="wrap">';
744
+        $this->display_header();
745
+        $this->display_admin_notices();
746
+        $this->display_filter_by_status();
747
+        $this->display_table();
748
+        echo '</div>';
749
+    }
750
+
751
+    /**
752
+     * Get the text to display in the search box on the list table.
753
+     */
754
+    protected function get_search_box_placeholder() {
755
+        return esc_html__( 'Search', 'woocommerce' );
756
+    }
757
+
758
+    /**
759
+     * Gets the screen per_page option name.
760
+     *
761
+     * @return string
762
+     */
763
+    protected function get_per_page_option_name() {
764
+        return $this->package . '_items_per_page';
765
+    }
766 766
 }
Please login to merge, or discard this patch.
Spacing   +125 added lines, -125 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3
-if ( ! class_exists( 'WP_List_Table' ) ) {
3
+if (!class_exists('WP_List_Table')) {
4 4
 	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
5 5
 }
6 6
 
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
 	 *
142 142
 	 * @deprecated 3.0.0 Use `_x()` instead.
143 143
 	 */
144
-	protected function translate( $text, $context = '' ) {
144
+	protected function translate($text, $context = '') {
145 145
 		return $text;
146 146
 	}
147 147
 
@@ -157,12 +157,12 @@  discard block
 block discarded – undo
157 157
 	protected function get_bulk_actions() {
158 158
 		$actions = array();
159 159
 
160
-		foreach ( $this->bulk_actions as $action => $label ) {
161
-			if ( ! is_callable( array( $this, 'bulk_' . $action ) ) ) {
162
-				throw new RuntimeException( "The bulk action $action does not have a callback method" );
160
+		foreach ($this->bulk_actions as $action => $label) {
161
+			if (!is_callable(array($this, 'bulk_' . $action))) {
162
+				throw new RuntimeException("The bulk action $action does not have a callback method");
163 163
 			}
164 164
 
165
-			$actions[ $action ] = $label;
165
+			$actions[$action] = $label;
166 166
 		}
167 167
 
168 168
 		return $actions;
@@ -177,24 +177,24 @@  discard block
 block discarded – undo
177 177
 		global $wpdb;
178 178
 		// Detect when a bulk action is being triggered.
179 179
 		$action = $this->current_action();
180
-		if ( ! $action ) {
180
+		if (!$action) {
181 181
 			return;
182 182
 		}
183 183
 
184
-		check_admin_referer( 'bulk-' . $this->_args['plural'] );
184
+		check_admin_referer('bulk-' . $this->_args['plural']);
185 185
 
186 186
 		$method = 'bulk_' . $action;
187
-		if ( array_key_exists( $action, $this->bulk_actions ) && is_callable( array( $this, $method ) ) && ! empty( $_GET['ID'] ) && is_array( $_GET['ID'] ) ) {
188
-			$ids_sql = '(' . implode( ',', array_fill( 0, count( $_GET['ID'] ), '%s' ) ) . ')';
189
-			$id      = array_map( 'absint', $_GET['ID'] );
190
-			$this->$method( $id, $wpdb->prepare( $ids_sql, $id ) ); //phpcs:ignore WordPress.DB.PreparedSQL
187
+		if (array_key_exists($action, $this->bulk_actions) && is_callable(array($this, $method)) && !empty($_GET['ID']) && is_array($_GET['ID'])) {
188
+			$ids_sql = '(' . implode(',', array_fill(0, count($_GET['ID']), '%s')) . ')';
189
+			$id      = array_map('absint', $_GET['ID']);
190
+			$this->$method($id, $wpdb->prepare($ids_sql, $id)); //phpcs:ignore WordPress.DB.PreparedSQL
191 191
 		}
192 192
 
193
-		if ( isset( $_SERVER['REQUEST_URI'] ) ) {
193
+		if (isset($_SERVER['REQUEST_URI'])) {
194 194
 			wp_safe_redirect(
195 195
 				remove_query_arg(
196
-					array( '_wp_http_referer', '_wpnonce', 'ID', 'action', 'action2' ),
197
-					esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) )
196
+					array('_wp_http_referer', '_wpnonce', 'ID', 'action', 'action2'),
197
+					esc_url_raw(wp_unslash($_SERVER['REQUEST_URI']))
198 198
 				)
199 199
 			);
200 200
 			exit;
@@ -209,10 +209,10 @@  discard block
 block discarded – undo
209 209
 	 * @param string $ids_sql the sql for the ids.
210 210
 	 * @return void
211 211
 	 */
212
-	protected function bulk_delete( array $ids, $ids_sql ) {
212
+	protected function bulk_delete(array $ids, $ids_sql) {
213 213
 		$store = ActionScheduler::store();
214
-		foreach ( $ids as $action_id ) {
215
-			$store->delete( $action_id );
214
+		foreach ($ids as $action_id) {
215
+			$store->delete($action_id);
216 216
 		}
217 217
 	}
218 218
 
@@ -223,7 +223,7 @@  discard block
 block discarded – undo
223 223
 	protected function prepare_column_headers() {
224 224
 		$this->_column_headers = array(
225 225
 			$this->get_columns(),
226
-			get_hidden_columns( $this->screen ),
226
+			get_hidden_columns($this->screen),
227 227
 			$this->get_sortable_columns(),
228 228
 		);
229 229
 	}
@@ -234,8 +234,8 @@  discard block
 block discarded – undo
234 234
 	 */
235 235
 	public function get_sortable_columns() {
236 236
 		$sort_by = array();
237
-		foreach ( $this->sort_by as $column ) {
238
-			$sort_by[ $column ] = array( $column, true );
237
+		foreach ($this->sort_by as $column) {
238
+			$sort_by[$column] = array($column, true);
239 239
 		}
240 240
 		return $sort_by;
241 241
 	}
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
 	 */
247 247
 	public function get_columns() {
248 248
 		$columns = array_merge(
249
-			array( 'cb' => '<input type="checkbox" />' ),
249
+			array('cb' => '<input type="checkbox" />'),
250 250
 			$this->columns
251 251
 		);
252 252
 
@@ -263,8 +263,8 @@  discard block
 block discarded – undo
263 263
 	protected function get_items_query_limit() {
264 264
 		global $wpdb;
265 265
 
266
-		$per_page = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
267
-		return $wpdb->prepare( 'LIMIT %d', $per_page );
266
+		$per_page = $this->get_items_per_page($this->get_per_page_option_name(), $this->items_per_page);
267
+		return $wpdb->prepare('LIMIT %d', $per_page);
268 268
 	}
269 269
 
270 270
 	/**
@@ -273,10 +273,10 @@  discard block
 block discarded – undo
273 273
 	 * @return int
274 274
 	 */
275 275
 	protected function get_items_offset() {
276
-		$per_page     = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
276
+		$per_page     = $this->get_items_per_page($this->get_per_page_option_name(), $this->items_per_page);
277 277
 		$current_page = $this->get_pagenum();
278
-		if ( 1 < $current_page ) {
279
-			$offset = $per_page * ( $current_page - 1 );
278
+		if (1 < $current_page) {
279
+			$offset = $per_page * ($current_page - 1);
280 280
 		} else {
281 281
 			$offset = 0;
282 282
 		}
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
 	protected function get_items_query_offset() {
295 295
 		global $wpdb;
296 296
 
297
-		return $wpdb->prepare( 'OFFSET %d', $this->get_items_offset() );
297
+		return $wpdb->prepare('OFFSET %d', $this->get_items_offset());
298 298
 	}
299 299
 
300 300
 	/**
@@ -303,12 +303,12 @@  discard block
 block discarded – undo
303 303
 	 * column and sortable. It will also use order (ASC|DESC) using DESC by default.
304 304
 	 */
305 305
 	protected function get_items_query_order() {
306
-		if ( empty( $this->sort_by ) ) {
306
+		if (empty($this->sort_by)) {
307 307
 			return '';
308 308
 		}
309 309
 
310
-		$orderby = esc_sql( $this->get_request_orderby() );
311
-		$order   = esc_sql( $this->get_request_order() );
310
+		$orderby = esc_sql($this->get_request_orderby());
311
+		$order   = esc_sql($this->get_request_order());
312 312
 
313 313
 		return "ORDER BY {$orderby} {$order}";
314 314
 	}
@@ -320,10 +320,10 @@  discard block
 block discarded – undo
320 320
 	 */
321 321
 	protected function get_request_orderby() {
322 322
 
323
-		$valid_sortable_columns = array_values( $this->sort_by );
323
+		$valid_sortable_columns = array_values($this->sort_by);
324 324
 
325
-		if ( ! empty( $_GET['orderby'] ) && in_array( $_GET['orderby'], $valid_sortable_columns, true ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
326
-			$orderby = sanitize_text_field( wp_unslash( $_GET['orderby'] ) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
325
+		if (!empty($_GET['orderby']) && in_array($_GET['orderby'], $valid_sortable_columns, true)) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
326
+			$orderby = sanitize_text_field(wp_unslash($_GET['orderby'])); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
327 327
 		} else {
328 328
 			$orderby = $valid_sortable_columns[0];
329 329
 		}
@@ -338,7 +338,7 @@  discard block
 block discarded – undo
338 338
 	 */
339 339
 	protected function get_request_order() {
340 340
 
341
-		if ( ! empty( $_GET['order'] ) && 'desc' === strtolower( sanitize_text_field( wp_unslash( $_GET['order'] ) ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
341
+		if (!empty($_GET['order']) && 'desc' === strtolower(sanitize_text_field(wp_unslash($_GET['order'])))) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
342 342
 			$order = 'DESC';
343 343
 		} else {
344 344
 			$order = 'ASC';
@@ -353,7 +353,7 @@  discard block
 block discarded – undo
353 353
 	 * @return string
354 354
 	 */
355 355
 	protected function get_request_status() {
356
-		$status = ( ! empty( $_GET['status'] ) ) ? sanitize_text_field( wp_unslash( $_GET['status'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
356
+		$status = (!empty($_GET['status'])) ? sanitize_text_field(wp_unslash($_GET['status'])) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
357 357
 		return $status;
358 358
 	}
359 359
 
@@ -363,7 +363,7 @@  discard block
 block discarded – undo
363 363
 	 * @return string
364 364
 	 */
365 365
 	protected function get_request_search_query() {
366
-		$search_query = ( ! empty( $_GET['s'] ) ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
366
+		$search_query = (!empty($_GET['s'])) ? sanitize_text_field(wp_unslash($_GET['s'])) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
367 367
 		return $search_query;
368 368
 	}
369 369
 
@@ -374,8 +374,8 @@  discard block
 block discarded – undo
374 374
 	 * @return array
375 375
 	 */
376 376
 	protected function get_table_columns() {
377
-		$columns = array_keys( $this->columns );
378
-		if ( ! in_array( $this->ID, $columns, true ) ) {
377
+		$columns = array_keys($this->columns);
378
+		if (!in_array($this->ID, $columns, true)) {
379 379
 			$columns[] = $this->ID;
380 380
 		}
381 381
 
@@ -394,19 +394,19 @@  discard block
 block discarded – undo
394 394
 	protected function get_items_query_search() {
395 395
 		global $wpdb;
396 396
 
397
-		if ( empty( $_GET['s'] ) || empty( $this->search_by ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
397
+		if (empty($_GET['s']) || empty($this->search_by)) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
398 398
 			return '';
399 399
 		}
400 400
 
401
-		$search_string = sanitize_text_field( wp_unslash( $_GET['s'] ) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
401
+		$search_string = sanitize_text_field(wp_unslash($_GET['s'])); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
402 402
 
403 403
 		$filter = array();
404
-		foreach ( $this->search_by as $column ) {
404
+		foreach ($this->search_by as $column) {
405 405
 			$wild     = '%';
406
-			$sql_like = $wild . $wpdb->esc_like( $search_string ) . $wild;
407
-			$filter[] = $wpdb->prepare( '`' . $column . '` LIKE %s', $sql_like ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQL.NotPrepared
406
+			$sql_like = $wild . $wpdb->esc_like($search_string) . $wild;
407
+			$filter[] = $wpdb->prepare('`' . $column . '` LIKE %s', $sql_like); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQL.NotPrepared
408 408
 		}
409
-		return implode( ' OR ', $filter );
409
+		return implode(' OR ', $filter);
410 410
 	}
411 411
 
412 412
 	/**
@@ -416,21 +416,21 @@  discard block
 block discarded – undo
416 416
 	protected function get_items_query_filters() {
417 417
 		global $wpdb;
418 418
 
419
-		if ( ! $this->filter_by || empty( $_GET['filter_by'] ) || ! is_array( $_GET['filter_by'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
419
+		if (!$this->filter_by || empty($_GET['filter_by']) || !is_array($_GET['filter_by'])) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
420 420
 			return '';
421 421
 		}
422 422
 
423 423
 		$filter = array();
424 424
 
425
-		foreach ( $this->filter_by as $column => $options ) {
426
-			if ( empty( $_GET['filter_by'][ $column ] ) || empty( $options[ $_GET['filter_by'][ $column ] ] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
425
+		foreach ($this->filter_by as $column => $options) {
426
+			if (empty($_GET['filter_by'][$column]) || empty($options[$_GET['filter_by'][$column]])) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
427 427
 				continue;
428 428
 			}
429 429
 
430
-			$filter[] = $wpdb->prepare( "`$column` = %s", sanitize_text_field( wp_unslash( $_GET['filter_by'][ $column ] ) ) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
430
+			$filter[] = $wpdb->prepare("`$column` = %s", sanitize_text_field(wp_unslash($_GET['filter_by'][$column]))); //phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
431 431
 		}
432 432
 
433
-		return implode( ' AND ', $filter );
433
+		return implode(' AND ', $filter);
434 434
 
435 435
 	}
436 436
 
@@ -450,9 +450,9 @@  discard block
 block discarded – undo
450 450
 
451 451
 		$this->process_row_actions();
452 452
 
453
-		if ( ! empty( $_REQUEST['_wp_http_referer'] && ! empty( $_SERVER['REQUEST_URI'] ) ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
453
+		if (!empty($_REQUEST['_wp_http_referer'] && !empty($_SERVER['REQUEST_URI']))) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
454 454
 			// _wp_http_referer is used only on bulk actions, we remove it to keep the $_GET shorter
455
-			wp_safe_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
455
+			wp_safe_redirect(remove_query_arg(array('_wp_http_referer', '_wpnonce'), esc_url_raw(wp_unslash($_SERVER['REQUEST_URI']))));
456 456
 			exit;
457 457
 		}
458 458
 
@@ -467,26 +467,26 @@  discard block
 block discarded – undo
467 467
 				$this->get_items_query_filters(),
468 468
 			)
469 469
 		);
470
-		$columns = '`' . implode( '`, `', $this->get_table_columns() ) . '`';
470
+		$columns = '`' . implode('`, `', $this->get_table_columns()) . '`';
471 471
 
472
-		if ( ! empty( $where ) ) {
473
-			$where = 'WHERE (' . implode( ') AND (', $where ) . ')';
472
+		if (!empty($where)) {
473
+			$where = 'WHERE (' . implode(') AND (', $where) . ')';
474 474
 		} else {
475 475
 			$where = '';
476 476
 		}
477 477
 
478 478
 		$sql = "SELECT $columns FROM {$this->table_name} {$where} {$order} {$limit} {$offset}";
479 479
 
480
-		$this->set_items( $wpdb->get_results( $sql, ARRAY_A ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
480
+		$this->set_items($wpdb->get_results($sql, ARRAY_A)); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
481 481
 
482 482
 		$query_count = "SELECT COUNT({$this->ID}) FROM {$this->table_name} {$where}";
483
-		$total_items = $wpdb->get_var( $query_count ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
484
-		$per_page    = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
483
+		$total_items = $wpdb->get_var($query_count); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
484
+		$per_page    = $this->get_items_per_page($this->get_per_page_option_name(), $this->items_per_page);
485 485
 		$this->set_pagination_args(
486 486
 			array(
487 487
 				'total_items' => $total_items,
488 488
 				'per_page'    => $per_page,
489
-				'total_pages' => ceil( $total_items / $per_page ),
489
+				'total_pages' => ceil($total_items / $per_page),
490 490
 			)
491 491
 		);
492 492
 	}
@@ -496,31 +496,31 @@  discard block
 block discarded – undo
496 496
 	 *
497 497
 	 * @param string $which The name of the table.
498 498
 	 */
499
-	public function extra_tablenav( $which ) {
500
-		if ( ! $this->filter_by || 'top' !== $which ) {
499
+	public function extra_tablenav($which) {
500
+		if (!$this->filter_by || 'top' !== $which) {
501 501
 			return;
502 502
 		}
503 503
 
504 504
 		echo '<div class="alignleft actions">';
505 505
 
506
-		foreach ( $this->filter_by as $id => $options ) {
507
-			$default = ! empty( $_GET['filter_by'][ $id ] ) ? sanitize_text_field( wp_unslash( $_GET['filter_by'][ $id ] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
508
-			if ( empty( $options[ $default ] ) ) {
506
+		foreach ($this->filter_by as $id => $options) {
507
+			$default = !empty($_GET['filter_by'][$id]) ? sanitize_text_field(wp_unslash($_GET['filter_by'][$id])) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
508
+			if (empty($options[$default])) {
509 509
 				$default = '';
510 510
 			}
511 511
 
512
-			echo '<select name="filter_by[' . esc_attr( $id ) . ']" class="first" id="filter-by-' . esc_attr( $id ) . '">';
512
+			echo '<select name="filter_by[' . esc_attr($id) . ']" class="first" id="filter-by-' . esc_attr($id) . '">';
513 513
 
514
-			foreach ( $options as $value => $label ) {
515
-				echo '<option value="' . esc_attr( $value ) . '" ' . esc_html( $value === $default ? 'selected' : '' ) . '>'
516
-					. esc_html( $label )
514
+			foreach ($options as $value => $label) {
515
+				echo '<option value="' . esc_attr($value) . '" ' . esc_html($value === $default ? 'selected' : '') . '>'
516
+					. esc_html($label)
517 517
 				. '</option>';
518 518
 			}
519 519
 
520 520
 			echo '</select>';
521 521
 		}
522 522
 
523
-		submit_button( esc_html__( 'Filter', 'woocommerce' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
523
+		submit_button(esc_html__('Filter', 'woocommerce'), '', 'filter_action', false, array('id' => 'post-query-submit'));
524 524
 		echo '</div>';
525 525
 	}
526 526
 
@@ -530,10 +530,10 @@  discard block
 block discarded – undo
530 530
 	 *
531 531
 	 * @param array $items Items array.
532 532
 	 */
533
-	protected function set_items( array $items ) {
533
+	protected function set_items(array $items) {
534 534
 		$this->items = array();
535
-		foreach ( $items as $item ) {
536
-			$this->items[ $item[ $this->ID ] ] = array_map( 'maybe_unserialize', $item );
535
+		foreach ($items as $item) {
536
+			$this->items[$item[$this->ID]] = array_map('maybe_unserialize', $item);
537 537
 		}
538 538
 	}
539 539
 
@@ -544,8 +544,8 @@  discard block
 block discarded – undo
544 544
 	 *
545 545
 	 * @param array $row The row to render.
546 546
 	 */
547
-	public function column_cb( $row ) {
548
-		return '<input name="ID[]" type="checkbox" value="' . esc_attr( $row[ $this->ID ] ) . '" />';
547
+	public function column_cb($row) {
548
+		return '<input name="ID[]" type="checkbox" value="' . esc_attr($row[$this->ID]) . '" />';
549 549
 	}
550 550
 
551 551
 	/**
@@ -558,36 +558,36 @@  discard block
 block discarded – undo
558 558
 	 * @param string $column_name Column name.
559 559
 	 * @return string
560 560
 	 */
561
-	protected function maybe_render_actions( $row, $column_name ) {
562
-		if ( empty( $this->row_actions[ $column_name ] ) ) {
561
+	protected function maybe_render_actions($row, $column_name) {
562
+		if (empty($this->row_actions[$column_name])) {
563 563
 			return;
564 564
 		}
565 565
 
566
-		$row_id = $row[ $this->ID ];
566
+		$row_id = $row[$this->ID];
567 567
 
568 568
 		$actions      = '<div class="row-actions">';
569 569
 		$action_count = 0;
570
-		foreach ( $this->row_actions[ $column_name ] as $action_key => $action ) {
570
+		foreach ($this->row_actions[$column_name] as $action_key => $action) {
571 571
 
572 572
 			$action_count++;
573 573
 
574
-			if ( ! method_exists( $this, 'row_action_' . $action_key ) ) {
574
+			if (!method_exists($this, 'row_action_' . $action_key)) {
575 575
 				continue;
576 576
 			}
577 577
 
578
-			$action_link = ! empty( $action['link'] ) ? $action['link'] : add_query_arg(
578
+			$action_link = !empty($action['link']) ? $action['link'] : add_query_arg(
579 579
 				array(
580 580
 					'row_action' => $action_key,
581 581
 					'row_id'     => $row_id,
582
-					'nonce'      => wp_create_nonce( $action_key . '::' . $row_id ),
582
+					'nonce'      => wp_create_nonce($action_key . '::' . $row_id),
583 583
 				)
584 584
 			);
585
-			$span_class  = ! empty( $action['class'] ) ? $action['class'] : $action_key;
586
-			$separator   = ( $action_count < count( $this->row_actions[ $column_name ] ) ) ? ' | ' : '';
585
+			$span_class  = !empty($action['class']) ? $action['class'] : $action_key;
586
+			$separator   = ($action_count < count($this->row_actions[$column_name])) ? ' | ' : '';
587 587
 
588
-			$actions .= sprintf( '<span class="%s">', esc_attr( $span_class ) );
589
-			$actions .= sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', esc_url( $action_link ), esc_attr( $action['desc'] ), esc_html( $action['name'] ) );
590
-			$actions .= sprintf( '%s</span>', $separator );
588
+			$actions .= sprintf('<span class="%s">', esc_attr($span_class));
589
+			$actions .= sprintf('<a href="%1$s" title="%2$s">%3$s</a>', esc_url($action_link), esc_attr($action['desc']), esc_html($action['name']));
590
+			$actions .= sprintf('%s</span>', $separator);
591 591
 		}
592 592
 		$actions .= '</div>';
593 593
 		return $actions;
@@ -599,27 +599,27 @@  discard block
 block discarded – undo
599 599
 	 * @return void
600 600
 	 */
601 601
 	protected function process_row_actions() {
602
-		$parameters = array( 'row_action', 'row_id', 'nonce' );
603
-		foreach ( $parameters as $parameter ) {
604
-			if ( empty( $_REQUEST[ $parameter ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
602
+		$parameters = array('row_action', 'row_id', 'nonce');
603
+		foreach ($parameters as $parameter) {
604
+			if (empty($_REQUEST[$parameter])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
605 605
 				return;
606 606
 			}
607 607
 		}
608 608
 
609
-		$action = sanitize_text_field( wp_unslash( $_REQUEST['row_action'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
610
-		$row_id = sanitize_text_field( wp_unslash( $_REQUEST['row_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
611
-		$nonce  = sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
609
+		$action = sanitize_text_field(wp_unslash($_REQUEST['row_action'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
610
+		$row_id = sanitize_text_field(wp_unslash($_REQUEST['row_id'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
611
+		$nonce  = sanitize_text_field(wp_unslash($_REQUEST['nonce'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
612 612
 		$method = 'row_action_' . $action; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
613 613
 
614
-		if ( wp_verify_nonce( $nonce, $action . '::' . $row_id ) && method_exists( $this, $method ) ) {
615
-			$this->$method( sanitize_text_field( wp_unslash( $row_id ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
614
+		if (wp_verify_nonce($nonce, $action . '::' . $row_id) && method_exists($this, $method)) {
615
+			$this->$method(sanitize_text_field(wp_unslash($row_id))); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
616 616
 		}
617 617
 
618
-		if ( isset( $_SERVER['REQUEST_URI'] ) ) {
618
+		if (isset($_SERVER['REQUEST_URI'])) {
619 619
 			wp_safe_redirect(
620 620
 				remove_query_arg(
621
-					array( 'row_id', 'row_action', 'nonce' ),
622
-					esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) )
621
+					array('row_id', 'row_action', 'nonce'),
622
+					esc_url_raw(wp_unslash($_SERVER['REQUEST_URI']))
623 623
 				)
624 624
 			);
625 625
 			exit;
@@ -634,9 +634,9 @@  discard block
 block discarded – undo
634 634
 	 *
635 635
 	 * @return string
636 636
 	 */
637
-	public function column_default( $item, $column_name ) {
638
-		$column_html  = esc_html( $item[ $column_name ] );
639
-		$column_html .= $this->maybe_render_actions( $item, $column_name );
637
+	public function column_default($item, $column_name) {
638
+		$column_html  = esc_html($item[$column_name]);
639
+		$column_html .= $this->maybe_render_actions($item, $column_name);
640 640
 		return $column_html;
641 641
 	}
642 642
 
@@ -644,10 +644,10 @@  discard block
 block discarded – undo
644 644
 	 * Display the table heading and search query, if any
645 645
 	 */
646 646
 	protected function display_header() {
647
-		echo '<h1 class="wp-heading-inline">' . esc_attr( $this->table_header ) . '</h1>';
648
-		if ( $this->get_request_search_query() ) {
647
+		echo '<h1 class="wp-heading-inline">' . esc_attr($this->table_header) . '</h1>';
648
+		if ($this->get_request_search_query()) {
649 649
 			/* translators: %s: search query */
650
-			echo '<span class="subtitle">' . esc_attr( sprintf( __( 'Search results for "%s"', 'woocommerce' ), $this->get_request_search_query() ) ) . '</span>';
650
+			echo '<span class="subtitle">' . esc_attr(sprintf(__('Search results for "%s"', 'woocommerce'), $this->get_request_search_query())) . '</span>';
651 651
 		}
652 652
 		echo '<hr class="wp-header-end">';
653 653
 	}
@@ -656,9 +656,9 @@  discard block
 block discarded – undo
656 656
 	 * Display the table heading and search query, if any
657 657
 	 */
658 658
 	protected function display_admin_notices() {
659
-		foreach ( $this->admin_notices as $notice ) {
660
-			echo '<div id="message" class="' . esc_attr( $notice['class'] ) . '">';
661
-			echo '	<p>' . wp_kses_post( $notice['message'] ) . '</p>';
659
+		foreach ($this->admin_notices as $notice) {
660
+			echo '<div id="message" class="' . esc_attr($notice['class']) . '">';
661
+			echo '	<p>' . wp_kses_post($notice['message']) . '</p>';
662 662
 			echo '</div>';
663 663
 		}
664 664
 	}
@@ -672,30 +672,30 @@  discard block
 block discarded – undo
672 672
 		$request_status    = $this->get_request_status();
673 673
 
674 674
 		// Helper to set 'all' filter when not set on status counts passed in.
675
-		if ( ! isset( $this->status_counts['all'] ) ) {
676
-			$this->status_counts = array( 'all' => array_sum( $this->status_counts ) ) + $this->status_counts;
675
+		if (!isset($this->status_counts['all'])) {
676
+			$this->status_counts = array('all' => array_sum($this->status_counts)) + $this->status_counts;
677 677
 		}
678 678
 
679
-		foreach ( $this->status_counts as $status_name => $count ) {
679
+		foreach ($this->status_counts as $status_name => $count) {
680 680
 
681
-			if ( 0 === $count ) {
681
+			if (0 === $count) {
682 682
 				continue;
683 683
 			}
684 684
 
685
-			if ( $status_name === $request_status || ( empty( $request_status ) && 'all' === $status_name ) ) {
685
+			if ($status_name === $request_status || (empty($request_status) && 'all' === $status_name)) {
686 686
 				$status_list_item = '<li class="%1$s"><strong>%3$s</strong> (%4$d)</li>';
687 687
 			} else {
688 688
 				$status_list_item = '<li class="%1$s"><a href="%2$s">%3$s</a> (%4$d)</li>';
689 689
 			}
690 690
 
691
-			$status_filter_url   = ( 'all' === $status_name ) ? remove_query_arg( 'status' ) : add_query_arg( 'status', $status_name );
692
-			$status_filter_url   = remove_query_arg( array( 'paged', 's' ), $status_filter_url );
693
-			$status_list_items[] = sprintf( $status_list_item, esc_attr( $status_name ), esc_url( $status_filter_url ), esc_html( ucfirst( $status_name ) ), absint( $count ) );
691
+			$status_filter_url   = ('all' === $status_name) ? remove_query_arg('status') : add_query_arg('status', $status_name);
692
+			$status_filter_url   = remove_query_arg(array('paged', 's'), $status_filter_url);
693
+			$status_list_items[] = sprintf($status_list_item, esc_attr($status_name), esc_url($status_filter_url), esc_html(ucfirst($status_name)), absint($count));
694 694
 		}
695 695
 
696
-		if ( $status_list_items ) {
696
+		if ($status_list_items) {
697 697
 			echo '<ul class="subsubsub">';
698
-			echo implode( " | \n", $status_list_items ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
698
+			echo implode(" | \n", $status_list_items); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
699 699
 			echo '</ul>';
700 700
 		}
701 701
 	}
@@ -706,15 +706,15 @@  discard block
 block discarded – undo
706 706
 	 * forget about any extra HTML.
707 707
 	 */
708 708
 	protected function display_table() {
709
-		echo '<form id="' . esc_attr( $this->_args['plural'] ) . '-filter" method="get">';
710
-		foreach ( $_GET as $key => $value ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
711
-			if ( '_' === $key[0] || 'paged' === $key || 'ID' === $key ) {
709
+		echo '<form id="' . esc_attr($this->_args['plural']) . '-filter" method="get">';
710
+		foreach ($_GET as $key => $value) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
711
+			if ('_' === $key[0] || 'paged' === $key || 'ID' === $key) {
712 712
 				continue;
713 713
 			}
714
-			echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '" />';
714
+			echo '<input type="hidden" name="' . esc_attr($key) . '" value="' . esc_attr($value) . '" />';
715 715
 		}
716
-		if ( ! empty( $this->search_by ) ) {
717
-			echo $this->search_box( $this->get_search_box_button_text(), 'plugin' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
716
+		if (!empty($this->search_by)) {
717
+			echo $this->search_box($this->get_search_box_button_text(), 'plugin'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
718 718
 		}
719 719
 		parent::display();
720 720
 		echo '</form>';
@@ -727,9 +727,9 @@  discard block
 block discarded – undo
727 727
 		$this->process_bulk_action();
728 728
 		$this->process_row_actions();
729 729
 
730
-		if ( ! empty( $_REQUEST['_wp_http_referer'] ) && ! empty( $_SERVER['REQUEST_URI'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
730
+		if (!empty($_REQUEST['_wp_http_referer']) && !empty($_SERVER['REQUEST_URI'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
731 731
 			// _wp_http_referer is used only on bulk actions, we remove it to keep the $_GET shorter
732
-			wp_safe_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
732
+			wp_safe_redirect(remove_query_arg(array('_wp_http_referer', '_wpnonce'), esc_url_raw(wp_unslash($_SERVER['REQUEST_URI']))));
733 733
 			exit;
734 734
 		}
735 735
 	}
@@ -752,7 +752,7 @@  discard block
 block discarded – undo
752 752
 	 * Get the text to display in the search box on the list table.
753 753
 	 */
754 754
 	protected function get_search_box_placeholder() {
755
-		return esc_html__( 'Search', 'woocommerce' );
755
+		return esc_html__('Search', 'woocommerce');
756 756
 	}
757 757
 
758 758
 	/**
Please login to merge, or discard this patch.
action-scheduler/classes/abstracts/ActionScheduler_Abstract_Schema.php 2 patches
Indentation   +157 added lines, -157 removed lines patch added patch discarded remove patch
@@ -12,161 +12,161 @@
 block discarded – undo
12 12
  */
13 13
 abstract class ActionScheduler_Abstract_Schema {
14 14
 
15
-	/**
16
-	 * @var int Increment this value in derived class to trigger a schema update.
17
-	 */
18
-	protected $schema_version = 1;
19
-
20
-	/**
21
-	 * @var string Schema version stored in database.
22
-	 */
23
-	protected $db_version;
24
-
25
-	/**
26
-	 * @var array Names of tables that will be registered by this class.
27
-	 */
28
-	protected $tables = [];
29
-
30
-	/**
31
-	 * Can optionally be used by concrete classes to carry out additional initialization work
32
-	 * as needed.
33
-	 */
34
-	public function init() {}
35
-
36
-	/**
37
-	 * Register tables with WordPress, and create them if needed.
38
-	 *
39
-	 * @param bool $force_update Optional. Default false. Use true to always run the schema update.
40
-	 *
41
-	 * @return void
42
-	 */
43
-	public function register_tables( $force_update = false ) {
44
-		global $wpdb;
45
-
46
-		// make WP aware of our tables
47
-		foreach ( $this->tables as $table ) {
48
-			$wpdb->tables[] = $table;
49
-			$name           = $this->get_full_table_name( $table );
50
-			$wpdb->$table   = $name;
51
-		}
52
-
53
-		// create the tables
54
-		if ( $this->schema_update_required() || $force_update ) {
55
-			foreach ( $this->tables as $table ) {
56
-				/**
57
-				 * Allow custom processing before updating a table schema.
58
-				 *
59
-				 * @param string $table Name of table being updated.
60
-				 * @param string $db_version Existing version of the table being updated.
61
-				 */
62
-				do_action( 'action_scheduler_before_schema_update', $table, $this->db_version );
63
-				$this->update_table( $table );
64
-			}
65
-			$this->mark_schema_update_complete();
66
-		}
67
-	}
68
-
69
-	/**
70
-	 * @param string $table The name of the table
71
-	 *
72
-	 * @return string The CREATE TABLE statement, suitable for passing to dbDelta
73
-	 */
74
-	abstract protected function get_table_definition( $table );
75
-
76
-	/**
77
-	 * Determine if the database schema is out of date
78
-	 * by comparing the integer found in $this->schema_version
79
-	 * with the option set in the WordPress options table
80
-	 *
81
-	 * @return bool
82
-	 */
83
-	private function schema_update_required() {
84
-		$option_name      = 'schema-' . static::class;
85
-		$this->db_version = get_option( $option_name, 0 );
86
-
87
-		// Check for schema option stored by the Action Scheduler Custom Tables plugin in case site has migrated from that plugin with an older schema
88
-		if ( 0 === $this->db_version ) {
89
-
90
-			$plugin_option_name = 'schema-';
91
-
92
-			switch ( static::class ) {
93
-				case 'ActionScheduler_StoreSchema' :
94
-					$plugin_option_name .= 'Action_Scheduler\Custom_Tables\DB_Store_Table_Maker';
95
-					break;
96
-				case 'ActionScheduler_LoggerSchema' :
97
-					$plugin_option_name .= 'Action_Scheduler\Custom_Tables\DB_Logger_Table_Maker';
98
-					break;
99
-			}
100
-
101
-			$this->db_version = get_option( $plugin_option_name, 0 );
102
-
103
-			delete_option( $plugin_option_name );
104
-		}
105
-
106
-		return version_compare( $this->db_version, $this->schema_version, '<' );
107
-	}
108
-
109
-	/**
110
-	 * Update the option in WordPress to indicate that
111
-	 * our schema is now up to date
112
-	 *
113
-	 * @return void
114
-	 */
115
-	private function mark_schema_update_complete() {
116
-		$option_name = 'schema-' . static::class;
117
-
118
-		// work around race conditions and ensure that our option updates
119
-		$value_to_save = (string) $this->schema_version . '.0.' . time();
120
-
121
-		update_option( $option_name, $value_to_save );
122
-	}
123
-
124
-	/**
125
-	 * Update the schema for the given table
126
-	 *
127
-	 * @param string $table The name of the table to update
128
-	 *
129
-	 * @return void
130
-	 */
131
-	private function update_table( $table ) {
132
-		require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
133
-		$definition = $this->get_table_definition( $table );
134
-		if ( $definition ) {
135
-			$updated = dbDelta( $definition );
136
-			foreach ( $updated as $updated_table => $update_description ) {
137
-				if ( strpos( $update_description, 'Created table' ) === 0 ) {
138
-					do_action( 'action_scheduler/created_table', $updated_table, $table );
139
-				}
140
-			}
141
-		}
142
-	}
143
-
144
-	/**
145
-	 * @param string $table
146
-	 *
147
-	 * @return string The full name of the table, including the
148
-	 *                table prefix for the current blog
149
-	 */
150
-	protected function get_full_table_name( $table ) {
151
-		return $GLOBALS[ 'wpdb' ]->prefix . $table;
152
-	}
153
-
154
-	/**
155
-	 * Confirms that all of the tables registered by this schema class have been created.
156
-	 *
157
-	 * @return bool
158
-	 */
159
-	public function tables_exist() {
160
-		global $wpdb;
161
-
162
-		$existing_tables = $wpdb->get_col( 'SHOW TABLES' );
163
-		$expected_tables = array_map(
164
-			function ( $table_name ) use ( $wpdb ) {
165
-				return $wpdb->prefix . $table_name;
166
-			},
167
-			$this->tables
168
-		);
169
-
170
-		return count( array_intersect( $existing_tables, $expected_tables ) ) === count( $expected_tables );
171
-	}
15
+    /**
16
+     * @var int Increment this value in derived class to trigger a schema update.
17
+     */
18
+    protected $schema_version = 1;
19
+
20
+    /**
21
+     * @var string Schema version stored in database.
22
+     */
23
+    protected $db_version;
24
+
25
+    /**
26
+     * @var array Names of tables that will be registered by this class.
27
+     */
28
+    protected $tables = [];
29
+
30
+    /**
31
+     * Can optionally be used by concrete classes to carry out additional initialization work
32
+     * as needed.
33
+     */
34
+    public function init() {}
35
+
36
+    /**
37
+     * Register tables with WordPress, and create them if needed.
38
+     *
39
+     * @param bool $force_update Optional. Default false. Use true to always run the schema update.
40
+     *
41
+     * @return void
42
+     */
43
+    public function register_tables( $force_update = false ) {
44
+        global $wpdb;
45
+
46
+        // make WP aware of our tables
47
+        foreach ( $this->tables as $table ) {
48
+            $wpdb->tables[] = $table;
49
+            $name           = $this->get_full_table_name( $table );
50
+            $wpdb->$table   = $name;
51
+        }
52
+
53
+        // create the tables
54
+        if ( $this->schema_update_required() || $force_update ) {
55
+            foreach ( $this->tables as $table ) {
56
+                /**
57
+                 * Allow custom processing before updating a table schema.
58
+                 *
59
+                 * @param string $table Name of table being updated.
60
+                 * @param string $db_version Existing version of the table being updated.
61
+                 */
62
+                do_action( 'action_scheduler_before_schema_update', $table, $this->db_version );
63
+                $this->update_table( $table );
64
+            }
65
+            $this->mark_schema_update_complete();
66
+        }
67
+    }
68
+
69
+    /**
70
+     * @param string $table The name of the table
71
+     *
72
+     * @return string The CREATE TABLE statement, suitable for passing to dbDelta
73
+     */
74
+    abstract protected function get_table_definition( $table );
75
+
76
+    /**
77
+     * Determine if the database schema is out of date
78
+     * by comparing the integer found in $this->schema_version
79
+     * with the option set in the WordPress options table
80
+     *
81
+     * @return bool
82
+     */
83
+    private function schema_update_required() {
84
+        $option_name      = 'schema-' . static::class;
85
+        $this->db_version = get_option( $option_name, 0 );
86
+
87
+        // Check for schema option stored by the Action Scheduler Custom Tables plugin in case site has migrated from that plugin with an older schema
88
+        if ( 0 === $this->db_version ) {
89
+
90
+            $plugin_option_name = 'schema-';
91
+
92
+            switch ( static::class ) {
93
+                case 'ActionScheduler_StoreSchema' :
94
+                    $plugin_option_name .= 'Action_Scheduler\Custom_Tables\DB_Store_Table_Maker';
95
+                    break;
96
+                case 'ActionScheduler_LoggerSchema' :
97
+                    $plugin_option_name .= 'Action_Scheduler\Custom_Tables\DB_Logger_Table_Maker';
98
+                    break;
99
+            }
100
+
101
+            $this->db_version = get_option( $plugin_option_name, 0 );
102
+
103
+            delete_option( $plugin_option_name );
104
+        }
105
+
106
+        return version_compare( $this->db_version, $this->schema_version, '<' );
107
+    }
108
+
109
+    /**
110
+     * Update the option in WordPress to indicate that
111
+     * our schema is now up to date
112
+     *
113
+     * @return void
114
+     */
115
+    private function mark_schema_update_complete() {
116
+        $option_name = 'schema-' . static::class;
117
+
118
+        // work around race conditions and ensure that our option updates
119
+        $value_to_save = (string) $this->schema_version . '.0.' . time();
120
+
121
+        update_option( $option_name, $value_to_save );
122
+    }
123
+
124
+    /**
125
+     * Update the schema for the given table
126
+     *
127
+     * @param string $table The name of the table to update
128
+     *
129
+     * @return void
130
+     */
131
+    private function update_table( $table ) {
132
+        require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
133
+        $definition = $this->get_table_definition( $table );
134
+        if ( $definition ) {
135
+            $updated = dbDelta( $definition );
136
+            foreach ( $updated as $updated_table => $update_description ) {
137
+                if ( strpos( $update_description, 'Created table' ) === 0 ) {
138
+                    do_action( 'action_scheduler/created_table', $updated_table, $table );
139
+                }
140
+            }
141
+        }
142
+    }
143
+
144
+    /**
145
+     * @param string $table
146
+     *
147
+     * @return string The full name of the table, including the
148
+     *                table prefix for the current blog
149
+     */
150
+    protected function get_full_table_name( $table ) {
151
+        return $GLOBALS[ 'wpdb' ]->prefix . $table;
152
+    }
153
+
154
+    /**
155
+     * Confirms that all of the tables registered by this schema class have been created.
156
+     *
157
+     * @return bool
158
+     */
159
+    public function tables_exist() {
160
+        global $wpdb;
161
+
162
+        $existing_tables = $wpdb->get_col( 'SHOW TABLES' );
163
+        $expected_tables = array_map(
164
+            function ( $table_name ) use ( $wpdb ) {
165
+                return $wpdb->prefix . $table_name;
166
+            },
167
+            $this->tables
168
+        );
169
+
170
+        return count( array_intersect( $existing_tables, $expected_tables ) ) === count( $expected_tables );
171
+    }
172 172
 }
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -40,27 +40,27 @@  discard block
 block discarded – undo
40 40
 	 *
41 41
 	 * @return void
42 42
 	 */
43
-	public function register_tables( $force_update = false ) {
43
+	public function register_tables($force_update = false) {
44 44
 		global $wpdb;
45 45
 
46 46
 		// make WP aware of our tables
47
-		foreach ( $this->tables as $table ) {
47
+		foreach ($this->tables as $table) {
48 48
 			$wpdb->tables[] = $table;
49
-			$name           = $this->get_full_table_name( $table );
49
+			$name           = $this->get_full_table_name($table);
50 50
 			$wpdb->$table   = $name;
51 51
 		}
52 52
 
53 53
 		// create the tables
54
-		if ( $this->schema_update_required() || $force_update ) {
55
-			foreach ( $this->tables as $table ) {
54
+		if ($this->schema_update_required() || $force_update) {
55
+			foreach ($this->tables as $table) {
56 56
 				/**
57 57
 				 * Allow custom processing before updating a table schema.
58 58
 				 *
59 59
 				 * @param string $table Name of table being updated.
60 60
 				 * @param string $db_version Existing version of the table being updated.
61 61
 				 */
62
-				do_action( 'action_scheduler_before_schema_update', $table, $this->db_version );
63
-				$this->update_table( $table );
62
+				do_action('action_scheduler_before_schema_update', $table, $this->db_version);
63
+				$this->update_table($table);
64 64
 			}
65 65
 			$this->mark_schema_update_complete();
66 66
 		}
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
 	 *
72 72
 	 * @return string The CREATE TABLE statement, suitable for passing to dbDelta
73 73
 	 */
74
-	abstract protected function get_table_definition( $table );
74
+	abstract protected function get_table_definition($table);
75 75
 
76 76
 	/**
77 77
 	 * Determine if the database schema is out of date
@@ -82,14 +82,14 @@  discard block
 block discarded – undo
82 82
 	 */
83 83
 	private function schema_update_required() {
84 84
 		$option_name      = 'schema-' . static::class;
85
-		$this->db_version = get_option( $option_name, 0 );
85
+		$this->db_version = get_option($option_name, 0);
86 86
 
87 87
 		// Check for schema option stored by the Action Scheduler Custom Tables plugin in case site has migrated from that plugin with an older schema
88
-		if ( 0 === $this->db_version ) {
88
+		if (0 === $this->db_version) {
89 89
 
90 90
 			$plugin_option_name = 'schema-';
91 91
 
92
-			switch ( static::class ) {
92
+			switch (static::class) {
93 93
 				case 'ActionScheduler_StoreSchema' :
94 94
 					$plugin_option_name .= 'Action_Scheduler\Custom_Tables\DB_Store_Table_Maker';
95 95
 					break;
@@ -98,12 +98,12 @@  discard block
 block discarded – undo
98 98
 					break;
99 99
 			}
100 100
 
101
-			$this->db_version = get_option( $plugin_option_name, 0 );
101
+			$this->db_version = get_option($plugin_option_name, 0);
102 102
 
103
-			delete_option( $plugin_option_name );
103
+			delete_option($plugin_option_name);
104 104
 		}
105 105
 
106
-		return version_compare( $this->db_version, $this->schema_version, '<' );
106
+		return version_compare($this->db_version, $this->schema_version, '<');
107 107
 	}
108 108
 
109 109
 	/**
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
 		// work around race conditions and ensure that our option updates
119 119
 		$value_to_save = (string) $this->schema_version . '.0.' . time();
120 120
 
121
-		update_option( $option_name, $value_to_save );
121
+		update_option($option_name, $value_to_save);
122 122
 	}
123 123
 
124 124
 	/**
@@ -128,14 +128,14 @@  discard block
 block discarded – undo
128 128
 	 *
129 129
 	 * @return void
130 130
 	 */
131
-	private function update_table( $table ) {
132
-		require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
133
-		$definition = $this->get_table_definition( $table );
134
-		if ( $definition ) {
135
-			$updated = dbDelta( $definition );
136
-			foreach ( $updated as $updated_table => $update_description ) {
137
-				if ( strpos( $update_description, 'Created table' ) === 0 ) {
138
-					do_action( 'action_scheduler/created_table', $updated_table, $table );
131
+	private function update_table($table) {
132
+		require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
133
+		$definition = $this->get_table_definition($table);
134
+		if ($definition) {
135
+			$updated = dbDelta($definition);
136
+			foreach ($updated as $updated_table => $update_description) {
137
+				if (strpos($update_description, 'Created table') === 0) {
138
+					do_action('action_scheduler/created_table', $updated_table, $table);
139 139
 				}
140 140
 			}
141 141
 		}
@@ -147,8 +147,8 @@  discard block
 block discarded – undo
147 147
 	 * @return string The full name of the table, including the
148 148
 	 *                table prefix for the current blog
149 149
 	 */
150
-	protected function get_full_table_name( $table ) {
151
-		return $GLOBALS[ 'wpdb' ]->prefix . $table;
150
+	protected function get_full_table_name($table) {
151
+		return $GLOBALS['wpdb']->prefix . $table;
152 152
 	}
153 153
 
154 154
 	/**
@@ -159,14 +159,14 @@  discard block
 block discarded – undo
159 159
 	public function tables_exist() {
160 160
 		global $wpdb;
161 161
 
162
-		$existing_tables = $wpdb->get_col( 'SHOW TABLES' );
162
+		$existing_tables = $wpdb->get_col('SHOW TABLES');
163 163
 		$expected_tables = array_map(
164
-			function ( $table_name ) use ( $wpdb ) {
164
+			function($table_name) use ($wpdb) {
165 165
 				return $wpdb->prefix . $table_name;
166 166
 			},
167 167
 			$this->tables
168 168
 		);
169 169
 
170
-		return count( array_intersect( $existing_tables, $expected_tables ) ) === count( $expected_tables );
170
+		return count(array_intersect($existing_tables, $expected_tables)) === count($expected_tables);
171 171
 	}
172 172
 }
Please login to merge, or discard this patch.
classes/abstracts/ActionScheduler_Abstract_RecurringSchedule.php 2 patches
Indentation   +86 added lines, -86 removed lines patch added patch discarded remove patch
@@ -5,98 +5,98 @@
 block discarded – undo
5 5
  */
6 6
 abstract class ActionScheduler_Abstract_RecurringSchedule extends ActionScheduler_Abstract_Schedule {
7 7
 
8
-	/**
9
-	 * The date & time the first instance of this schedule was setup to run (which may not be this instance).
10
-	 *
11
-	 * Schedule objects are attached to an action object. Each schedule stores the run date for that
12
-	 * object as the start date - @see $this->start - and logic to calculate the next run date after
13
-	 * that - @see $this->calculate_next(). The $first_date property also keeps a record of when the very
14
-	 * first instance of this chain of schedules ran.
15
-	 *
16
-	 * @var DateTime
17
-	 */
18
-	private $first_date = NULL;
8
+    /**
9
+     * The date & time the first instance of this schedule was setup to run (which may not be this instance).
10
+     *
11
+     * Schedule objects are attached to an action object. Each schedule stores the run date for that
12
+     * object as the start date - @see $this->start - and logic to calculate the next run date after
13
+     * that - @see $this->calculate_next(). The $first_date property also keeps a record of when the very
14
+     * first instance of this chain of schedules ran.
15
+     *
16
+     * @var DateTime
17
+     */
18
+    private $first_date = NULL;
19 19
 
20
-	/**
21
-	 * Timestamp equivalent of @see $this->first_date
22
-	 *
23
-	 * @var int
24
-	 */
25
-	protected $first_timestamp = NULL;
20
+    /**
21
+     * Timestamp equivalent of @see $this->first_date
22
+     *
23
+     * @var int
24
+     */
25
+    protected $first_timestamp = NULL;
26 26
 
27
-	/**
28
-	 * The recurrance between each time an action is run using this schedule.
29
-	 * Used to calculate the start date & time. Can be a number of seconds, in the
30
-	 * case of ActionScheduler_IntervalSchedule, or a cron expression, as in the
31
-	 * case of ActionScheduler_CronSchedule. Or something else.
32
-	 *
33
-	 * @var mixed
34
-	 */
35
-	protected $recurrence;
27
+    /**
28
+     * The recurrance between each time an action is run using this schedule.
29
+     * Used to calculate the start date & time. Can be a number of seconds, in the
30
+     * case of ActionScheduler_IntervalSchedule, or a cron expression, as in the
31
+     * case of ActionScheduler_CronSchedule. Or something else.
32
+     *
33
+     * @var mixed
34
+     */
35
+    protected $recurrence;
36 36
 
37
-	/**
38
-	 * @param DateTime $date The date & time to run the action.
39
-	 * @param mixed $recurrence The data used to determine the schedule's recurrance.
40
-	 * @param DateTime|null $first (Optional) The date & time the first instance of this interval schedule ran. Default null, meaning this is the first instance.
41
-	 */
42
-	public function __construct( DateTime $date, $recurrence, DateTime $first = null ) {
43
-		parent::__construct( $date );
44
-		$this->first_date = empty( $first ) ? $date : $first;
45
-		$this->recurrence = $recurrence;
46
-	}
37
+    /**
38
+     * @param DateTime $date The date & time to run the action.
39
+     * @param mixed $recurrence The data used to determine the schedule's recurrance.
40
+     * @param DateTime|null $first (Optional) The date & time the first instance of this interval schedule ran. Default null, meaning this is the first instance.
41
+     */
42
+    public function __construct( DateTime $date, $recurrence, DateTime $first = null ) {
43
+        parent::__construct( $date );
44
+        $this->first_date = empty( $first ) ? $date : $first;
45
+        $this->recurrence = $recurrence;
46
+    }
47 47
 
48
-	/**
49
-	 * @return bool
50
-	 */
51
-	public function is_recurring() {
52
-		return true;
53
-	}
48
+    /**
49
+     * @return bool
50
+     */
51
+    public function is_recurring() {
52
+        return true;
53
+    }
54 54
 
55
-	/**
56
-	 * Get the date & time of the first schedule in this recurring series.
57
-	 *
58
-	 * @return DateTime|null
59
-	 */
60
-	public function get_first_date() {
61
-		return clone $this->first_date;
62
-	}
55
+    /**
56
+     * Get the date & time of the first schedule in this recurring series.
57
+     *
58
+     * @return DateTime|null
59
+     */
60
+    public function get_first_date() {
61
+        return clone $this->first_date;
62
+    }
63 63
 
64
-	/**
65
-	 * @return string
66
-	 */
67
-	public function get_recurrence() {
68
-		return $this->recurrence;
69
-	}
64
+    /**
65
+     * @return string
66
+     */
67
+    public function get_recurrence() {
68
+        return $this->recurrence;
69
+    }
70 70
 
71
-	/**
72
-	 * For PHP 5.2 compat, since DateTime objects can't be serialized
73
-	 * @return array
74
-	 */
75
-	public function __sleep() {
76
-		$sleep_params = parent::__sleep();
77
-		$this->first_timestamp = $this->first_date->getTimestamp();
78
-		return array_merge( $sleep_params, array(
79
-			'first_timestamp',
80
-			'recurrence'
81
-		) );
82
-	}
71
+    /**
72
+     * For PHP 5.2 compat, since DateTime objects can't be serialized
73
+     * @return array
74
+     */
75
+    public function __sleep() {
76
+        $sleep_params = parent::__sleep();
77
+        $this->first_timestamp = $this->first_date->getTimestamp();
78
+        return array_merge( $sleep_params, array(
79
+            'first_timestamp',
80
+            'recurrence'
81
+        ) );
82
+    }
83 83
 
84
-	/**
85
-	 * Unserialize recurring schedules serialized/stored prior to AS 3.0.0
86
-	 *
87
-	 * Prior to Action Scheduler 3.0.0, schedules used different property names to refer
88
-	 * to equivalent data. For example, ActionScheduler_IntervalSchedule::start_timestamp
89
-	 * was the same as ActionScheduler_SimpleSchedule::timestamp. This was addressed in
90
-	 * Action Scheduler 3.0.0, where properties and property names were aligned for better
91
-	 * inheritance. To maintain backward compatibility with scheduled serialized and stored
92
-	 * prior to 3.0, we need to correctly map the old property names.
93
-	 */
94
-	public function __wakeup() {
95
-		parent::__wakeup();
96
-		if ( $this->first_timestamp > 0 ) {
97
-			$this->first_date = as_get_datetime_object( $this->first_timestamp );
98
-		} else {
99
-			$this->first_date = $this->get_date();
100
-		}
101
-	}
84
+    /**
85
+     * Unserialize recurring schedules serialized/stored prior to AS 3.0.0
86
+     *
87
+     * Prior to Action Scheduler 3.0.0, schedules used different property names to refer
88
+     * to equivalent data. For example, ActionScheduler_IntervalSchedule::start_timestamp
89
+     * was the same as ActionScheduler_SimpleSchedule::timestamp. This was addressed in
90
+     * Action Scheduler 3.0.0, where properties and property names were aligned for better
91
+     * inheritance. To maintain backward compatibility with scheduled serialized and stored
92
+     * prior to 3.0, we need to correctly map the old property names.
93
+     */
94
+    public function __wakeup() {
95
+        parent::__wakeup();
96
+        if ( $this->first_timestamp > 0 ) {
97
+            $this->first_date = as_get_datetime_object( $this->first_timestamp );
98
+        } else {
99
+            $this->first_date = $this->get_date();
100
+        }
101
+    }
102 102
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -39,9 +39,9 @@  discard block
 block discarded – undo
39 39
 	 * @param mixed $recurrence The data used to determine the schedule's recurrance.
40 40
 	 * @param DateTime|null $first (Optional) The date & time the first instance of this interval schedule ran. Default null, meaning this is the first instance.
41 41
 	 */
42
-	public function __construct( DateTime $date, $recurrence, DateTime $first = null ) {
43
-		parent::__construct( $date );
44
-		$this->first_date = empty( $first ) ? $date : $first;
42
+	public function __construct(DateTime $date, $recurrence, DateTime $first = null) {
43
+		parent::__construct($date);
44
+		$this->first_date = empty($first) ? $date : $first;
45 45
 		$this->recurrence = $recurrence;
46 46
 	}
47 47
 
@@ -75,10 +75,10 @@  discard block
 block discarded – undo
75 75
 	public function __sleep() {
76 76
 		$sleep_params = parent::__sleep();
77 77
 		$this->first_timestamp = $this->first_date->getTimestamp();
78
-		return array_merge( $sleep_params, array(
78
+		return array_merge($sleep_params, array(
79 79
 			'first_timestamp',
80 80
 			'recurrence'
81
-		) );
81
+		));
82 82
 	}
83 83
 
84 84
 	/**
@@ -93,8 +93,8 @@  discard block
 block discarded – undo
93 93
 	 */
94 94
 	public function __wakeup() {
95 95
 		parent::__wakeup();
96
-		if ( $this->first_timestamp > 0 ) {
97
-			$this->first_date = as_get_datetime_object( $this->first_timestamp );
96
+		if ($this->first_timestamp > 0) {
97
+			$this->first_date = as_get_datetime_object($this->first_timestamp);
98 98
 		} else {
99 99
 			$this->first_date = $this->get_date();
100 100
 		}
Please login to merge, or discard this patch.
packages/action-scheduler/classes/abstracts/ActionScheduler_Lock.php 2 patches
Indentation   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -7,56 +7,56 @@
 block discarded – undo
7 7
  */
8 8
 abstract class ActionScheduler_Lock {
9 9
 
10
-	/** @var ActionScheduler_Lock */
11
-	private static $locker = NULL;
12
-
13
-	/** @var int */
14
-	protected static $lock_duration = MINUTE_IN_SECONDS;
15
-
16
-	/**
17
-	 * Check if a lock is set for a given lock type.
18
-	 *
19
-	 * @param string $lock_type A string to identify different lock types.
20
-	 * @return bool
21
-	 */
22
-	public function is_locked( $lock_type ) {
23
-		return ( $this->get_expiration( $lock_type ) >= time() );
24
-	}
25
-
26
-	/**
27
-	 * Set a lock.
28
-	 *
29
-	 * @param string $lock_type A string to identify different lock types.
30
-	 * @return bool
31
-	 */
32
-	abstract public function set( $lock_type );
33
-
34
-	/**
35
-	 * If a lock is set, return the timestamp it was set to expiry.
36
-	 *
37
-	 * @param string $lock_type A string to identify different lock types.
38
-	 * @return bool|int False if no lock is set, otherwise the timestamp for when the lock is set to expire.
39
-	 */
40
-	abstract public function get_expiration( $lock_type );
41
-
42
-	/**
43
-	 * Get the amount of time to set for a given lock. 60 seconds by default.
44
-	 *
45
-	 * @param string $lock_type A string to identify different lock types.
46
-	 * @return int
47
-	 */
48
-	protected function get_duration( $lock_type ) {
49
-		return apply_filters( 'action_scheduler_lock_duration', self::$lock_duration, $lock_type );
50
-	}
51
-
52
-	/**
53
-	 * @return ActionScheduler_Lock
54
-	 */
55
-	public static function instance() {
56
-		if ( empty( self::$locker ) ) {
57
-			$class = apply_filters( 'action_scheduler_lock_class', 'ActionScheduler_OptionLock' );
58
-			self::$locker = new $class();
59
-		}
60
-		return self::$locker;
61
-	}
10
+    /** @var ActionScheduler_Lock */
11
+    private static $locker = NULL;
12
+
13
+    /** @var int */
14
+    protected static $lock_duration = MINUTE_IN_SECONDS;
15
+
16
+    /**
17
+     * Check if a lock is set for a given lock type.
18
+     *
19
+     * @param string $lock_type A string to identify different lock types.
20
+     * @return bool
21
+     */
22
+    public function is_locked( $lock_type ) {
23
+        return ( $this->get_expiration( $lock_type ) >= time() );
24
+    }
25
+
26
+    /**
27
+     * Set a lock.
28
+     *
29
+     * @param string $lock_type A string to identify different lock types.
30
+     * @return bool
31
+     */
32
+    abstract public function set( $lock_type );
33
+
34
+    /**
35
+     * If a lock is set, return the timestamp it was set to expiry.
36
+     *
37
+     * @param string $lock_type A string to identify different lock types.
38
+     * @return bool|int False if no lock is set, otherwise the timestamp for when the lock is set to expire.
39
+     */
40
+    abstract public function get_expiration( $lock_type );
41
+
42
+    /**
43
+     * Get the amount of time to set for a given lock. 60 seconds by default.
44
+     *
45
+     * @param string $lock_type A string to identify different lock types.
46
+     * @return int
47
+     */
48
+    protected function get_duration( $lock_type ) {
49
+        return apply_filters( 'action_scheduler_lock_duration', self::$lock_duration, $lock_type );
50
+    }
51
+
52
+    /**
53
+     * @return ActionScheduler_Lock
54
+     */
55
+    public static function instance() {
56
+        if ( empty( self::$locker ) ) {
57
+            $class = apply_filters( 'action_scheduler_lock_class', 'ActionScheduler_OptionLock' );
58
+            self::$locker = new $class();
59
+        }
60
+        return self::$locker;
61
+    }
62 62
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -19,8 +19,8 @@  discard block
 block discarded – undo
19 19
 	 * @param string $lock_type A string to identify different lock types.
20 20
 	 * @return bool
21 21
 	 */
22
-	public function is_locked( $lock_type ) {
23
-		return ( $this->get_expiration( $lock_type ) >= time() );
22
+	public function is_locked($lock_type) {
23
+		return ($this->get_expiration($lock_type) >= time());
24 24
 	}
25 25
 
26 26
 	/**
@@ -29,7 +29,7 @@  discard block
 block discarded – undo
29 29
 	 * @param string $lock_type A string to identify different lock types.
30 30
 	 * @return bool
31 31
 	 */
32
-	abstract public function set( $lock_type );
32
+	abstract public function set($lock_type);
33 33
 
34 34
 	/**
35 35
 	 * If a lock is set, return the timestamp it was set to expiry.
@@ -37,7 +37,7 @@  discard block
 block discarded – undo
37 37
 	 * @param string $lock_type A string to identify different lock types.
38 38
 	 * @return bool|int False if no lock is set, otherwise the timestamp for when the lock is set to expire.
39 39
 	 */
40
-	abstract public function get_expiration( $lock_type );
40
+	abstract public function get_expiration($lock_type);
41 41
 
42 42
 	/**
43 43
 	 * Get the amount of time to set for a given lock. 60 seconds by default.
@@ -45,16 +45,16 @@  discard block
 block discarded – undo
45 45
 	 * @param string $lock_type A string to identify different lock types.
46 46
 	 * @return int
47 47
 	 */
48
-	protected function get_duration( $lock_type ) {
49
-		return apply_filters( 'action_scheduler_lock_duration', self::$lock_duration, $lock_type );
48
+	protected function get_duration($lock_type) {
49
+		return apply_filters('action_scheduler_lock_duration', self::$lock_duration, $lock_type);
50 50
 	}
51 51
 
52 52
 	/**
53 53
 	 * @return ActionScheduler_Lock
54 54
 	 */
55 55
 	public static function instance() {
56
-		if ( empty( self::$locker ) ) {
57
-			$class = apply_filters( 'action_scheduler_lock_class', 'ActionScheduler_OptionLock' );
56
+		if (empty(self::$locker)) {
57
+			$class = apply_filters('action_scheduler_lock_class', 'ActionScheduler_OptionLock');
58 58
 			self::$locker = new $class();
59 59
 		}
60 60
 		return self::$locker;
Please login to merge, or discard this patch.
action-scheduler/classes/abstracts/ActionScheduler_TimezoneHelper.php 2 patches
Indentation   +145 added lines, -145 removed lines patch added patch discarded remove patch
@@ -4,149 +4,149 @@
 block discarded – undo
4 4
  * Class ActionScheduler_TimezoneHelper
5 5
  */
6 6
 abstract class ActionScheduler_TimezoneHelper {
7
-	private static $local_timezone = NULL;
8
-
9
-	/**
10
-	 * Set a DateTime's timezone to the WordPress site's timezone, or a UTC offset
11
-	 * if no timezone string is available.
12
-	 *
13
-	 * @since  2.1.0
14
-	 *
15
-	 * @param DateTime $date
16
-	 * @return ActionScheduler_DateTime
17
-	 */
18
-	public static function set_local_timezone( DateTime $date ) {
19
-
20
-		// Accept a DateTime for easier backward compatibility, even though we require methods on ActionScheduler_DateTime
21
-		if ( ! is_a( $date, 'ActionScheduler_DateTime' ) ) {
22
-			$date = as_get_datetime_object( $date->format( 'U' ) );
23
-		}
24
-
25
-		if ( get_option( 'timezone_string' ) ) {
26
-			$date->setTimezone( new DateTimeZone( self::get_local_timezone_string() ) );
27
-		} else {
28
-			$date->setUtcOffset( self::get_local_timezone_offset() );
29
-		}
30
-
31
-		return $date;
32
-	}
33
-
34
-	/**
35
-	 * Helper to retrieve the timezone string for a site until a WP core method exists
36
-	 * (see https://core.trac.wordpress.org/ticket/24730).
37
-	 *
38
-	 * Adapted from wc_timezone_string() and https://secure.php.net/manual/en/function.timezone-name-from-abbr.php#89155.
39
-	 *
40
-	 * If no timezone string is set, and its not possible to match the UTC offset set for the site to a timezone
41
-	 * string, then an empty string will be returned, and the UTC offset should be used to set a DateTime's
42
-	 * timezone.
43
-	 *
44
-	 * @since 2.1.0
45
-	 * @return string PHP timezone string for the site or empty if no timezone string is available.
46
-	 */
47
-	protected static function get_local_timezone_string( $reset = false ) {
48
-		// If site timezone string exists, return it.
49
-		$timezone = get_option( 'timezone_string' );
50
-		if ( $timezone ) {
51
-			return $timezone;
52
-		}
53
-
54
-		// Get UTC offset, if it isn't set then return UTC.
55
-		$utc_offset = intval( get_option( 'gmt_offset', 0 ) );
56
-		if ( 0 === $utc_offset ) {
57
-			return 'UTC';
58
-		}
59
-
60
-		// Adjust UTC offset from hours to seconds.
61
-		$utc_offset *= 3600;
62
-
63
-		// Attempt to guess the timezone string from the UTC offset.
64
-		$timezone = timezone_name_from_abbr( '', $utc_offset );
65
-		if ( $timezone ) {
66
-			return $timezone;
67
-		}
68
-
69
-		// Last try, guess timezone string manually.
70
-		foreach ( timezone_abbreviations_list() as $abbr ) {
71
-			foreach ( $abbr as $city ) {
72
-				if ( (bool) date( 'I' ) === (bool) $city['dst'] && $city['timezone_id'] && intval( $city['offset'] ) === $utc_offset ) {
73
-					return $city['timezone_id'];
74
-				}
75
-			}
76
-		}
77
-
78
-		// No timezone string
79
-		return '';
80
-	}
81
-
82
-	/**
83
-	 * Get timezone offset in seconds.
84
-	 *
85
-	 * @since  2.1.0
86
-	 * @return float
87
-	 */
88
-	protected static function get_local_timezone_offset() {
89
-		$timezone = get_option( 'timezone_string' );
90
-
91
-		if ( $timezone ) {
92
-			$timezone_object = new DateTimeZone( $timezone );
93
-			return $timezone_object->getOffset( new DateTime( 'now' ) );
94
-		} else {
95
-			return floatval( get_option( 'gmt_offset', 0 ) ) * HOUR_IN_SECONDS;
96
-		}
97
-	}
98
-
99
-	/**
100
-	 * @deprecated 2.1.0
101
-	 */
102
-	public static function get_local_timezone( $reset = FALSE ) {
103
-		_deprecated_function( __FUNCTION__, '2.1.0', 'ActionScheduler_TimezoneHelper::set_local_timezone()' );
104
-		if ( $reset ) {
105
-			self::$local_timezone = NULL;
106
-		}
107
-		if ( !isset(self::$local_timezone) ) {
108
-			$tzstring = get_option('timezone_string');
109
-
110
-			if ( empty($tzstring) ) {
111
-				$gmt_offset = get_option('gmt_offset');
112
-				if ( $gmt_offset == 0 ) {
113
-					$tzstring = 'UTC';
114
-				} else {
115
-					$gmt_offset *= HOUR_IN_SECONDS;
116
-					$tzstring   = timezone_name_from_abbr( '', $gmt_offset, 1 );
117
-
118
-					// If there's no timezone string, try again with no DST.
119
-					if ( false === $tzstring ) {
120
-						$tzstring = timezone_name_from_abbr( '', $gmt_offset, 0 );
121
-					}
122
-
123
-					// Try mapping to the first abbreviation we can find.
124
-					if ( false === $tzstring ) {
125
-						$is_dst = date( 'I' );
126
-						foreach ( timezone_abbreviations_list() as $abbr ) {
127
-							foreach ( $abbr as $city ) {
128
-								if ( $city['dst'] == $is_dst && $city['offset'] == $gmt_offset ) {
129
-									// If there's no valid timezone ID, keep looking.
130
-									if ( null === $city['timezone_id'] ) {
131
-										continue;
132
-									}
133
-
134
-									$tzstring = $city['timezone_id'];
135
-									break 2;
136
-								}
137
-							}
138
-						}
139
-					}
140
-
141
-					// If we still have no valid string, then fall back to UTC.
142
-					if ( false === $tzstring ) {
143
-						$tzstring = 'UTC';
144
-					}
145
-				}
146
-			}
147
-
148
-			self::$local_timezone = new DateTimeZone($tzstring);
149
-		}
150
-		return self::$local_timezone;
151
-	}
7
+    private static $local_timezone = NULL;
8
+
9
+    /**
10
+     * Set a DateTime's timezone to the WordPress site's timezone, or a UTC offset
11
+     * if no timezone string is available.
12
+     *
13
+     * @since  2.1.0
14
+     *
15
+     * @param DateTime $date
16
+     * @return ActionScheduler_DateTime
17
+     */
18
+    public static function set_local_timezone( DateTime $date ) {
19
+
20
+        // Accept a DateTime for easier backward compatibility, even though we require methods on ActionScheduler_DateTime
21
+        if ( ! is_a( $date, 'ActionScheduler_DateTime' ) ) {
22
+            $date = as_get_datetime_object( $date->format( 'U' ) );
23
+        }
24
+
25
+        if ( get_option( 'timezone_string' ) ) {
26
+            $date->setTimezone( new DateTimeZone( self::get_local_timezone_string() ) );
27
+        } else {
28
+            $date->setUtcOffset( self::get_local_timezone_offset() );
29
+        }
30
+
31
+        return $date;
32
+    }
33
+
34
+    /**
35
+     * Helper to retrieve the timezone string for a site until a WP core method exists
36
+     * (see https://core.trac.wordpress.org/ticket/24730).
37
+     *
38
+     * Adapted from wc_timezone_string() and https://secure.php.net/manual/en/function.timezone-name-from-abbr.php#89155.
39
+     *
40
+     * If no timezone string is set, and its not possible to match the UTC offset set for the site to a timezone
41
+     * string, then an empty string will be returned, and the UTC offset should be used to set a DateTime's
42
+     * timezone.
43
+     *
44
+     * @since 2.1.0
45
+     * @return string PHP timezone string for the site or empty if no timezone string is available.
46
+     */
47
+    protected static function get_local_timezone_string( $reset = false ) {
48
+        // If site timezone string exists, return it.
49
+        $timezone = get_option( 'timezone_string' );
50
+        if ( $timezone ) {
51
+            return $timezone;
52
+        }
53
+
54
+        // Get UTC offset, if it isn't set then return UTC.
55
+        $utc_offset = intval( get_option( 'gmt_offset', 0 ) );
56
+        if ( 0 === $utc_offset ) {
57
+            return 'UTC';
58
+        }
59
+
60
+        // Adjust UTC offset from hours to seconds.
61
+        $utc_offset *= 3600;
62
+
63
+        // Attempt to guess the timezone string from the UTC offset.
64
+        $timezone = timezone_name_from_abbr( '', $utc_offset );
65
+        if ( $timezone ) {
66
+            return $timezone;
67
+        }
68
+
69
+        // Last try, guess timezone string manually.
70
+        foreach ( timezone_abbreviations_list() as $abbr ) {
71
+            foreach ( $abbr as $city ) {
72
+                if ( (bool) date( 'I' ) === (bool) $city['dst'] && $city['timezone_id'] && intval( $city['offset'] ) === $utc_offset ) {
73
+                    return $city['timezone_id'];
74
+                }
75
+            }
76
+        }
77
+
78
+        // No timezone string
79
+        return '';
80
+    }
81
+
82
+    /**
83
+     * Get timezone offset in seconds.
84
+     *
85
+     * @since  2.1.0
86
+     * @return float
87
+     */
88
+    protected static function get_local_timezone_offset() {
89
+        $timezone = get_option( 'timezone_string' );
90
+
91
+        if ( $timezone ) {
92
+            $timezone_object = new DateTimeZone( $timezone );
93
+            return $timezone_object->getOffset( new DateTime( 'now' ) );
94
+        } else {
95
+            return floatval( get_option( 'gmt_offset', 0 ) ) * HOUR_IN_SECONDS;
96
+        }
97
+    }
98
+
99
+    /**
100
+     * @deprecated 2.1.0
101
+     */
102
+    public static function get_local_timezone( $reset = FALSE ) {
103
+        _deprecated_function( __FUNCTION__, '2.1.0', 'ActionScheduler_TimezoneHelper::set_local_timezone()' );
104
+        if ( $reset ) {
105
+            self::$local_timezone = NULL;
106
+        }
107
+        if ( !isset(self::$local_timezone) ) {
108
+            $tzstring = get_option('timezone_string');
109
+
110
+            if ( empty($tzstring) ) {
111
+                $gmt_offset = get_option('gmt_offset');
112
+                if ( $gmt_offset == 0 ) {
113
+                    $tzstring = 'UTC';
114
+                } else {
115
+                    $gmt_offset *= HOUR_IN_SECONDS;
116
+                    $tzstring   = timezone_name_from_abbr( '', $gmt_offset, 1 );
117
+
118
+                    // If there's no timezone string, try again with no DST.
119
+                    if ( false === $tzstring ) {
120
+                        $tzstring = timezone_name_from_abbr( '', $gmt_offset, 0 );
121
+                    }
122
+
123
+                    // Try mapping to the first abbreviation we can find.
124
+                    if ( false === $tzstring ) {
125
+                        $is_dst = date( 'I' );
126
+                        foreach ( timezone_abbreviations_list() as $abbr ) {
127
+                            foreach ( $abbr as $city ) {
128
+                                if ( $city['dst'] == $is_dst && $city['offset'] == $gmt_offset ) {
129
+                                    // If there's no valid timezone ID, keep looking.
130
+                                    if ( null === $city['timezone_id'] ) {
131
+                                        continue;
132
+                                    }
133
+
134
+                                    $tzstring = $city['timezone_id'];
135
+                                    break 2;
136
+                                }
137
+                            }
138
+                        }
139
+                    }
140
+
141
+                    // If we still have no valid string, then fall back to UTC.
142
+                    if ( false === $tzstring ) {
143
+                        $tzstring = 'UTC';
144
+                    }
145
+                }
146
+            }
147
+
148
+            self::$local_timezone = new DateTimeZone($tzstring);
149
+        }
150
+        return self::$local_timezone;
151
+    }
152 152
 }
Please login to merge, or discard this patch.
Spacing   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -15,17 +15,17 @@  discard block
 block discarded – undo
15 15
 	 * @param DateTime $date
16 16
 	 * @return ActionScheduler_DateTime
17 17
 	 */
18
-	public static function set_local_timezone( DateTime $date ) {
18
+	public static function set_local_timezone(DateTime $date) {
19 19
 
20 20
 		// Accept a DateTime for easier backward compatibility, even though we require methods on ActionScheduler_DateTime
21
-		if ( ! is_a( $date, 'ActionScheduler_DateTime' ) ) {
22
-			$date = as_get_datetime_object( $date->format( 'U' ) );
21
+		if (!is_a($date, 'ActionScheduler_DateTime')) {
22
+			$date = as_get_datetime_object($date->format('U'));
23 23
 		}
24 24
 
25
-		if ( get_option( 'timezone_string' ) ) {
26
-			$date->setTimezone( new DateTimeZone( self::get_local_timezone_string() ) );
25
+		if (get_option('timezone_string')) {
26
+			$date->setTimezone(new DateTimeZone(self::get_local_timezone_string()));
27 27
 		} else {
28
-			$date->setUtcOffset( self::get_local_timezone_offset() );
28
+			$date->setUtcOffset(self::get_local_timezone_offset());
29 29
 		}
30 30
 
31 31
 		return $date;
@@ -44,16 +44,16 @@  discard block
 block discarded – undo
44 44
 	 * @since 2.1.0
45 45
 	 * @return string PHP timezone string for the site or empty if no timezone string is available.
46 46
 	 */
47
-	protected static function get_local_timezone_string( $reset = false ) {
47
+	protected static function get_local_timezone_string($reset = false) {
48 48
 		// If site timezone string exists, return it.
49
-		$timezone = get_option( 'timezone_string' );
50
-		if ( $timezone ) {
49
+		$timezone = get_option('timezone_string');
50
+		if ($timezone) {
51 51
 			return $timezone;
52 52
 		}
53 53
 
54 54
 		// Get UTC offset, if it isn't set then return UTC.
55
-		$utc_offset = intval( get_option( 'gmt_offset', 0 ) );
56
-		if ( 0 === $utc_offset ) {
55
+		$utc_offset = intval(get_option('gmt_offset', 0));
56
+		if (0 === $utc_offset) {
57 57
 			return 'UTC';
58 58
 		}
59 59
 
@@ -61,15 +61,15 @@  discard block
 block discarded – undo
61 61
 		$utc_offset *= 3600;
62 62
 
63 63
 		// Attempt to guess the timezone string from the UTC offset.
64
-		$timezone = timezone_name_from_abbr( '', $utc_offset );
65
-		if ( $timezone ) {
64
+		$timezone = timezone_name_from_abbr('', $utc_offset);
65
+		if ($timezone) {
66 66
 			return $timezone;
67 67
 		}
68 68
 
69 69
 		// Last try, guess timezone string manually.
70
-		foreach ( timezone_abbreviations_list() as $abbr ) {
71
-			foreach ( $abbr as $city ) {
72
-				if ( (bool) date( 'I' ) === (bool) $city['dst'] && $city['timezone_id'] && intval( $city['offset'] ) === $utc_offset ) {
70
+		foreach (timezone_abbreviations_list() as $abbr) {
71
+			foreach ($abbr as $city) {
72
+				if ((bool) date('I') === (bool) $city['dst'] && $city['timezone_id'] && intval($city['offset']) === $utc_offset) {
73 73
 					return $city['timezone_id'];
74 74
 				}
75 75
 			}
@@ -86,48 +86,48 @@  discard block
 block discarded – undo
86 86
 	 * @return float
87 87
 	 */
88 88
 	protected static function get_local_timezone_offset() {
89
-		$timezone = get_option( 'timezone_string' );
89
+		$timezone = get_option('timezone_string');
90 90
 
91
-		if ( $timezone ) {
92
-			$timezone_object = new DateTimeZone( $timezone );
93
-			return $timezone_object->getOffset( new DateTime( 'now' ) );
91
+		if ($timezone) {
92
+			$timezone_object = new DateTimeZone($timezone);
93
+			return $timezone_object->getOffset(new DateTime('now'));
94 94
 		} else {
95
-			return floatval( get_option( 'gmt_offset', 0 ) ) * HOUR_IN_SECONDS;
95
+			return floatval(get_option('gmt_offset', 0)) * HOUR_IN_SECONDS;
96 96
 		}
97 97
 	}
98 98
 
99 99
 	/**
100 100
 	 * @deprecated 2.1.0
101 101
 	 */
102
-	public static function get_local_timezone( $reset = FALSE ) {
103
-		_deprecated_function( __FUNCTION__, '2.1.0', 'ActionScheduler_TimezoneHelper::set_local_timezone()' );
104
-		if ( $reset ) {
102
+	public static function get_local_timezone($reset = FALSE) {
103
+		_deprecated_function(__FUNCTION__, '2.1.0', 'ActionScheduler_TimezoneHelper::set_local_timezone()');
104
+		if ($reset) {
105 105
 			self::$local_timezone = NULL;
106 106
 		}
107
-		if ( !isset(self::$local_timezone) ) {
107
+		if (!isset(self::$local_timezone)) {
108 108
 			$tzstring = get_option('timezone_string');
109 109
 
110
-			if ( empty($tzstring) ) {
110
+			if (empty($tzstring)) {
111 111
 				$gmt_offset = get_option('gmt_offset');
112
-				if ( $gmt_offset == 0 ) {
112
+				if ($gmt_offset == 0) {
113 113
 					$tzstring = 'UTC';
114 114
 				} else {
115 115
 					$gmt_offset *= HOUR_IN_SECONDS;
116
-					$tzstring   = timezone_name_from_abbr( '', $gmt_offset, 1 );
116
+					$tzstring = timezone_name_from_abbr('', $gmt_offset, 1);
117 117
 
118 118
 					// If there's no timezone string, try again with no DST.
119
-					if ( false === $tzstring ) {
120
-						$tzstring = timezone_name_from_abbr( '', $gmt_offset, 0 );
119
+					if (false === $tzstring) {
120
+						$tzstring = timezone_name_from_abbr('', $gmt_offset, 0);
121 121
 					}
122 122
 
123 123
 					// Try mapping to the first abbreviation we can find.
124
-					if ( false === $tzstring ) {
125
-						$is_dst = date( 'I' );
126
-						foreach ( timezone_abbreviations_list() as $abbr ) {
127
-							foreach ( $abbr as $city ) {
128
-								if ( $city['dst'] == $is_dst && $city['offset'] == $gmt_offset ) {
124
+					if (false === $tzstring) {
125
+						$is_dst = date('I');
126
+						foreach (timezone_abbreviations_list() as $abbr) {
127
+							foreach ($abbr as $city) {
128
+								if ($city['dst'] == $is_dst && $city['offset'] == $gmt_offset) {
129 129
 									// If there's no valid timezone ID, keep looking.
130
-									if ( null === $city['timezone_id'] ) {
130
+									if (null === $city['timezone_id']) {
131 131
 										continue;
132 132
 									}
133 133
 
@@ -139,7 +139,7 @@  discard block
 block discarded – undo
139 139
 					}
140 140
 
141 141
 					// If we still have no valid string, then fall back to UTC.
142
-					if ( false === $tzstring ) {
142
+					if (false === $tzstring) {
143 143
 						$tzstring = 'UTC';
144 144
 					}
145 145
 				}
Please login to merge, or discard this patch.
action-scheduler/classes/abstracts/ActionScheduler_Abstract_QueueRunner.php 2 patches
Indentation   +232 added lines, -232 removed lines patch added patch discarded remove patch
@@ -5,236 +5,236 @@
 block discarded – undo
5 5
  */
6 6
 abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abstract_QueueRunner_Deprecated {
7 7
 
8
-	/** @var ActionScheduler_QueueCleaner */
9
-	protected $cleaner;
10
-
11
-	/** @var ActionScheduler_FatalErrorMonitor */
12
-	protected $monitor;
13
-
14
-	/** @var ActionScheduler_Store */
15
-	protected $store;
16
-
17
-	/**
18
-	 * The created time.
19
-	 *
20
-	 * Represents when the queue runner was constructed and used when calculating how long a PHP request has been running.
21
-	 * For this reason it should be as close as possible to the PHP request start time.
22
-	 *
23
-	 * @var int
24
-	 */
25
-	private $created_time;
26
-
27
-	/**
28
-	 * ActionScheduler_Abstract_QueueRunner constructor.
29
-	 *
30
-	 * @param ActionScheduler_Store             $store
31
-	 * @param ActionScheduler_FatalErrorMonitor $monitor
32
-	 * @param ActionScheduler_QueueCleaner      $cleaner
33
-	 */
34
-	public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null ) {
35
-
36
-		$this->created_time = microtime( true );
37
-
38
-		$this->store   = $store ? $store : ActionScheduler_Store::instance();
39
-		$this->monitor = $monitor ? $monitor : new ActionScheduler_FatalErrorMonitor( $this->store );
40
-		$this->cleaner = $cleaner ? $cleaner : new ActionScheduler_QueueCleaner( $this->store );
41
-	}
42
-
43
-	/**
44
-	 * Process an individual action.
45
-	 *
46
-	 * @param int $action_id The action ID to process.
47
-	 * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
48
-	 *        Generally, this should be capitalised and not localised as it's a proper noun.
49
-	 */
50
-	public function process_action( $action_id, $context = '' ) {
51
-		try {
52
-			$valid_action = false;
53
-			do_action( 'action_scheduler_before_execute', $action_id, $context );
54
-
55
-			if ( ActionScheduler_Store::STATUS_PENDING !== $this->store->get_status( $action_id ) ) {
56
-				do_action( 'action_scheduler_execution_ignored', $action_id, $context );
57
-				return;
58
-			}
59
-
60
-			$valid_action = true;
61
-			do_action( 'action_scheduler_begin_execute', $action_id, $context );
62
-
63
-			$action = $this->store->fetch_action( $action_id );
64
-			$this->store->log_execution( $action_id );
65
-			$action->execute();
66
-			do_action( 'action_scheduler_after_execute', $action_id, $action, $context );
67
-			$this->store->mark_complete( $action_id );
68
-		} catch ( Exception $e ) {
69
-			if ( $valid_action ) {
70
-				$this->store->mark_failure( $action_id );
71
-				do_action( 'action_scheduler_failed_execution', $action_id, $e, $context );
72
-			} else {
73
-				do_action( 'action_scheduler_failed_validation', $action_id, $e, $context );
74
-			}
75
-		}
76
-
77
-		if ( isset( $action ) && is_a( $action, 'ActionScheduler_Action' ) && $action->get_schedule()->is_recurring() ) {
78
-			$this->schedule_next_instance( $action, $action_id );
79
-		}
80
-	}
81
-
82
-	/**
83
-	 * Schedule the next instance of the action if necessary.
84
-	 *
85
-	 * @param ActionScheduler_Action $action
86
-	 * @param int $action_id
87
-	 */
88
-	protected function schedule_next_instance( ActionScheduler_Action $action, $action_id ) {
89
-		try {
90
-			ActionScheduler::factory()->repeat( $action );
91
-		} catch ( Exception $e ) {
92
-			do_action( 'action_scheduler_failed_to_schedule_next_instance', $action_id, $e, $action );
93
-		}
94
-	}
95
-
96
-	/**
97
-	 * Run the queue cleaner.
98
-	 *
99
-	 * @author Jeremy Pry
100
-	 */
101
-	protected function run_cleanup() {
102
-		$this->cleaner->clean( 10 * $this->get_time_limit() );
103
-	}
104
-
105
-	/**
106
-	 * Get the number of concurrent batches a runner allows.
107
-	 *
108
-	 * @return int
109
-	 */
110
-	public function get_allowed_concurrent_batches() {
111
-		return apply_filters( 'action_scheduler_queue_runner_concurrent_batches', 1 );
112
-	}
113
-
114
-	/**
115
-	 * Check if the number of allowed concurrent batches is met or exceeded.
116
-	 *
117
-	 * @return bool
118
-	 */
119
-	public function has_maximum_concurrent_batches() {
120
-		return $this->store->get_claim_count() >= $this->get_allowed_concurrent_batches();
121
-	}
122
-
123
-	/**
124
-	 * Get the maximum number of seconds a batch can run for.
125
-	 *
126
-	 * @return int The number of seconds.
127
-	 */
128
-	protected function get_time_limit() {
129
-
130
-		$time_limit = 30;
131
-
132
-		// Apply deprecated filter from deprecated get_maximum_execution_time() method
133
-		if ( has_filter( 'action_scheduler_maximum_execution_time' ) ) {
134
-			_deprecated_function( 'action_scheduler_maximum_execution_time', '2.1.1', 'action_scheduler_queue_runner_time_limit' );
135
-			$time_limit = apply_filters( 'action_scheduler_maximum_execution_time', $time_limit );
136
-		}
137
-
138
-		return absint( apply_filters( 'action_scheduler_queue_runner_time_limit', $time_limit ) );
139
-	}
140
-
141
-	/**
142
-	 * Get the number of seconds the process has been running.
143
-	 *
144
-	 * @return int The number of seconds.
145
-	 */
146
-	protected function get_execution_time() {
147
-		$execution_time = microtime( true ) - $this->created_time;
148
-
149
-		// Get the CPU time if the hosting environment uses it rather than wall-clock time to calculate a process's execution time.
150
-		if ( function_exists( 'getrusage' ) && apply_filters( 'action_scheduler_use_cpu_execution_time', defined( 'PANTHEON_ENVIRONMENT' ) ) ) {
151
-			$resource_usages = getrusage();
152
-
153
-			if ( isset( $resource_usages['ru_stime.tv_usec'], $resource_usages['ru_stime.tv_usec'] ) ) {
154
-				$execution_time = $resource_usages['ru_stime.tv_sec'] + ( $resource_usages['ru_stime.tv_usec'] / 1000000 );
155
-			}
156
-		}
157
-
158
-		return $execution_time;
159
-	}
160
-
161
-	/**
162
-	 * Check if the host's max execution time is (likely) to be exceeded if processing more actions.
163
-	 *
164
-	 * @param int $processed_actions The number of actions processed so far - used to determine the likelihood of exceeding the time limit if processing another action
165
-	 * @return bool
166
-	 */
167
-	protected function time_likely_to_be_exceeded( $processed_actions ) {
168
-
169
-		$execution_time        = $this->get_execution_time();
170
-		$max_execution_time    = $this->get_time_limit();
171
-		$time_per_action       = $execution_time / $processed_actions;
172
-		$estimated_time        = $execution_time + ( $time_per_action * 3 );
173
-		$likely_to_be_exceeded = $estimated_time > $max_execution_time;
174
-
175
-		return apply_filters( 'action_scheduler_maximum_execution_time_likely_to_be_exceeded', $likely_to_be_exceeded, $this, $processed_actions, $execution_time, $max_execution_time );
176
-	}
177
-
178
-	/**
179
-	 * Get memory limit
180
-	 *
181
-	 * Based on WP_Background_Process::get_memory_limit()
182
-	 *
183
-	 * @return int
184
-	 */
185
-	protected function get_memory_limit() {
186
-		if ( function_exists( 'ini_get' ) ) {
187
-			$memory_limit = ini_get( 'memory_limit' );
188
-		} else {
189
-			$memory_limit = '128M'; // Sensible default, and minimum required by WooCommerce
190
-		}
191
-
192
-		if ( ! $memory_limit || -1 === $memory_limit || '-1' === $memory_limit ) {
193
-			// Unlimited, set to 32GB.
194
-			$memory_limit = '32G';
195
-		}
196
-
197
-		return ActionScheduler_Compatibility::convert_hr_to_bytes( $memory_limit );
198
-	}
199
-
200
-	/**
201
-	 * Memory exceeded
202
-	 *
203
-	 * Ensures the batch process never exceeds 90% of the maximum WordPress memory.
204
-	 *
205
-	 * Based on WP_Background_Process::memory_exceeded()
206
-	 *
207
-	 * @return bool
208
-	 */
209
-	protected function memory_exceeded() {
210
-
211
-		$memory_limit    = $this->get_memory_limit() * 0.90;
212
-		$current_memory  = memory_get_usage( true );
213
-		$memory_exceeded = $current_memory >= $memory_limit;
214
-
215
-		return apply_filters( 'action_scheduler_memory_exceeded', $memory_exceeded, $this );
216
-	}
217
-
218
-	/**
219
-	 * See if the batch limits have been exceeded, which is when memory usage is almost at
220
-	 * the maximum limit, or the time to process more actions will exceed the max time limit.
221
-	 *
222
-	 * Based on WC_Background_Process::batch_limits_exceeded()
223
-	 *
224
-	 * @param int $processed_actions The number of actions processed so far - used to determine the likelihood of exceeding the time limit if processing another action
225
-	 * @return bool
226
-	 */
227
-	protected function batch_limits_exceeded( $processed_actions ) {
228
-		return $this->memory_exceeded() || $this->time_likely_to_be_exceeded( $processed_actions );
229
-	}
230
-
231
-	/**
232
-	 * Process actions in the queue.
233
-	 *
234
-	 * @author Jeremy Pry
235
-	 * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
236
-	 *        Generally, this should be capitalised and not localised as it's a proper noun.
237
-	 * @return int The number of actions processed.
238
-	 */
239
-	abstract public function run( $context = '' );
8
+    /** @var ActionScheduler_QueueCleaner */
9
+    protected $cleaner;
10
+
11
+    /** @var ActionScheduler_FatalErrorMonitor */
12
+    protected $monitor;
13
+
14
+    /** @var ActionScheduler_Store */
15
+    protected $store;
16
+
17
+    /**
18
+     * The created time.
19
+     *
20
+     * Represents when the queue runner was constructed and used when calculating how long a PHP request has been running.
21
+     * For this reason it should be as close as possible to the PHP request start time.
22
+     *
23
+     * @var int
24
+     */
25
+    private $created_time;
26
+
27
+    /**
28
+     * ActionScheduler_Abstract_QueueRunner constructor.
29
+     *
30
+     * @param ActionScheduler_Store             $store
31
+     * @param ActionScheduler_FatalErrorMonitor $monitor
32
+     * @param ActionScheduler_QueueCleaner      $cleaner
33
+     */
34
+    public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null ) {
35
+
36
+        $this->created_time = microtime( true );
37
+
38
+        $this->store   = $store ? $store : ActionScheduler_Store::instance();
39
+        $this->monitor = $monitor ? $monitor : new ActionScheduler_FatalErrorMonitor( $this->store );
40
+        $this->cleaner = $cleaner ? $cleaner : new ActionScheduler_QueueCleaner( $this->store );
41
+    }
42
+
43
+    /**
44
+     * Process an individual action.
45
+     *
46
+     * @param int $action_id The action ID to process.
47
+     * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
48
+     *        Generally, this should be capitalised and not localised as it's a proper noun.
49
+     */
50
+    public function process_action( $action_id, $context = '' ) {
51
+        try {
52
+            $valid_action = false;
53
+            do_action( 'action_scheduler_before_execute', $action_id, $context );
54
+
55
+            if ( ActionScheduler_Store::STATUS_PENDING !== $this->store->get_status( $action_id ) ) {
56
+                do_action( 'action_scheduler_execution_ignored', $action_id, $context );
57
+                return;
58
+            }
59
+
60
+            $valid_action = true;
61
+            do_action( 'action_scheduler_begin_execute', $action_id, $context );
62
+
63
+            $action = $this->store->fetch_action( $action_id );
64
+            $this->store->log_execution( $action_id );
65
+            $action->execute();
66
+            do_action( 'action_scheduler_after_execute', $action_id, $action, $context );
67
+            $this->store->mark_complete( $action_id );
68
+        } catch ( Exception $e ) {
69
+            if ( $valid_action ) {
70
+                $this->store->mark_failure( $action_id );
71
+                do_action( 'action_scheduler_failed_execution', $action_id, $e, $context );
72
+            } else {
73
+                do_action( 'action_scheduler_failed_validation', $action_id, $e, $context );
74
+            }
75
+        }
76
+
77
+        if ( isset( $action ) && is_a( $action, 'ActionScheduler_Action' ) && $action->get_schedule()->is_recurring() ) {
78
+            $this->schedule_next_instance( $action, $action_id );
79
+        }
80
+    }
81
+
82
+    /**
83
+     * Schedule the next instance of the action if necessary.
84
+     *
85
+     * @param ActionScheduler_Action $action
86
+     * @param int $action_id
87
+     */
88
+    protected function schedule_next_instance( ActionScheduler_Action $action, $action_id ) {
89
+        try {
90
+            ActionScheduler::factory()->repeat( $action );
91
+        } catch ( Exception $e ) {
92
+            do_action( 'action_scheduler_failed_to_schedule_next_instance', $action_id, $e, $action );
93
+        }
94
+    }
95
+
96
+    /**
97
+     * Run the queue cleaner.
98
+     *
99
+     * @author Jeremy Pry
100
+     */
101
+    protected function run_cleanup() {
102
+        $this->cleaner->clean( 10 * $this->get_time_limit() );
103
+    }
104
+
105
+    /**
106
+     * Get the number of concurrent batches a runner allows.
107
+     *
108
+     * @return int
109
+     */
110
+    public function get_allowed_concurrent_batches() {
111
+        return apply_filters( 'action_scheduler_queue_runner_concurrent_batches', 1 );
112
+    }
113
+
114
+    /**
115
+     * Check if the number of allowed concurrent batches is met or exceeded.
116
+     *
117
+     * @return bool
118
+     */
119
+    public function has_maximum_concurrent_batches() {
120
+        return $this->store->get_claim_count() >= $this->get_allowed_concurrent_batches();
121
+    }
122
+
123
+    /**
124
+     * Get the maximum number of seconds a batch can run for.
125
+     *
126
+     * @return int The number of seconds.
127
+     */
128
+    protected function get_time_limit() {
129
+
130
+        $time_limit = 30;
131
+
132
+        // Apply deprecated filter from deprecated get_maximum_execution_time() method
133
+        if ( has_filter( 'action_scheduler_maximum_execution_time' ) ) {
134
+            _deprecated_function( 'action_scheduler_maximum_execution_time', '2.1.1', 'action_scheduler_queue_runner_time_limit' );
135
+            $time_limit = apply_filters( 'action_scheduler_maximum_execution_time', $time_limit );
136
+        }
137
+
138
+        return absint( apply_filters( 'action_scheduler_queue_runner_time_limit', $time_limit ) );
139
+    }
140
+
141
+    /**
142
+     * Get the number of seconds the process has been running.
143
+     *
144
+     * @return int The number of seconds.
145
+     */
146
+    protected function get_execution_time() {
147
+        $execution_time = microtime( true ) - $this->created_time;
148
+
149
+        // Get the CPU time if the hosting environment uses it rather than wall-clock time to calculate a process's execution time.
150
+        if ( function_exists( 'getrusage' ) && apply_filters( 'action_scheduler_use_cpu_execution_time', defined( 'PANTHEON_ENVIRONMENT' ) ) ) {
151
+            $resource_usages = getrusage();
152
+
153
+            if ( isset( $resource_usages['ru_stime.tv_usec'], $resource_usages['ru_stime.tv_usec'] ) ) {
154
+                $execution_time = $resource_usages['ru_stime.tv_sec'] + ( $resource_usages['ru_stime.tv_usec'] / 1000000 );
155
+            }
156
+        }
157
+
158
+        return $execution_time;
159
+    }
160
+
161
+    /**
162
+     * Check if the host's max execution time is (likely) to be exceeded if processing more actions.
163
+     *
164
+     * @param int $processed_actions The number of actions processed so far - used to determine the likelihood of exceeding the time limit if processing another action
165
+     * @return bool
166
+     */
167
+    protected function time_likely_to_be_exceeded( $processed_actions ) {
168
+
169
+        $execution_time        = $this->get_execution_time();
170
+        $max_execution_time    = $this->get_time_limit();
171
+        $time_per_action       = $execution_time / $processed_actions;
172
+        $estimated_time        = $execution_time + ( $time_per_action * 3 );
173
+        $likely_to_be_exceeded = $estimated_time > $max_execution_time;
174
+
175
+        return apply_filters( 'action_scheduler_maximum_execution_time_likely_to_be_exceeded', $likely_to_be_exceeded, $this, $processed_actions, $execution_time, $max_execution_time );
176
+    }
177
+
178
+    /**
179
+     * Get memory limit
180
+     *
181
+     * Based on WP_Background_Process::get_memory_limit()
182
+     *
183
+     * @return int
184
+     */
185
+    protected function get_memory_limit() {
186
+        if ( function_exists( 'ini_get' ) ) {
187
+            $memory_limit = ini_get( 'memory_limit' );
188
+        } else {
189
+            $memory_limit = '128M'; // Sensible default, and minimum required by WooCommerce
190
+        }
191
+
192
+        if ( ! $memory_limit || -1 === $memory_limit || '-1' === $memory_limit ) {
193
+            // Unlimited, set to 32GB.
194
+            $memory_limit = '32G';
195
+        }
196
+
197
+        return ActionScheduler_Compatibility::convert_hr_to_bytes( $memory_limit );
198
+    }
199
+
200
+    /**
201
+     * Memory exceeded
202
+     *
203
+     * Ensures the batch process never exceeds 90% of the maximum WordPress memory.
204
+     *
205
+     * Based on WP_Background_Process::memory_exceeded()
206
+     *
207
+     * @return bool
208
+     */
209
+    protected function memory_exceeded() {
210
+
211
+        $memory_limit    = $this->get_memory_limit() * 0.90;
212
+        $current_memory  = memory_get_usage( true );
213
+        $memory_exceeded = $current_memory >= $memory_limit;
214
+
215
+        return apply_filters( 'action_scheduler_memory_exceeded', $memory_exceeded, $this );
216
+    }
217
+
218
+    /**
219
+     * See if the batch limits have been exceeded, which is when memory usage is almost at
220
+     * the maximum limit, or the time to process more actions will exceed the max time limit.
221
+     *
222
+     * Based on WC_Background_Process::batch_limits_exceeded()
223
+     *
224
+     * @param int $processed_actions The number of actions processed so far - used to determine the likelihood of exceeding the time limit if processing another action
225
+     * @return bool
226
+     */
227
+    protected function batch_limits_exceeded( $processed_actions ) {
228
+        return $this->memory_exceeded() || $this->time_likely_to_be_exceeded( $processed_actions );
229
+    }
230
+
231
+    /**
232
+     * Process actions in the queue.
233
+     *
234
+     * @author Jeremy Pry
235
+     * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
236
+     *        Generally, this should be capitalised and not localised as it's a proper noun.
237
+     * @return int The number of actions processed.
238
+     */
239
+    abstract public function run( $context = '' );
240 240
 }
Please login to merge, or discard this patch.
Spacing   +46 added lines, -46 removed lines patch added patch discarded remove patch
@@ -31,13 +31,13 @@  discard block
 block discarded – undo
31 31
 	 * @param ActionScheduler_FatalErrorMonitor $monitor
32 32
 	 * @param ActionScheduler_QueueCleaner      $cleaner
33 33
 	 */
34
-	public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null ) {
34
+	public function __construct(ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null) {
35 35
 
36
-		$this->created_time = microtime( true );
36
+		$this->created_time = microtime(true);
37 37
 
38 38
 		$this->store   = $store ? $store : ActionScheduler_Store::instance();
39
-		$this->monitor = $monitor ? $monitor : new ActionScheduler_FatalErrorMonitor( $this->store );
40
-		$this->cleaner = $cleaner ? $cleaner : new ActionScheduler_QueueCleaner( $this->store );
39
+		$this->monitor = $monitor ? $monitor : new ActionScheduler_FatalErrorMonitor($this->store);
40
+		$this->cleaner = $cleaner ? $cleaner : new ActionScheduler_QueueCleaner($this->store);
41 41
 	}
42 42
 
43 43
 	/**
@@ -47,35 +47,35 @@  discard block
 block discarded – undo
47 47
 	 * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
48 48
 	 *        Generally, this should be capitalised and not localised as it's a proper noun.
49 49
 	 */
50
-	public function process_action( $action_id, $context = '' ) {
50
+	public function process_action($action_id, $context = '') {
51 51
 		try {
52 52
 			$valid_action = false;
53
-			do_action( 'action_scheduler_before_execute', $action_id, $context );
53
+			do_action('action_scheduler_before_execute', $action_id, $context);
54 54
 
55
-			if ( ActionScheduler_Store::STATUS_PENDING !== $this->store->get_status( $action_id ) ) {
56
-				do_action( 'action_scheduler_execution_ignored', $action_id, $context );
55
+			if (ActionScheduler_Store::STATUS_PENDING !== $this->store->get_status($action_id)) {
56
+				do_action('action_scheduler_execution_ignored', $action_id, $context);
57 57
 				return;
58 58
 			}
59 59
 
60 60
 			$valid_action = true;
61
-			do_action( 'action_scheduler_begin_execute', $action_id, $context );
61
+			do_action('action_scheduler_begin_execute', $action_id, $context);
62 62
 
63
-			$action = $this->store->fetch_action( $action_id );
64
-			$this->store->log_execution( $action_id );
63
+			$action = $this->store->fetch_action($action_id);
64
+			$this->store->log_execution($action_id);
65 65
 			$action->execute();
66
-			do_action( 'action_scheduler_after_execute', $action_id, $action, $context );
67
-			$this->store->mark_complete( $action_id );
68
-		} catch ( Exception $e ) {
69
-			if ( $valid_action ) {
70
-				$this->store->mark_failure( $action_id );
71
-				do_action( 'action_scheduler_failed_execution', $action_id, $e, $context );
66
+			do_action('action_scheduler_after_execute', $action_id, $action, $context);
67
+			$this->store->mark_complete($action_id);
68
+		} catch (Exception $e) {
69
+			if ($valid_action) {
70
+				$this->store->mark_failure($action_id);
71
+				do_action('action_scheduler_failed_execution', $action_id, $e, $context);
72 72
 			} else {
73
-				do_action( 'action_scheduler_failed_validation', $action_id, $e, $context );
73
+				do_action('action_scheduler_failed_validation', $action_id, $e, $context);
74 74
 			}
75 75
 		}
76 76
 
77
-		if ( isset( $action ) && is_a( $action, 'ActionScheduler_Action' ) && $action->get_schedule()->is_recurring() ) {
78
-			$this->schedule_next_instance( $action, $action_id );
77
+		if (isset($action) && is_a($action, 'ActionScheduler_Action') && $action->get_schedule()->is_recurring()) {
78
+			$this->schedule_next_instance($action, $action_id);
79 79
 		}
80 80
 	}
81 81
 
@@ -85,11 +85,11 @@  discard block
 block discarded – undo
85 85
 	 * @param ActionScheduler_Action $action
86 86
 	 * @param int $action_id
87 87
 	 */
88
-	protected function schedule_next_instance( ActionScheduler_Action $action, $action_id ) {
88
+	protected function schedule_next_instance(ActionScheduler_Action $action, $action_id) {
89 89
 		try {
90
-			ActionScheduler::factory()->repeat( $action );
91
-		} catch ( Exception $e ) {
92
-			do_action( 'action_scheduler_failed_to_schedule_next_instance', $action_id, $e, $action );
90
+			ActionScheduler::factory()->repeat($action);
91
+		} catch (Exception $e) {
92
+			do_action('action_scheduler_failed_to_schedule_next_instance', $action_id, $e, $action);
93 93
 		}
94 94
 	}
95 95
 
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
 	 * @author Jeremy Pry
100 100
 	 */
101 101
 	protected function run_cleanup() {
102
-		$this->cleaner->clean( 10 * $this->get_time_limit() );
102
+		$this->cleaner->clean(10 * $this->get_time_limit());
103 103
 	}
104 104
 
105 105
 	/**
@@ -108,7 +108,7 @@  discard block
 block discarded – undo
108 108
 	 * @return int
109 109
 	 */
110 110
 	public function get_allowed_concurrent_batches() {
111
-		return apply_filters( 'action_scheduler_queue_runner_concurrent_batches', 1 );
111
+		return apply_filters('action_scheduler_queue_runner_concurrent_batches', 1);
112 112
 	}
113 113
 
114 114
 	/**
@@ -130,12 +130,12 @@  discard block
 block discarded – undo
130 130
 		$time_limit = 30;
131 131
 
132 132
 		// Apply deprecated filter from deprecated get_maximum_execution_time() method
133
-		if ( has_filter( 'action_scheduler_maximum_execution_time' ) ) {
134
-			_deprecated_function( 'action_scheduler_maximum_execution_time', '2.1.1', 'action_scheduler_queue_runner_time_limit' );
135
-			$time_limit = apply_filters( 'action_scheduler_maximum_execution_time', $time_limit );
133
+		if (has_filter('action_scheduler_maximum_execution_time')) {
134
+			_deprecated_function('action_scheduler_maximum_execution_time', '2.1.1', 'action_scheduler_queue_runner_time_limit');
135
+			$time_limit = apply_filters('action_scheduler_maximum_execution_time', $time_limit);
136 136
 		}
137 137
 
138
-		return absint( apply_filters( 'action_scheduler_queue_runner_time_limit', $time_limit ) );
138
+		return absint(apply_filters('action_scheduler_queue_runner_time_limit', $time_limit));
139 139
 	}
140 140
 
141 141
 	/**
@@ -144,14 +144,14 @@  discard block
 block discarded – undo
144 144
 	 * @return int The number of seconds.
145 145
 	 */
146 146
 	protected function get_execution_time() {
147
-		$execution_time = microtime( true ) - $this->created_time;
147
+		$execution_time = microtime(true) - $this->created_time;
148 148
 
149 149
 		// Get the CPU time if the hosting environment uses it rather than wall-clock time to calculate a process's execution time.
150
-		if ( function_exists( 'getrusage' ) && apply_filters( 'action_scheduler_use_cpu_execution_time', defined( 'PANTHEON_ENVIRONMENT' ) ) ) {
150
+		if (function_exists('getrusage') && apply_filters('action_scheduler_use_cpu_execution_time', defined('PANTHEON_ENVIRONMENT'))) {
151 151
 			$resource_usages = getrusage();
152 152
 
153
-			if ( isset( $resource_usages['ru_stime.tv_usec'], $resource_usages['ru_stime.tv_usec'] ) ) {
154
-				$execution_time = $resource_usages['ru_stime.tv_sec'] + ( $resource_usages['ru_stime.tv_usec'] / 1000000 );
153
+			if (isset($resource_usages['ru_stime.tv_usec'], $resource_usages['ru_stime.tv_usec'])) {
154
+				$execution_time = $resource_usages['ru_stime.tv_sec'] + ($resource_usages['ru_stime.tv_usec'] / 1000000);
155 155
 			}
156 156
 		}
157 157
 
@@ -164,15 +164,15 @@  discard block
 block discarded – undo
164 164
 	 * @param int $processed_actions The number of actions processed so far - used to determine the likelihood of exceeding the time limit if processing another action
165 165
 	 * @return bool
166 166
 	 */
167
-	protected function time_likely_to_be_exceeded( $processed_actions ) {
167
+	protected function time_likely_to_be_exceeded($processed_actions) {
168 168
 
169 169
 		$execution_time        = $this->get_execution_time();
170 170
 		$max_execution_time    = $this->get_time_limit();
171 171
 		$time_per_action       = $execution_time / $processed_actions;
172
-		$estimated_time        = $execution_time + ( $time_per_action * 3 );
172
+		$estimated_time        = $execution_time + ($time_per_action * 3);
173 173
 		$likely_to_be_exceeded = $estimated_time > $max_execution_time;
174 174
 
175
-		return apply_filters( 'action_scheduler_maximum_execution_time_likely_to_be_exceeded', $likely_to_be_exceeded, $this, $processed_actions, $execution_time, $max_execution_time );
175
+		return apply_filters('action_scheduler_maximum_execution_time_likely_to_be_exceeded', $likely_to_be_exceeded, $this, $processed_actions, $execution_time, $max_execution_time);
176 176
 	}
177 177
 
178 178
 	/**
@@ -183,18 +183,18 @@  discard block
 block discarded – undo
183 183
 	 * @return int
184 184
 	 */
185 185
 	protected function get_memory_limit() {
186
-		if ( function_exists( 'ini_get' ) ) {
187
-			$memory_limit = ini_get( 'memory_limit' );
186
+		if (function_exists('ini_get')) {
187
+			$memory_limit = ini_get('memory_limit');
188 188
 		} else {
189 189
 			$memory_limit = '128M'; // Sensible default, and minimum required by WooCommerce
190 190
 		}
191 191
 
192
-		if ( ! $memory_limit || -1 === $memory_limit || '-1' === $memory_limit ) {
192
+		if (!$memory_limit || -1 === $memory_limit || '-1' === $memory_limit) {
193 193
 			// Unlimited, set to 32GB.
194 194
 			$memory_limit = '32G';
195 195
 		}
196 196
 
197
-		return ActionScheduler_Compatibility::convert_hr_to_bytes( $memory_limit );
197
+		return ActionScheduler_Compatibility::convert_hr_to_bytes($memory_limit);
198 198
 	}
199 199
 
200 200
 	/**
@@ -209,10 +209,10 @@  discard block
 block discarded – undo
209 209
 	protected function memory_exceeded() {
210 210
 
211 211
 		$memory_limit    = $this->get_memory_limit() * 0.90;
212
-		$current_memory  = memory_get_usage( true );
212
+		$current_memory  = memory_get_usage(true);
213 213
 		$memory_exceeded = $current_memory >= $memory_limit;
214 214
 
215
-		return apply_filters( 'action_scheduler_memory_exceeded', $memory_exceeded, $this );
215
+		return apply_filters('action_scheduler_memory_exceeded', $memory_exceeded, $this);
216 216
 	}
217 217
 
218 218
 	/**
@@ -224,8 +224,8 @@  discard block
 block discarded – undo
224 224
 	 * @param int $processed_actions The number of actions processed so far - used to determine the likelihood of exceeding the time limit if processing another action
225 225
 	 * @return bool
226 226
 	 */
227
-	protected function batch_limits_exceeded( $processed_actions ) {
228
-		return $this->memory_exceeded() || $this->time_likely_to_be_exceeded( $processed_actions );
227
+	protected function batch_limits_exceeded($processed_actions) {
228
+		return $this->memory_exceeded() || $this->time_likely_to_be_exceeded($processed_actions);
229 229
 	}
230 230
 
231 231
 	/**
@@ -236,5 +236,5 @@  discard block
 block discarded – undo
236 236
 	 *        Generally, this should be capitalised and not localised as it's a proper noun.
237 237
 	 * @return int The number of actions processed.
238 238
 	 */
239
-	abstract public function run( $context = '' );
239
+	abstract public function run($context = '');
240 240
 }
Please login to merge, or discard this patch.
packages/action-scheduler/classes/ActionScheduler_WPCommentCleaner.php 2 patches
Indentation   +104 added lines, -104 removed lines patch added patch discarded remove patch
@@ -7,109 +7,109 @@
 block discarded – undo
7 7
  */
8 8
 class ActionScheduler_WPCommentCleaner {
9 9
 
10
-	/**
11
-	 * Post migration hook used to cleanup the WP comment table.
12
-	 *
13
-	 * @var string
14
-	 */
15
-	protected static $cleanup_hook = 'action_scheduler/cleanup_wp_comment_logs';
16
-
17
-	/**
18
-	 * An instance of the ActionScheduler_wpCommentLogger class to interact with the comments table.
19
-	 *
20
-	 * This instance should only be used as an interface. It should not be initialized.
21
-	 *
22
-	 * @var ActionScheduler_wpCommentLogger
23
-	 */
24
-	protected static $wp_comment_logger = null;
25
-
26
-	/**
27
-	 * The key used to store the cached value of whether there are logs in the WP comment table.
28
-	 *
29
-	 * @var string
30
-	 */
31
-	protected static $has_logs_option_key = 'as_has_wp_comment_logs';
32
-
33
-	/**
34
-	 * Initialize the class and attach callbacks.
35
-	 */
36
-	public static function init() {
37
-		if ( empty( self::$wp_comment_logger ) ) {
38
-			self::$wp_comment_logger = new ActionScheduler_wpCommentLogger();
39
-		}
40
-
41
-		add_action( self::$cleanup_hook, array( __CLASS__, 'delete_all_action_comments' ) );
42
-
43
-		// While there are orphaned logs left in the comments table, we need to attach the callbacks which filter comment counts.
44
-		add_action( 'pre_get_comments', array( self::$wp_comment_logger, 'filter_comment_queries' ), 10, 1 );
45
-		add_action( 'wp_count_comments', array( self::$wp_comment_logger, 'filter_comment_count' ), 20, 2 ); // run after WC_Comments::wp_count_comments() to make sure we exclude order notes and action logs
46
-		add_action( 'comment_feed_where', array( self::$wp_comment_logger, 'filter_comment_feed' ), 10, 2 );
47
-
48
-		// Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen
49
-		add_action( 'load-tools_page_action-scheduler', array( __CLASS__, 'register_admin_notice' ) );
50
-		add_action( 'load-woocommerce_page_wc-status', array( __CLASS__, 'register_admin_notice' ) );
51
-	}
52
-
53
-	/**
54
-	 * Determines if there are log entries in the wp comments table.
55
-	 *
56
-	 * Uses the flag set on migration completion set by @see self::maybe_schedule_cleanup().
57
-	 *
58
-	 * @return boolean Whether there are scheduled action comments in the comments table.
59
-	 */
60
-	public static function has_logs() {
61
-		return 'yes' === get_option( self::$has_logs_option_key );
62
-	}
63
-
64
-	/**
65
-	 * Schedules the WP Post comment table cleanup to run in 6 months if it's not already scheduled.
66
-	 * Attached to the migration complete hook 'action_scheduler/migration_complete'.
67
-	 */
68
-	public static function maybe_schedule_cleanup() {
69
-		if ( (bool) get_comments( array( 'type' => ActionScheduler_wpCommentLogger::TYPE, 'number' => 1, 'fields' => 'ids' ) ) ) {
70
-			update_option( self::$has_logs_option_key, 'yes' );
71
-
72
-			if ( ! as_next_scheduled_action( self::$cleanup_hook ) ) {
73
-				as_schedule_single_action( gmdate( 'U' ) + ( 6 * MONTH_IN_SECONDS ), self::$cleanup_hook );
74
-			}
75
-		}
76
-	}
77
-
78
-	/**
79
-	 * Delete all action comments from the WP Comments table.
80
-	 */
81
-	public static function delete_all_action_comments() {
82
-		global $wpdb;
83
-		$wpdb->delete( $wpdb->comments, array( 'comment_type' => ActionScheduler_wpCommentLogger::TYPE, 'comment_agent' => ActionScheduler_wpCommentLogger::AGENT ) );
84
-		delete_option( self::$has_logs_option_key );
85
-	}
86
-
87
-	/**
88
-	 * Registers admin notices about the orphaned action logs.
89
-	 */
90
-	public static function register_admin_notice() {
91
-		add_action( 'admin_notices', array( __CLASS__, 'print_admin_notice' ) );
92
-	}
10
+    /**
11
+     * Post migration hook used to cleanup the WP comment table.
12
+     *
13
+     * @var string
14
+     */
15
+    protected static $cleanup_hook = 'action_scheduler/cleanup_wp_comment_logs';
16
+
17
+    /**
18
+     * An instance of the ActionScheduler_wpCommentLogger class to interact with the comments table.
19
+     *
20
+     * This instance should only be used as an interface. It should not be initialized.
21
+     *
22
+     * @var ActionScheduler_wpCommentLogger
23
+     */
24
+    protected static $wp_comment_logger = null;
25
+
26
+    /**
27
+     * The key used to store the cached value of whether there are logs in the WP comment table.
28
+     *
29
+     * @var string
30
+     */
31
+    protected static $has_logs_option_key = 'as_has_wp_comment_logs';
32
+
33
+    /**
34
+     * Initialize the class and attach callbacks.
35
+     */
36
+    public static function init() {
37
+        if ( empty( self::$wp_comment_logger ) ) {
38
+            self::$wp_comment_logger = new ActionScheduler_wpCommentLogger();
39
+        }
40
+
41
+        add_action( self::$cleanup_hook, array( __CLASS__, 'delete_all_action_comments' ) );
42
+
43
+        // While there are orphaned logs left in the comments table, we need to attach the callbacks which filter comment counts.
44
+        add_action( 'pre_get_comments', array( self::$wp_comment_logger, 'filter_comment_queries' ), 10, 1 );
45
+        add_action( 'wp_count_comments', array( self::$wp_comment_logger, 'filter_comment_count' ), 20, 2 ); // run after WC_Comments::wp_count_comments() to make sure we exclude order notes and action logs
46
+        add_action( 'comment_feed_where', array( self::$wp_comment_logger, 'filter_comment_feed' ), 10, 2 );
47
+
48
+        // Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen
49
+        add_action( 'load-tools_page_action-scheduler', array( __CLASS__, 'register_admin_notice' ) );
50
+        add_action( 'load-woocommerce_page_wc-status', array( __CLASS__, 'register_admin_notice' ) );
51
+    }
52
+
53
+    /**
54
+     * Determines if there are log entries in the wp comments table.
55
+     *
56
+     * Uses the flag set on migration completion set by @see self::maybe_schedule_cleanup().
57
+     *
58
+     * @return boolean Whether there are scheduled action comments in the comments table.
59
+     */
60
+    public static function has_logs() {
61
+        return 'yes' === get_option( self::$has_logs_option_key );
62
+    }
63
+
64
+    /**
65
+     * Schedules the WP Post comment table cleanup to run in 6 months if it's not already scheduled.
66
+     * Attached to the migration complete hook 'action_scheduler/migration_complete'.
67
+     */
68
+    public static function maybe_schedule_cleanup() {
69
+        if ( (bool) get_comments( array( 'type' => ActionScheduler_wpCommentLogger::TYPE, 'number' => 1, 'fields' => 'ids' ) ) ) {
70
+            update_option( self::$has_logs_option_key, 'yes' );
71
+
72
+            if ( ! as_next_scheduled_action( self::$cleanup_hook ) ) {
73
+                as_schedule_single_action( gmdate( 'U' ) + ( 6 * MONTH_IN_SECONDS ), self::$cleanup_hook );
74
+            }
75
+        }
76
+    }
77
+
78
+    /**
79
+     * Delete all action comments from the WP Comments table.
80
+     */
81
+    public static function delete_all_action_comments() {
82
+        global $wpdb;
83
+        $wpdb->delete( $wpdb->comments, array( 'comment_type' => ActionScheduler_wpCommentLogger::TYPE, 'comment_agent' => ActionScheduler_wpCommentLogger::AGENT ) );
84
+        delete_option( self::$has_logs_option_key );
85
+    }
86
+
87
+    /**
88
+     * Registers admin notices about the orphaned action logs.
89
+     */
90
+    public static function register_admin_notice() {
91
+        add_action( 'admin_notices', array( __CLASS__, 'print_admin_notice' ) );
92
+    }
93 93
 	
94
-	/**
95
-	 * Prints details about the orphaned action logs and includes information on where to learn more.
96
-	 */
97
-	public static function print_admin_notice() {
98
-		$next_cleanup_message        = '';
99
-		$next_scheduled_cleanup_hook = as_next_scheduled_action( self::$cleanup_hook );
100
-
101
-		if ( $next_scheduled_cleanup_hook ) {
102
-			/* translators: %s: date interval */
103
-			$next_cleanup_message = sprintf( __( 'This data will be deleted in %s.', 'woocommerce' ), human_time_diff( gmdate( 'U' ), $next_scheduled_cleanup_hook ) );
104
-		}
105
-
106
-		$notice = sprintf(
107
-			/* translators: 1: next cleanup message 2: github issue URL */
108
-			__( 'Action Scheduler has migrated data to custom tables; however, orphaned log entries exist in the WordPress Comments table. %1$s <a href="%2$s">Learn more &raquo;</a>', 'woocommerce' ),
109
-			$next_cleanup_message,
110
-			'https://github.com/woocommerce/action-scheduler/issues/368'
111
-		);
112
-
113
-		echo '<div class="notice notice-warning"><p>' . wp_kses_post( $notice ) . '</p></div>';
114
-	}
94
+    /**
95
+     * Prints details about the orphaned action logs and includes information on where to learn more.
96
+     */
97
+    public static function print_admin_notice() {
98
+        $next_cleanup_message        = '';
99
+        $next_scheduled_cleanup_hook = as_next_scheduled_action( self::$cleanup_hook );
100
+
101
+        if ( $next_scheduled_cleanup_hook ) {
102
+            /* translators: %s: date interval */
103
+            $next_cleanup_message = sprintf( __( 'This data will be deleted in %s.', 'woocommerce' ), human_time_diff( gmdate( 'U' ), $next_scheduled_cleanup_hook ) );
104
+        }
105
+
106
+        $notice = sprintf(
107
+            /* translators: 1: next cleanup message 2: github issue URL */
108
+            __( 'Action Scheduler has migrated data to custom tables; however, orphaned log entries exist in the WordPress Comments table. %1$s <a href="%2$s">Learn more &raquo;</a>', 'woocommerce' ),
109
+            $next_cleanup_message,
110
+            'https://github.com/woocommerce/action-scheduler/issues/368'
111
+        );
112
+
113
+        echo '<div class="notice notice-warning"><p>' . wp_kses_post( $notice ) . '</p></div>';
114
+    }
115 115
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -34,20 +34,20 @@  discard block
 block discarded – undo
34 34
 	 * Initialize the class and attach callbacks.
35 35
 	 */
36 36
 	public static function init() {
37
-		if ( empty( self::$wp_comment_logger ) ) {
37
+		if (empty(self::$wp_comment_logger)) {
38 38
 			self::$wp_comment_logger = new ActionScheduler_wpCommentLogger();
39 39
 		}
40 40
 
41
-		add_action( self::$cleanup_hook, array( __CLASS__, 'delete_all_action_comments' ) );
41
+		add_action(self::$cleanup_hook, array(__CLASS__, 'delete_all_action_comments'));
42 42
 
43 43
 		// While there are orphaned logs left in the comments table, we need to attach the callbacks which filter comment counts.
44
-		add_action( 'pre_get_comments', array( self::$wp_comment_logger, 'filter_comment_queries' ), 10, 1 );
45
-		add_action( 'wp_count_comments', array( self::$wp_comment_logger, 'filter_comment_count' ), 20, 2 ); // run after WC_Comments::wp_count_comments() to make sure we exclude order notes and action logs
46
-		add_action( 'comment_feed_where', array( self::$wp_comment_logger, 'filter_comment_feed' ), 10, 2 );
44
+		add_action('pre_get_comments', array(self::$wp_comment_logger, 'filter_comment_queries'), 10, 1);
45
+		add_action('wp_count_comments', array(self::$wp_comment_logger, 'filter_comment_count'), 20, 2); // run after WC_Comments::wp_count_comments() to make sure we exclude order notes and action logs
46
+		add_action('comment_feed_where', array(self::$wp_comment_logger, 'filter_comment_feed'), 10, 2);
47 47
 
48 48
 		// Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen
49
-		add_action( 'load-tools_page_action-scheduler', array( __CLASS__, 'register_admin_notice' ) );
50
-		add_action( 'load-woocommerce_page_wc-status', array( __CLASS__, 'register_admin_notice' ) );
49
+		add_action('load-tools_page_action-scheduler', array(__CLASS__, 'register_admin_notice'));
50
+		add_action('load-woocommerce_page_wc-status', array(__CLASS__, 'register_admin_notice'));
51 51
 	}
52 52
 
53 53
 	/**
@@ -58,7 +58,7 @@  discard block
 block discarded – undo
58 58
 	 * @return boolean Whether there are scheduled action comments in the comments table.
59 59
 	 */
60 60
 	public static function has_logs() {
61
-		return 'yes' === get_option( self::$has_logs_option_key );
61
+		return 'yes' === get_option(self::$has_logs_option_key);
62 62
 	}
63 63
 
64 64
 	/**
@@ -66,11 +66,11 @@  discard block
 block discarded – undo
66 66
 	 * Attached to the migration complete hook 'action_scheduler/migration_complete'.
67 67
 	 */
68 68
 	public static function maybe_schedule_cleanup() {
69
-		if ( (bool) get_comments( array( 'type' => ActionScheduler_wpCommentLogger::TYPE, 'number' => 1, 'fields' => 'ids' ) ) ) {
70
-			update_option( self::$has_logs_option_key, 'yes' );
69
+		if ((bool) get_comments(array('type' => ActionScheduler_wpCommentLogger::TYPE, 'number' => 1, 'fields' => 'ids'))) {
70
+			update_option(self::$has_logs_option_key, 'yes');
71 71
 
72
-			if ( ! as_next_scheduled_action( self::$cleanup_hook ) ) {
73
-				as_schedule_single_action( gmdate( 'U' ) + ( 6 * MONTH_IN_SECONDS ), self::$cleanup_hook );
72
+			if (!as_next_scheduled_action(self::$cleanup_hook)) {
73
+				as_schedule_single_action(gmdate('U') + (6 * MONTH_IN_SECONDS), self::$cleanup_hook);
74 74
 			}
75 75
 		}
76 76
 	}
@@ -80,15 +80,15 @@  discard block
 block discarded – undo
80 80
 	 */
81 81
 	public static function delete_all_action_comments() {
82 82
 		global $wpdb;
83
-		$wpdb->delete( $wpdb->comments, array( 'comment_type' => ActionScheduler_wpCommentLogger::TYPE, 'comment_agent' => ActionScheduler_wpCommentLogger::AGENT ) );
84
-		delete_option( self::$has_logs_option_key );
83
+		$wpdb->delete($wpdb->comments, array('comment_type' => ActionScheduler_wpCommentLogger::TYPE, 'comment_agent' => ActionScheduler_wpCommentLogger::AGENT));
84
+		delete_option(self::$has_logs_option_key);
85 85
 	}
86 86
 
87 87
 	/**
88 88
 	 * Registers admin notices about the orphaned action logs.
89 89
 	 */
90 90
 	public static function register_admin_notice() {
91
-		add_action( 'admin_notices', array( __CLASS__, 'print_admin_notice' ) );
91
+		add_action('admin_notices', array(__CLASS__, 'print_admin_notice'));
92 92
 	}
93 93
 	
94 94
 	/**
@@ -96,20 +96,20 @@  discard block
 block discarded – undo
96 96
 	 */
97 97
 	public static function print_admin_notice() {
98 98
 		$next_cleanup_message        = '';
99
-		$next_scheduled_cleanup_hook = as_next_scheduled_action( self::$cleanup_hook );
99
+		$next_scheduled_cleanup_hook = as_next_scheduled_action(self::$cleanup_hook);
100 100
 
101
-		if ( $next_scheduled_cleanup_hook ) {
101
+		if ($next_scheduled_cleanup_hook) {
102 102
 			/* translators: %s: date interval */
103
-			$next_cleanup_message = sprintf( __( 'This data will be deleted in %s.', 'woocommerce' ), human_time_diff( gmdate( 'U' ), $next_scheduled_cleanup_hook ) );
103
+			$next_cleanup_message = sprintf(__('This data will be deleted in %s.', 'woocommerce'), human_time_diff(gmdate('U'), $next_scheduled_cleanup_hook));
104 104
 		}
105 105
 
106 106
 		$notice = sprintf(
107 107
 			/* translators: 1: next cleanup message 2: github issue URL */
108
-			__( 'Action Scheduler has migrated data to custom tables; however, orphaned log entries exist in the WordPress Comments table. %1$s <a href="%2$s">Learn more &raquo;</a>', 'woocommerce' ),
108
+			__('Action Scheduler has migrated data to custom tables; however, orphaned log entries exist in the WordPress Comments table. %1$s <a href="%2$s">Learn more &raquo;</a>', 'woocommerce'),
109 109
 			$next_cleanup_message,
110 110
 			'https://github.com/woocommerce/action-scheduler/issues/368'
111 111
 		);
112 112
 
113
-		echo '<div class="notice notice-warning"><p>' . wp_kses_post( $notice ) . '</p></div>';
113
+		echo '<div class="notice notice-warning"><p>' . wp_kses_post($notice) . '</p></div>';
114 114
 	}
115 115
 }
Please login to merge, or discard this patch.