PluginProbe
Social Media Auto Poster – Schedule & Publish to Buffer / 6.2.1
Social Media Auto Poster – Schedule & Publish to Buffer v6.2.1
6.2.5 6.2.4 6.2.3 6.2.2 6.2.1 6.2.0 6.1.2 6.1.1 6.1.0 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 6.0.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 All 126 releases
wp-to-buffer / lib / social / includes / class-cron.php

class-cron.php in Social Media Auto Poster – Schedule & Publish to Buffer 6.2.1, at lib/social/includes/class-cron.php

422 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Cron class.
4 *
5 * @package WPZinc\Social
6 * @author WP Zinc
7 */
8
9 namespace WPZinc\Social;
10
11 /**
12 * Functions to schedule, reschedule and unschedule events with WordPress' Cron for
13 * - Log Cleanup (old log entries that are no longer needed)
14 * - Media Cleanup (images auto generated by the Plugin that are no longer needed)
15 *
16 * @package WPZinc\Social
17 * @author WP Zinc
18 * @version 3.7.2
19 */
20 class Cron {
21
22 /**
23 * Holds the base class object.
24 *
25 * @since 3.7.2
26 *
27 * @var object
28 */
29 public $base;
30
31 /**
32 * Constructor
33 *
34 * @since 3.7.2
35 *
36 * @param object $base Base Plugin Class.
37 */
38 public function __construct( $base ) {
39
40 // Store base class.
41 $this->base = $base;
42
43 }
44
45 /**
46 * Schedules the log cleanup event in the WordPress CRON on a daily basis
47 *
48 * @since 3.9.8
49 */
50 public function schedule_log_cleanup_event() {
51
52 // Bail if the preserve logs settings is indefinite.
53 if ( ! $this->base->get_class( 'settings' )->get_setting( 'log', '[preserve_days]' ) ) {
54 return;
55 }
56
57 // Bail if the scheduled event already exists.
58 $scheduled_event = $this->get_log_cleanup_event();
59 if ( $scheduled_event !== false ) {
60 return;
61 }
62
63 // Schedule event.
64 $scheduled_date_time = gmdate( 'Y-m-d', strtotime( '+1 day' ) ) . ' 00:00:00';
65 wp_schedule_event( strtotime( $scheduled_date_time ), 'daily', $this->base->plugin->filter_name . '_log_cleanup_cron' );
66
67 }
68
69 /**
70 * Unschedules the log cleanup event in the WordPress CRON.
71 *
72 * @since 3.9.8
73 */
74 public function unschedule_log_cleanup_event() {
75
76 wp_clear_scheduled_hook( $this->base->plugin->filter_name . '_log_cleanup_cron' );
77
78 }
79
80 /**
81 * Reschedules the log cleanup event in the WordPress CRON, by unscheduling
82 * and scheduling it.
83 *
84 * @since 3.9.8
85 */
86 public function reschedule_log_cleanup_event() {
87
88 $this->unschedule_log_cleanup_event();
89 $this->schedule_log_cleanup_event();
90
91 }
92
93 /**
94 * Returns the scheduled log cleanup event, if it exists
95 *
96 * @since 3.9.8
97 */
98 public function get_log_cleanup_event() {
99
100 return wp_get_schedule( $this->base->plugin->filter_name . '_log_cleanup_cron' );
101
102 }
103
104 /**
105 * Returns the scheduled log cleanup event's next date and time to run, if it exists
106 *
107 * @since 3.9.8
108 *
109 * @param mixed $format Format Timestamp (false | php date() compat. string).
110 */
111 public function get_log_cleanup_event_next_scheduled( $format = false ) {
112
113 // Get timestamp for when the event will next run.
114 $scheduled = wp_next_scheduled( $this->base->plugin->filter_name . '_log_cleanup_cron' );
115
116 // If no timestamp or we're not formatting the result, return it now.
117 if ( ! $scheduled || ! $format ) {
118 return $scheduled;
119 }
120
121 // Return formatted date/time.
122 return gmdate( $format, $scheduled );
123 }
124
125 /**
126 * Runs the log cleanup CRON event
127 *
128 * @since 3.9.8
129 */
130 public function log_cleanup() {
131
132 // Bail if the preserve logs settings is indefinite.
133 // We shouldn't ever call this function if this is the case, but it's a useful sanity check.
134 $preserve_days = $this->base->get_class( 'settings' )->get_setting( 'log', '[preserve_days]' );
135 if ( ! $preserve_days ) {
136 return;
137 }
138
139 // Define the date cutoff.
140 $date_time = gmdate( 'Y-m-d H:i:s', strtotime( '-' . $preserve_days . ' days' ) );
141 // Delete log entries older than the date.
142 $this->base->get_class( 'log' )->delete_by_request_sent_cutoff( $date_time );
143
144 }
145
146 /**
147 * Schedules the media cleanup event in the WordPress CRON on a daily basis
148 *
149 * @since 4.2.0
150 */
151 public function schedule_media_cleanup_event() {
152
153 // Bail if the scheduled event already exists.
154 $scheduled_event = $this->get_media_cleanup_event();
155 if ( $scheduled_event !== false ) {
156 return;
157 }
158
159 // Schedule event.
160 $scheduled_date_time = gmdate( 'Y-m-d', strtotime( '+1 day' ) ) . ' 01:00:00';
161 wp_schedule_event( strtotime( $scheduled_date_time ), 'daily', $this->base->plugin->filter_name . '_media_cleanup_cron' );
162
163 }
164
165 /**
166 * Unschedules the media cleanup event in the WordPress CRON.
167 *
168 * @since 4.2.0
169 */
170 public function unschedule_media_cleanup_event() {
171
172 wp_clear_scheduled_hook( $this->base->plugin->filter_name . '_media_cleanup_cron' );
173
174 }
175
176 /**
177 * Reschedules the media cleanup event in the WordPress CRON, by unscheduling
178 * and scheduling it.
179 *
180 * @since 4.2.0
181 */
182 public function reschedule_media_cleanup_event() {
183
184 $this->unschedule_media_cleanup_event();
185 $this->schedule_media_cleanup_event();
186
187 }
188
189 /**
190 * Returns the scheduled media cleanup event, if it exists
191 *
192 * @since 4.2.0
193 */
194 public function get_media_cleanup_event() {
195
196 return wp_get_schedule( $this->base->plugin->filter_name . '_media_cleanup_cron' );
197
198 }
199
200 /**
201 * Returns the scheduled media cleanup event's next date and time to run, if it exists
202 *
203 * @since 4.2.0
204 *
205 * @param mixed $format Format Timestamp (false | php date() compat. string).
206 */
207 public function get_media_cleanup_event_next_scheduled( $format = false ) {
208
209 // Get timestamp for when the event will next run.
210 $scheduled = wp_next_scheduled( $this->base->plugin->filter_name . '_media_cleanup_cron' );
211
212 // If no timestamp or we're not formatting the result, return it now.
213 if ( ! $scheduled || ! $format ) {
214 return $scheduled;
215 }
216
217 // Return formatted date/time.
218 return gmdate( $format, $scheduled );
219 }
220
221 /**
222 * Schedules a single event in the WordPress CRON to refresh the access token(s)
223 * shortly before the earliest one expires.
224 *
225 * Access tokens are short lived and refresh tokens are single use, so refreshing
226 * proactively avoids requests failing with an authentication error, and avoids
227 * several requests attempting to refresh using the same refresh token at once.
228 *
229 * @since 6.2.0
230 */
231 public function schedule_refresh_token_event() {
232
233 // Clear any existing scheduled event.
234 $this->unschedule_refresh_token_event();
235
236 // Get the earliest expiry timestamp across all connected accounts.
237 $token_expires = $this->get_earliest_token_expiry();
238
239 // Bail only if no account has a refresh token.
240 if ( $token_expires === false ) {
241 return;
242 }
243
244 // The default number of seconds before an access token expires to refresh it.
245 $seconds = 5 * MINUTE_IN_SECONDS;
246
247 /**
248 * The number of seconds before an access token expires to refresh it.
249 *
250 * @since 6.2.0
251 *
252 * @param int $seconds Seconds before expiry.
253 */
254 $seconds = apply_filters( $this->base->plugin->filter_name . '_cron_refresh_token_seconds_before_expiry', $seconds );
255
256 // Determine when to refresh.
257 $refresh_at = $token_expires - $seconds;
258
259 // If the refresh time is in the past, schedule the event for 1 minute from now.
260 if ( $refresh_at <= time() ) {
261 $refresh_at = time() + MINUTE_IN_SECONDS;
262 }
263
264 // Schedule event.
265 wp_schedule_single_event( $refresh_at, $this->base->plugin->filter_name . '_refresh_token_cron' );
266
267 }
268
269 /**
270 * Unschedules the refresh token event in the WordPress CRON.
271 *
272 * @since 6.2.0
273 */
274 public function unschedule_refresh_token_event() {
275
276 wp_clear_scheduled_hook( $this->base->plugin->filter_name . '_refresh_token_cron' );
277
278 }
279
280 /**
281 * Reschedules the refresh token event in the WordPress CRON, based on the expiry
282 * of the stored access token(s).
283 *
284 * Called on upgrade, so that sites connected before this event existed get one
285 * scheduled without having to reconnect, and whenever a token is issued or
286 * refreshed, so that each token schedules the refresh of its successor.
287 *
288 * @since 6.2.0
289 */
290 public function reschedule_refresh_token_event() {
291
292 $this->schedule_refresh_token_event();
293
294 }
295
296 /**
297 * Returns the scheduled refresh token event, if it exists
298 *
299 * @since 6.2.0
300 *
301 * @return mixed bool | string
302 */
303 public function get_refresh_token_event() {
304
305 return wp_get_schedule( $this->base->plugin->filter_name . '_refresh_token_cron' );
306
307 }
308
309 /**
310 * Returns the scheduled refresh token event's next date and time to run, if it exists
311 *
312 * @since 6.2.0
313 *
314 * @param mixed $format Format Timestamp (false | php date() compat. string).
315 * @return mixed bool | int | string
316 */
317 public function get_refresh_token_event_next_scheduled( $format = false ) {
318
319 // Get timestamp for when the event will next run.
320 $scheduled = wp_next_scheduled( $this->base->plugin->filter_name . '_refresh_token_cron' );
321
322 // If no timestamp or we're not formatting the result, return it now.
323 if ( ! $scheduled || ! $format ) {
324 return $scheduled;
325 }
326
327 // Return formatted date/time.
328 return gmdate( $format, $scheduled );
329
330 }
331
332 /**
333 * Returns the earliest access token expiry timestamp across all connected accounts.
334 *
335 * Accounts holding a refresh token but no expiry timestamp are treated as due now,
336 * returning zero, so that an event is still scheduled for them.
337 *
338 * @since 6.2.0
339 *
340 * @return mixed false | int false if no account has a refresh token.
341 */
342 private function get_earliest_token_expiry() {
343
344 $earliest = false;
345
346 foreach ( $this->base->get_class( 'settings' )->get_accounts() as $account ) {
347 // Skip accounts with no refresh token, as there's nothing to refresh with.
348 if ( empty( $account['refresh_token'] ) ) {
349 continue;
350 }
351
352 // An account with no stored expiry is treated as due now, so that an
353 // event is still scheduled for it.
354 $token_expires = ( empty( $account['token_expires'] ) ? 0 : (int) $account['token_expires'] );
355
356 // Compare against false explicitly, as a zero timestamp is a valid value
357 // here and would otherwise be treated as "not yet set".
358 if ( $earliest === false || $token_expires < $earliest ) {
359 $earliest = $token_expires;
360 }
361 }
362
363 return $earliest;
364
365 }
366
367 /**
368 * Runs the refresh token CRON event, exchanging each stored refresh token that is
369 * due to expire for a new access token.
370 *
371 * The API class fires an action on a successful refresh, which stores the new
372 * access token, refresh token and expiry against the account.
373 *
374 * @since 6.2.0
375 */
376 public function refresh_token() {
377
378 // Bail if the API class cannot refresh tokens, for example where the service
379 // issues a token that does not expire.
380 if ( ! method_exists( $this->base->get_class( 'api' ), 'refresh_token' ) ) {
381 return;
382 }
383
384 // The default number of seconds before an access token expires to refresh it.
385 $seconds = 5 * MINUTE_IN_SECONDS;
386
387 /**
388 * The number of seconds before an access token expires to refresh it.
389 *
390 * @since 6.2.0
391 *
392 * @param int $seconds Seconds before expiry.
393 */
394 $seconds = apply_filters( $this->base->plugin->filter_name . '_cron_refresh_token_seconds_before_expiry', $seconds );
395
396 // Iterate through accounts, refreshing any access token that is due to expire.
397 foreach ( $this->base->get_class( 'settings' )->get_accounts() as $account ) {
398 // Skip accounts with no refresh token, as there's nothing to refresh with.
399 if ( empty( $account['refresh_token'] ) ) {
400 continue;
401 }
402
403 // Skip accounts whose access token isn't due to expire yet.
404 if ( ! empty( $account['token_expires'] ) && (int) $account['token_expires'] > ( time() + $seconds ) ) {
405 continue;
406 }
407
408 // Refresh this account's access token.
409 $this->base->get_class( 'api' )->set_tokens(
410 $account['access_token'],
411 $account['refresh_token'],
412 $account['token_expires']
413 );
414 $this->base->get_class( 'api' )->refresh_token();
415 }
416
417 // Schedule the next event based on what is now stored.
418 $this->schedule_refresh_token_event();
419
420 }
421 }
422