Completed
Push — add/jetpack_connection_new_met... ( 975e37...16d930 )
by
unknown
25:10 queued 15:42
created

Jetpack_JSON_API_Cron_Schedule_Endpoint   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 52
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 52
rs 10
c 0
b 0
f 0
wmc 11
lcom 1
cbo 2

1 Method

Rating   Name   Duplication   Size   Complexity  
B result() 0 49 11
1
<?php
2
3
// GET /sites/%s/cron
4
class Jetpack_JSON_API_Cron_Endpoint extends Jetpack_JSON_API_Endpoint {
5
	protected $needed_capabilities = 'manage_options';
6
7
	protected function validate_call( $_blog_id, $capability, $check_manage_active = true ) {
8
		return parent::validate_call( $_blog_id, $capability, false );
9
	}
10
11
	protected function result() {
12
		return array(
13
			'cron_array' => _get_cron_array(),
14
			'current_timestamp' => time()
15
		);
16
	}
17
18
	protected function sanitize_hook( $hook ) {
19
		return preg_replace( '/[^A-Za-z0-9-_]/', '', $hook );
20
	}
21
22
	protected function resolve_arguments() {
23
		$args = $this->input();
24
		return  isset( $args['arguments'] ) ? json_decode( $args['arguments'] ) : array();
25
	}
26
27
	protected function is_cron_locked( $gmt_time ) {
28
		// The cron lock: a unix timestamp from when the cron was spawned.
29
		$doing_cron_transient = $this->get_cron_lock();
30
		if ( $doing_cron_transient && ( $doing_cron_transient + WP_CRON_LOCK_TIMEOUT > $gmt_time )  ) {
31
			return new WP_Error( 'cron-is-locked', 'Current there is a cron already happening.', 403 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'cron-is-locked'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
32
		}
33
		return $doing_cron_transient;
34
	}
35
36
	protected function maybe_unlock_cron( $doing_wp_cron ) {
37
		if ( $this->get_cron_lock() == $doing_wp_cron ) {
38
			delete_transient( 'doing_cron' );
39
		}
40
	}
41
42
	protected function lock_cron() {
43
		$lock = sprintf( '%.22F', microtime( true ) );
44
		set_transient( 'doing_cron', $lock );
45
		return $lock;
46
	}
47
48
	protected function get_schedules( $hook, $args ) {
49
		$crons = _get_cron_array();
50
		$key = md5(serialize($args));
51
		if ( empty( $crons ) )
52
			return array();
53
		$found = array();
54
		foreach ( $crons as $timestamp => $cron ) {
55
			if ( isset( $cron[$hook][$key] ) )
56
				$found[] = $timestamp;
57
		}
58
59
		return $found;
60
	}
61
62
	/**
63
	 * This function is based on the one found in wp-cron.php with a similar name
64
	 * @return int
65
	 */
66
	protected function get_cron_lock() {
67
		global $wpdb;
68
69
		$value = 0;
70
		if ( wp_using_ext_object_cache() ) {
71
			/*
72
			 * Skip local cache and force re-fetch of doing_cron transient
73
			 * in case another process updated the cache.
74
			 */
75
			$value = wp_cache_get( 'doing_cron', 'transient', true );
76
		} else {
77
			$row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", '_transient_doing_cron' ) );
78
			if ( is_object( $row ) ) {
79
				$value = $row->option_value;
80
			}
81
		}
82
		return $value;
83
	}
84
}
85
86
// POST /sites/%s/cron
87
class Jetpack_JSON_API_Cron_Post_Endpoint extends Jetpack_JSON_API_Cron_Endpoint {
88
89
	protected function result() {
90
		define( 'DOING_CRON', true );
91
		set_time_limit( 0 );
92
		$args = $this->input();
93
94
		if ( false === $crons = _get_cron_array() ) {
95
			return new WP_Error( 'no-cron-event', 'Currently there are no cron events', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'no-cron-event'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
96
		}
97
98
		$timestamps_to_run = array_keys( $crons );
99
		$gmt_time = microtime( true );
100
101
		if ( isset( $timestamps_to_run[0] ) && $timestamps_to_run[0] > $gmt_time ) {
102
			return new WP_Error( 'no-cron-event', 'Currently there are no cron events ready to be run', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'no-cron-event'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
103
		}
104
105
		$locked = $this->is_cron_locked( $gmt_time );
106
		if ( is_wp_error( $locked ) ) {
107
			return $locked;
108
		}
109
110
		$lock = $this->lock_cron();
111
		$processed_events = array();
112
113
		foreach ( $crons as $timestamp => $cronhooks ) {
114
			if ( $timestamp > $gmt_time && ! isset( $args[ 'hook' ] ) ) {
115
				break;
116
			}
117
118
			foreach ( $cronhooks as $hook => $hook_data ) {
119
				if ( isset( $args[ 'hook' ] ) && ! in_array( $hook, $args['hook'] ) ) {
120
					continue;
121
				}
122
123
				foreach ( $hook_data as $hash => $hook_item ) {
124
125
					$schedule = $hook_item['schedule'];
126
					$arguments = $hook_item['args'];
127
128
					if ( $schedule != false ) {
129
						wp_reschedule_event( $timestamp, $schedule, $hook, $arguments );
130
					}
131
132
					wp_unschedule_event( $timestamp, $hook, $arguments );
133
134
					do_action_ref_array( $hook, $arguments );
135
					$processed_events[] = array( $hook => $arguments );
136
137
					// If the hook ran too long and another cron process stole the lock,
138
					// or if we things are taking longer then 20 seconds then quit.
139
					if ( ( $this->get_cron_lock() != $lock ) || ( $gmt_time + 20 > microtime( true ) ) ) {
140
						$this->maybe_unlock_cron( $lock );
141
						return array( 'success' => $processed_events );
142
					}
143
144
				}
145
			}
146
		}
147
148
		$this->maybe_unlock_cron( $lock );
149
		return array( 'success' => $processed_events );
150
	}
151
}
152
153
// POST /sites/%s/cron/schedule
154
class Jetpack_JSON_API_Cron_Schedule_Endpoint extends Jetpack_JSON_API_Cron_Endpoint {
155
156
	protected function result() {
157
		$args = $this->input();
158
		if ( ! isset( $args['timestamp'] ) ) {
159
			return new WP_Error( 'missing_argument', 'Please provide the timestamp argument', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'missing_argument'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
160
		}
161
162
		if ( ! is_int( $args['timestamp'] ) || $args['timestamp'] < time() ) {
163
			return new WP_Error( 'timestamp-invalid', 'Please provide timestamp that is an integer and set in the future', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'timestamp-invalid'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
164
		}
165
166
		if ( ! isset( $args['hook'] ) ) {
167
			return new WP_Error( 'missing_argument', 'Please provide the hook argument', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'missing_argument'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
168
		}
169
170
		$hook = $this->sanitize_hook( $args['hook'] );
171
172
		$locked = $this->is_cron_locked( microtime( true ) );
173
		if ( is_wp_error( $locked ) ) {
174
			return $locked;
175
		}
176
177
		$arguments = $this->resolve_arguments();
178
		$next_scheduled = $this->get_schedules( $hook, $arguments );
179
180
		if ( isset( $args['recurrence'] ) ) {
181
			$schedules = wp_get_schedules();
182
			if ( ! isset( $schedules[ $args['recurrence'] ] ) ) {
183
				return new WP_Error( 'invalid-recurrence', 'Please provide a valid recurrence argument', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid-recurrence'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
184
			}
185
186
			if ( count( $next_scheduled ) > 0 ) {
187
				return new WP_Error( 'event-already-scheduled', 'This event is ready scheduled', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'event-already-scheduled'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
188
			}
189
			$lock = $this->lock_cron();
190
			wp_schedule_event( $args['timestamp'], $args['recurrence'], $hook, $arguments );
191
			$this->maybe_unlock_cron( $lock );
192
			return array( 'success' => true );
193
		}
194
195
		foreach( $next_scheduled as $scheduled_time ) {
196
			if ( abs( $scheduled_time - $args['timestamp'] ) <= 10 * MINUTE_IN_SECONDS ) {
197
				return new WP_Error( 'event-already-scheduled', 'This event is ready scheduled', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'event-already-scheduled'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
198
			}
199
		}
200
		$lock = $this->lock_cron();
201
		$next = wp_schedule_single_event( $args['timestamp'], $hook, $arguments );
202
		$this->maybe_unlock_cron( $lock );
203
		return array( 'success' => $next );
204
	}
205
}
206
207
// POST /sites/%s/cron/unschedule
208
class Jetpack_JSON_API_Cron_Unschedule_Endpoint extends Jetpack_JSON_API_Cron_Endpoint {
209
210
	protected function result() {
211
		$args = $this->input();
212
213
		if ( !isset( $args['hook'] ) ) {
214
			return new WP_Error( 'missing_argument', 'Please provide the hook argument', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'missing_argument'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
215
		}
216
217
		$hook = $this->sanitize_hook( $args['hook'] );
218
219
		$locked = $this->is_cron_locked( microtime( true ) );
220
		if ( is_wp_error( $locked ) ) {
221
			return $locked;
222
		}
223
224
		$crons = _get_cron_array();
225
		if ( empty( $crons ) ) {
226
			return new WP_Error( 'cron-not-present', 'Unable to unschedule an event, no events in the cron', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'cron-not-present'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
227
		}
228
229
		$arguments = $this->resolve_arguments();
230
231
		if ( isset( $args['timestamp'] ) ) {
232
			$next_schedulded = $this->get_schedules( $hook, $arguments );
233
			if ( in_array( $args['timestamp'], $next_schedulded ) ) {
234
				return new WP_Error( 'event-not-present', 'Unable to unschedule the event, the event doesn\'t exist', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'event-not-present'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
235
			}
236
237
			$lock = $this->lock_cron();
238
			wp_unschedule_event( $args['timestamp'], $hook, $arguments );
239
			$this->maybe_unlock_cron( $lock );
240
			return array( 'success' => true );
241
		}
242
		$lock = $this->lock_cron();
243
		wp_clear_scheduled_hook( $hook, $arguments );
244
		$this->maybe_unlock_cron( $lock );
245
		return array( 'success' => true );
246
	}
247
}
248