/
class-rest-api.php
159 lines (139 loc) · 4.31 KB
/
class-rest-api.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<?php
/**
* Plugin's REST API
*
* @package a8c_Cron_Control
*/
namespace Automattic\WP\Cron_Control;
/**
* REST API class
*/
class REST_API extends Singleton {
/**
* API SETUP
*/
const API_NAMESPACE = 'cron-control/v1';
const ENDPOINT_LIST = 'events';
const ENDPOINT_RUN = 'event';
/**
* PLUGIN SETUP
*/
/**
* Register hooks
*/
protected function class_init() {
add_action( 'rest_api_init', array( $this, 'rest_api_init' ) );
}
/**
* PLUGIN FUNCTIONALITY
*/
/**
* Register API routes
*/
public function rest_api_init() {
register_rest_route(
self::API_NAMESPACE,
'/' . self::ENDPOINT_LIST,
array(
'methods' => 'POST',
'callback' => array( $this, 'get_events' ),
'permission_callback' => array( $this, 'check_secret' ),
'show_in_index' => false,
)
);
register_rest_route(
self::API_NAMESPACE,
'/' . self::ENDPOINT_RUN,
array(
'methods' => 'PUT',
'callback' => array( $this, 'run_event' ),
'permission_callback' => array( $this, 'check_secret' ),
'show_in_index' => false,
)
);
}
/**
* List events pending for the current period
*
* For monitoring and alerting, also provides the total number of pending events
*/
public function get_events() {
$response_array = array(
'events' => array(),
'orchestrate_disabled' => Events::instance()->run_disabled(),
);
// Include events only when automatic execution is enabled.
if ( 0 === $response_array['orchestrate_disabled'] ) {
$response_array = array_merge( $response_array, Events::instance()->get_events() );
}
$response_array['endpoint'] = get_rest_url( null, self::API_NAMESPACE . '/' . self::ENDPOINT_RUN );
// Provide pending event count for monitoring etc.
$response_array['total_events_pending'] = count_events_by_status( Events_Store::STATUS_PENDING );
return rest_ensure_response( $response_array );
}
/**
* Execute a specific event
*
* @param object $request REST API request object.
* @return object
*/
public function run_event( $request ) {
// Stop if event execution is .
$run_disabled = Events::instance()->run_disabled();
if ( 0 !== $run_disabled ) {
if ( 1 === $run_disabled ) {
$message = __( 'Automatic event execution is disabled indefinitely.', 'automattic-cron-control' );
} else {
/* translators: 1: Time automatic execution is disabled until, 2: Unix timestamp */
$message = sprintf( __( 'Automatic event execution is disabled until %1$s UTC (%2$d).', 'automattic-cron-control' ), date_i18n( TIME_FORMAT, $run_disabled ), $run_disabled );
}
return rest_ensure_response(
new \WP_Error(
'automatic-execution-disabled',
$message,
array(
'status' => 403,
)
)
);
}
// Parse request for details needed to identify the event to execute.
// `$timestamp` is, unsurprisingly, the Unix timestamp the event is scheduled for.
// `$action` is the md5 hash of the action used when the event is registered.
// `$instance` is the md5 hash of the event's arguments array, which Core uses to index the `cron` option.
$event = $request->get_json_params();
$timestamp = isset( $event['timestamp'] ) ? absint( $event['timestamp'] ) : null;
$action = isset( $event['action'] ) ? trim( sanitize_text_field( $event['action'] ) ) : null;
$instance = isset( $event['instance'] ) ? trim( sanitize_text_field( $event['instance'] ) ) : null;
return rest_ensure_response( run_event( $timestamp, $action, $instance ) );
}
/**
* Check if request is authorized
*
* @param object $request REST API request object.
* @return bool|\WP_Error
*/
public function check_secret( $request ) {
if ( false === \WP_CRON_CONTROL_SECRET ) {
return new \WP_Error(
'api-disabled',
__( 'Cron Control REST API endpoints are disabled', 'automattic-cron-control' ),
array(
'status' => 403,
)
);
}
$body = $request->get_json_params();
// For now, mimic original plugin's "authentication" method. This needs to be better.
if ( ! isset( $body['secret'] ) || ! hash_equals( \WP_CRON_CONTROL_SECRET, $body['secret'] ) ) {
return new \WP_Error(
'no-secret',
__( 'Secret must be specified with all requests', 'automattic-cron-control' ),
array(
'status' => 400,
)
);
}
return true;
}
}