PluginProbe ʕ •ᴥ•ʔ
OttoKit: All-in-One Automation Platform / 1.0.75
OttoKit: All-in-One Automation Platform v1.0.75
1.1.31 1.1.30 1.1.29 1.1.28 1.1.27 1.1.9 trunk 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 1.0.39 1.0.40 1.0.41 1.0.42 1.0.43 1.0.44 1.0.45 1.0.46 1.0.47 1.0.48 1.0.49 1.0.50 1.0.51 1.0.52 1.0.53 1.0.54 1.0.55 1.0.56 1.0.57 1.0.58 1.0.59 1.0.60 1.0.61 1.0.62 1.0.63 1.0.64 1.0.65 1.0.66 1.0.67 1.0.68 1.0.69 1.0.7 1.0.70 1.0.71 1.0.72 1.0.73 1.0.74 1.0.75 1.0.76 1.0.77 1.0.78 1.0.79 1.0.8 1.0.80 1.0.81 1.0.82 1.0.83 1.0.84 1.0.85 1.0.86 1.0.87 1.0.88 1.0.89 1.0.9 1.0.90 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.20 1.1.21 1.1.22 1.1.23 1.1.24 1.1.25 1.1.26 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8
suretriggers / src / Controllers / WebhookRequestsController.php
suretriggers / src / Controllers Last commit date
AuthController.php 1 year ago AutomationController.php 3 years ago EventController.php 3 years ago GlobalSearchController.php 1 year ago IntegrationsController.php 2 years ago OptionController.php 3 years ago RestController.php 1 year ago RoutesController.php 1 year ago SettingsController.php 3 years ago WebhookRequestsController.php 1 year ago
WebhookRequestsController.php
334 lines
1 <?php
2 /**
3 * WebhookRequestsController.
4 * php version 5.6
5 *
6 * @category WebhookRequestsController
7 * @package SureTriggers
8 * @author BSF <username@example.com>
9 * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
10 * @link https://www.brainstormforce.com/
11 * @since 1.0.0
12 */
13
14 namespace SureTriggers\Controllers;
15
16 use SureTriggers\Traits\SingletonLoader;
17 use SureTriggers\Models\SaasApiToken;
18 use SureTriggers\Controllers\RestController;
19
20 /**
21 * WebhookRequestsController- Store Webhook requests and retry for failed.
22 *
23 * @category WebhookRequestsController
24 * @package SureTriggers
25 * @author BSF <username@example.com>
26 * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
27 * @link https://www.brainstormforce.com/
28 * @since 1.0.0
29 *
30 * @psalm-suppress UndefinedTrait
31 */
32 class WebhookRequestsController {
33
34 use SingletonLoader;
35
36 /**
37 * Webhook Requests Table name.
38 *
39 * @var string
40 */
41 protected static $name = 'suretriggers_webhook_requests';
42
43 /**
44 * Initialise data.
45 */
46 public function __construct() {
47 add_action( 'suretriggers_retry_failed_requests', [ $this, 'suretriggers_retry_failed_trigger_requests' ] );
48 add_action( 'suretriggers_webhook_requests_cleanup_logs', [ $this, 'suretriggers_cleanup_requests_logs' ] );
49 add_action( 'suretriggers_verify_api_connection', [ $this, 'suretriggers_verify_api_wp_connection' ] );
50 add_filter( 'cron_schedules', [ $this, 'suretriggers_custom_cron_schedule' ] );
51 }
52
53 /**
54 * Get the table name.
55 *
56 * @return string
57 */
58 public static function get_table_name() {
59 global $wpdb;
60 return $wpdb->prefix . self::$name;
61 }
62
63 /**
64 * Adds a custom cron schedule for every 30 minutes.
65 *
66 * @param array $schedules An array of non-default cron schedules.
67 * @return array Filtered array of non-default cron schedules.
68 */
69 public static function suretriggers_custom_cron_schedule( $schedules ) {
70 $schedules['suretriggers_retry_cron_schedule'] = [
71 'interval' => 30 * MINUTE_IN_SECONDS,
72 'display' => __( 'Every 30 minutes', 'suretriggers' ),
73 ];
74 return $schedules;
75 }
76
77 /**
78 * Custom table for storing of webhook requests logs.
79 *
80 * @return void
81 */
82 public static function suretriggers_webhook_request_log_table() {
83 global $wpdb;
84 $table_name = self::get_table_name();
85 $charset_collate = $wpdb->get_charset_collate();
86
87 $sql = "CREATE TABLE $table_name (
88 id mediumint(9) NOT NULL AUTO_INCREMENT,
89 request_method varchar(255) NULL,
90 request_url varchar(255) NOT NULL,
91 request_data longtext NOT NULL,
92 response_code int(3) NOT NULL,
93 status varchar(20) NOT NULL,
94 error_info varchar(255) NOT NULL,
95 retry_attempts int(3) DEFAULT 0,
96 processed_at datetime NULL,
97 created_at datetime,
98 updated_at datetime ON UPDATE CURRENT_TIMESTAMP,
99 PRIMARY KEY (id)
100 ) $charset_collate;";
101
102 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
103 dbDelta( $sql );
104 }
105
106 /**
107 * Setup cron to retry failed webhook requests and cleanup logs for Triggers.
108 *
109 * @return void
110 */
111 public static function suretriggers_setup_custom_cron() {
112 // Retry failed requests.
113 if ( ! wp_next_scheduled( 'suretriggers_retry_failed_requests' ) ) {
114 wp_schedule_event( time(), 'suretriggers_retry_cron_schedule', 'suretriggers_retry_failed_requests' );
115 }
116
117 // Clean up log requests that are older than 15 days.
118 if ( ! wp_next_scheduled( 'suretriggers_webhook_requests_cleanup_logs' ) ) {
119 wp_schedule_event( time(), 'daily', 'suretriggers_webhook_requests_cleanup_logs' );
120 }
121
122 // Verify the API connection every 12 hours to keep the connection alive.
123 if ( ! wp_next_scheduled( 'suretriggers_verify_api_connection' ) ) {
124 wp_schedule_event( time(), 'twicedaily', 'suretriggers_verify_api_connection' );
125 }
126 }
127
128 /**
129 * Log Request handler.
130 *
131 * @param string $data Request data.
132 * @param int $response_code Response Code.
133 * @param string $error_info Error Info.
134 *
135 * @return void
136 */
137 public static function suretriggers_log_request( $data, $response_code, $error_info ) {
138 global $wpdb;
139 // Store the data in request logs.
140 $wpdb->insert(
141 self::get_table_name(),
142 [
143 'request_method' => 'POST',
144 'request_url' => SURE_TRIGGERS_WEBHOOK_SERVER_URL . '/wordpress/webhook',
145 'request_data' => $data,
146 'response_code' => $response_code,
147 'status' => ( 200 === $response_code ) ? 'success' : 'failed',
148 'error_info' => $error_info,
149 'retry_attempts' => 0,
150 'processed_at' => null,
151 'created_at' => current_time( 'mysql' ),
152 'updated_at' => current_time( 'mysql' ),
153 ]
154 );
155 }
156
157 /**
158 * Update Failed Webhook Request handler via cron.
159 *
160 * @return void
161 */
162 public static function suretriggers_retry_failed_trigger_requests() {
163 global $wpdb;
164 $table_name = self::get_table_name();
165
166 // Select all failed requests that haven't exceeded retry attempts.
167 $failed_requests = $wpdb->get_results(
168 $wpdb->prepare(
169 "SELECT * FROM {$table_name} WHERE status = %s AND retry_attempts < %d", //phpcs:ignore
170 'failed',
171 5
172 ),
173 ARRAY_A
174 );
175
176 foreach ( $failed_requests as $request ) {
177 $data = json_decode( $request['request_data'], true );
178 if ( is_array( $data ) ) {
179 $data['headers']['Authorization'] = 'Bearer ' . SaasApiToken::get();
180 $response = wp_remote_post( $request['request_url'], $data );
181 $response_code = wp_remote_retrieve_response_code( $response );
182 $error_info = wp_remote_retrieve_body( $response );
183 if ( 405 === $response_code ) {
184 $error_info = wp_remote_retrieve_response_message( $response );
185 }
186 if ( 0 === $response_code ) {
187 $error_info = __( 'Service not available', 'suretriggers' );
188 }
189 // Update the request if failed with the new response.
190 $wpdb->update(
191 $table_name,
192 [
193 'request_method' => $request['request_method'],
194 'request_url' => $request['request_url'],
195 'request_data' => $request['request_data'],
196 'response_code' => $response_code,
197 'status' => ( 200 === $response_code ) ? 'success' : 'failed',
198 'error_info' => $error_info,
199 'retry_attempts' => $request['retry_attempts'] + 1,
200 'processed_at' => current_time( 'mysql' ),
201 'updated_at' => current_time( 'mysql' ),
202 ],
203 [ 'id' => $request['id'] ]
204 );
205 }
206 }
207 }
208
209 /**
210 * Update Failed Webhook Request handler via Retry button.
211 *
212 * @param int $id ID.
213 *
214 * @return bool
215 */
216 public static function suretriggers_retry_trigger_request( $id ) {
217 global $wpdb;
218 $table_name = self::get_table_name();
219 $failed_requests = $wpdb->get_row(
220 $wpdb->prepare(
221 "SELECT * FROM {$table_name} WHERE id = %d", //phpcs:ignore
222 $id
223 ),
224 ARRAY_A
225 );
226
227 $data = json_decode( $failed_requests['request_data'], true );
228 if ( is_array( $data ) ) {
229 $data['headers']['Authorization'] = 'Bearer ' . SaasApiToken::get();
230 $response = wp_remote_post( $failed_requests['request_url'], $data );
231 $response_code = wp_remote_retrieve_response_code( $response );
232 $error_info = wp_remote_retrieve_body( $response );
233 if ( 405 === wp_remote_retrieve_response_code( $response ) ) {
234 $error_info = wp_remote_retrieve_response_message( $response );
235 }
236 if ( 0 === wp_remote_retrieve_response_code( $response ) ) {
237 $error_info = __( 'Service not available', 'suretriggers' );
238 }
239 $wpdb->update(
240 $table_name,
241 [
242 'request_method' => $failed_requests['request_method'],
243 'request_url' => $failed_requests['request_url'],
244 'request_data' => $failed_requests['request_data'],
245 'response_code' => $response_code,
246 'status' => ( 200 === $response_code ) ? 'success' : 'failed',
247 'error_info' => $error_info,
248 'retry_attempts' => $failed_requests['retry_attempts'] + 1,
249 'processed_at' => current_time( 'mysql' ),
250 'updated_at' => current_time( 'mysql' ),
251 ],
252 [ 'id' => $id ]
253 );
254 return true;
255 }
256 return false;
257 }
258
259 /**
260 * Delete failed webhook requests log that are 60 days older.
261 * Delete success webhook requests log that are 30 days older.
262 *
263 * @return void
264 */
265 public static function suretriggers_cleanup_requests_logs() {
266 global $wpdb;
267 $table_name = self::get_table_name();
268 $wpdb->query( $wpdb->prepare( "DELETE FROM {$table_name} WHERE status = %s AND created_at < NOW() - INTERVAL %d DAY", 'failed', 60 ) ); //phpcs:ignore
269 $wpdb->query( $wpdb->prepare( "DELETE FROM {$table_name} WHERE status = %s AND created_at < NOW() - INTERVAL %d DAY", 'success', 30 ) ); //phpcs:ignore
270 }
271
272 /**
273 * Verify WordPress connection with SureTriggers API to check the connection status twice daily.
274 *
275 * @return void
276 */
277 public static function suretriggers_verify_api_wp_connection() {
278 $response = RestController::suretriggers_verify_wp_connection();
279 // Check if the response is valid.
280 if ( is_wp_error( $response ) ) {
281 update_option( 'suretriggers_verify_connection', 'suretriggers_connection_wp_error' );
282 } else {
283 $status_code = wp_remote_retrieve_response_code( $response );
284 if ( 200 !== $status_code ) {
285 update_option( 'suretriggers_verify_connection', 'suretriggers_connection_error' );
286 } else {
287 update_option( 'suretriggers_verify_connection', 'suretriggers_connection_successful' );
288 }
289 }
290 }
291
292 /**
293 * Unschedule the event on plugin deletion.
294 *
295 * @return void
296 */
297 public static function suretriggers_remove_table_retry_cron() {
298 // Clear custom scheduled cron created.
299 wp_clear_scheduled_hook( 'suretriggers_retry_cron_schedule' );
300
301 // Remove retry cron schedule on plugin deletion.
302 $retry_failed_requests = wp_next_scheduled( 'suretriggers_retry_failed_requests' );
303 if ( $retry_failed_requests ) {
304 wp_unschedule_event( $retry_failed_requests, 'suretriggers_retry_failed_requests' );
305 }
306
307 // Remove clean up cron schedule.
308 $webhook_requests_cleanup = wp_next_scheduled( 'suretriggers_webhook_requests_cleanup_logs' );
309 if ( $webhook_requests_cleanup ) {
310 wp_unschedule_event( $webhook_requests_cleanup, 'suretriggers_webhook_requests_cleanup_logs' );
311 }
312
313 // Remove connection verification cron schedule.
314 $webhook_requests_cleanup = wp_next_scheduled( 'suretriggers_verify_api_connection' );
315 if ( $webhook_requests_cleanup ) {
316 wp_unschedule_event( $webhook_requests_cleanup, 'suretriggers_verify_api_connection' );
317 }
318
319 // Delete table on plugin delete.
320 global $wpdb;
321 $table_name = self::get_table_name();
322 // Drop the custom table.
323 $table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) );
324 if ( $table_exists ) {
325 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
326 $sql = "DROP TABLE IF EXISTS $table_name";
327 dbDelta( $sql );
328 }
329 }
330
331 }
332
333 WebhookRequestsController::get_instance();
334