PluginProbe
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI / 6.0.3
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI v6.0.3
6.0.3 6.0.2 6.0.1 6.0.0 5.8.6 5.8.5 5.8.4 5.8.3 5.8.2 5.8.1 5.8.0 5.7.9.2 5.7.9.1 5.7.8 5.7.9 5.7.6 5.7.7 5.7.5 5.7.4 5.7.3 5.7.2 5.7.1 trunk 5.6.0 5.6.1 All 34 releases
← All changes | includes/ajax-functions.php +1128 -0 5.8.3 → 6.0.3 View file →
@@ -1,0 +1,1128 @@
1 +<?php
2 +/**
3 + * Ajax Functions
4 + *
5 + * @package AutomatorWP\Ajax_Functions
6 + * @author AutomatorWP <[email protected]>, Ruben Garcia <[email protected]>
7 + * @since 1.0.0
8 + */
9 +// Exit if accessed directly
10 +if( !defined( 'ABSPATH' ) ) exit;
11 +
12 +/**
13 + * Add an automation trigger/action through ajax
14 + *
15 + * @since 1.0.0
16 + */
17 +function automatorwp_ajax_add_automation_item() {
18 + // Security check, forces to die if not security passed
19 + check_ajax_referer( 'automatorwp_admin', 'nonce' );
20 +
21 + // Permissions check
22 + if( ! current_user_can( automatorwp_get_manager_capability() ) ) {
23 + wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'automatorwp' ) );
24 + }
25 +
26 + // Sanitize parameters
27 + $automation_id = absint( $_POST['automation_id'] );
28 + $type = sanitize_text_field( $_POST['type'] ); // The trigger or action reference
29 + $item_type = sanitize_text_field( $_POST['item_type'] ); // 'trigger' or 'action'
30 + $position = absint( $_POST['position'] );
31 +
32 + // Check parameters
33 + if( $automation_id === 0 ) {
34 + wp_send_json_error( __( 'Invalid automation.', 'automatorwp' ) );
35 + }
36 +
37 + $automation = automatorwp_get_automation_object( $automation_id );
38 +
39 + if( ! $automation ) {
40 + wp_send_json_error( __( 'Invalid automation.', 'automatorwp' ) );
41 + }
42 +
43 + if( ! in_array( $item_type, array( 'trigger', 'action' ) ) ) {
44 + wp_send_json_error( __( 'Invalid item type.', 'automatorwp' ) );
45 + }
46 +
47 + ct_setup_table( "automatorwp_{$item_type}s" );
48 +
49 + if( $item_type === 'trigger' ) {
50 + $type_args = automatorwp_get_trigger( $type );
51 + } else if( $item_type === 'action' ) {
52 + $type_args = automatorwp_get_action( $type );
53 + }
54 +
55 + if( ! $type_args ) {
56 + if( $item_type === 'trigger' ) {
57 + wp_send_json_error( __( 'Invalid trigger.', 'automatorwp' ) );
58 + } else if( $item_type === 'action' ) {
59 + wp_send_json_error( __( 'Invalid action.', 'automatorwp' ) );
60 + }
61 + }
62 +
63 + $object = array(
64 + 'automation_id' => $automation_id,
65 + 'title' => '',
66 + 'type' => $type,
67 + 'status' => 'active',
68 + 'position' => $position,
69 + 'date' => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
70 + );
71 +
72 + // Create the new trigger
73 + $id = ct_insert_object( $object );
74 +
75 + // Initialize trigger options
76 + if( $id ) {
77 +
78 + // Append the id to the trigger data
79 + $object['id'] = $id;
80 +
81 + // Loop all options looking for their fields
82 + foreach( $type_args['options'] as $option => $args ) {
83 +
84 + // Loop all option fields to initialize them
85 + foreach( $args['fields'] as $field_id => $field_args ) {
86 +
87 + if( isset( $field_args['default'] ) ) {
88 + ct_update_object_meta( $id, $field_id, $field_args['default'] );
89 + }
90 +
91 + }
92 +
93 + }
94 +
95 + // Update the trigger title
96 + ct_update_object( array(
97 + 'id' => $id,
98 + 'title' => automatorwp_parse_automation_item_edit_label( (object) $object, $item_type, 'view' )
99 + ) );
100 + }
101 +
102 + ct_reset_setup_table();
103 +
104 + // Flush cache to ensure that option replacement gets the newest value
105 + wp_cache_flush();
106 +
107 + if( $id ) {
108 +
109 + // Append the trigger html
110 + ob_start();
111 + automatorwp_automation_item_edit_html( (object) $object, $item_type, $automation );
112 + $edit_html = ob_get_clean();
113 +
114 + $tags_html = '';
115 +
116 + if( $item_type === 'trigger' )
117 + delete_transient( 'automatorwp_triggers_in_use' );
118 + else if( $item_type === 'action' )
119 + delete_transient( 'automatorwp_actions_in_use' );
120 +
121 + // Set up the trigger tags html
122 + if( $item_type === 'trigger' ) {
123 +
124 + // Get the trigger tags
125 + $tags = automatorwp_get_trigger_tags( (object) $object );
126 +
127 + if( ! empty( $tags ) && isset( $tags[$id] ) ) {
128 + $tags_html = automatorwp_get_tags_selector_group_html( $id, $tags[$id] );
129 + }
130 +
131 + }
132 +
133 + // Set up the action tags html
134 + if( $item_type === 'action' ) {
135 +
136 + // Get the action tags
137 + $tags = automatorwp_get_action_tags( (object) $object );
138 +
139 + if( ! empty( $tags ) && isset( $tags[$id] ) ) {
140 + $tags_html = automatorwp_get_tags_selector_group_html( $id, $tags[$id] );
141 + }
142 + }
143 +
144 + // Send back a successful response
145 + wp_send_json_success( array(
146 + $item_type => $object,
147 + 'edit_html' => $edit_html,
148 + 'tags_html' => $tags_html,
149 + ) );
150 + } else {
151 + if( $item_type === 'trigger' )
152 + wp_send_json_error( __( 'Trigger can\'t be created.', 'automatorwp' ) );
153 + else if( $item_type === 'action' )
154 + wp_send_json_error( __( 'Action can\'t be created.', 'automatorwp' ) );
155 + }
156 +
157 +}
158 +add_action( 'wp_ajax_automatorwp_add_automation_item', 'automatorwp_ajax_add_automation_item' );
159 +
160 +/**
161 + * Delete an automation trigger/action through ajax
162 + *
163 + * @since 1.0.0
164 + */
165 +function automatorwp_ajax_delete_automation_item() {
166 + // Security check, forces to die if not security passed
167 + check_ajax_referer( 'automatorwp_admin', 'nonce' );
168 +
169 + // Permissions check
170 + if( ! current_user_can( automatorwp_get_manager_capability() ) ) {
171 + wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'automatorwp' ) );
172 + }
173 +
174 + // Sanitize parameters
175 + $id = absint( $_POST['id'] );
176 + $item_type = sanitize_text_field( $_POST['item_type'] ); // 'trigger' or 'action'
177 +
178 + // Check parameters
179 + if( $id === 0 ) {
180 + wp_send_json_error( __( 'Invalid item.', 'automatorwp' ) );
181 + }
182 +
183 + if( ! in_array( $item_type, array( 'trigger', 'action' ) ) ) {
184 + wp_send_json_error( __( 'Invalid item type.', 'automatorwp' ) );
185 + }
186 +
187 + ct_setup_table( "automatorwp_{$item_type}s" );
188 +
189 + ct_delete_object( $id );
190 +
191 + ct_reset_setup_table();
192 +
193 + if( $item_type === 'trigger' )
194 + delete_transient( 'automatorwp_triggers_in_use' );
195 + else if( $item_type === 'action' )
196 + delete_transient( 'automatorwp_actions_in_use' );
197 +
198 + // Send back a successful response
199 + wp_send_json_success( __( 'Item deleted.', 'automatorwp' ) );
200 +}
201 +add_action( 'wp_ajax_automatorwp_delete_automation_item', 'automatorwp_ajax_delete_automation_item' );
202 +
203 +/**
204 + * Update automation triggers/actions order through ajax
205 + *
206 + * @since 1.0.0
207 + */
208 +function automatorwp_ajax_update_automation_items_order() {
209 +
210 + // Security check, forces to die if not security passed
211 + check_ajax_referer( 'automatorwp_admin', 'nonce' );
212 +
213 + // Permissions check
214 + if( ! current_user_can( automatorwp_get_manager_capability() ) ) {
215 + wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'automatorwp' ) );
216 + }
217 +
218 + // Sanitize parameters
219 + $items_order = $_POST['items_order']; // Sanitized before
220 + $item_type = sanitize_text_field( $_POST['item_type'] ); // 'trigger' or 'action'
221 +
222 + // Check parameters
223 + if( ! is_array( $items_order ) ) {
224 + wp_send_json_error( __( 'Invalid items.', 'automatorwp' ) );
225 + }
226 +
227 + if( empty( $items_order ) ) {
228 + wp_send_json_error( __( 'Invalid items.', 'automatorwp' ) );
229 + }
230 +
231 + if( ! in_array( $item_type, array( 'trigger', 'action' ) ) ) {
232 + wp_send_json_error( __( 'Invalid item type.', 'automatorwp' ) );
233 + }
234 +
235 + ct_setup_table( "automatorwp_{$item_type}s" );
236 +
237 + foreach( $items_order as $id => $position ) {
238 +
239 + // Sanitize id and position
240 + $id = absint( $id );
241 + $position = absint( $position );
242 +
243 + // Skip if not ID provided
244 + if( $id === 0 ) {
245 + continue;
246 + }
247 +
248 + // Update item position
249 + ct_update_object( array(
250 + 'id' => $id,
251 + 'position' => $position,
252 + ) );
253 + }
254 +
255 + ct_reset_setup_table();
256 +
257 + // Send back a successful response
258 + wp_send_json_error( __( 'Items order updated.', 'automatorwp' ) );
259 +
260 +}
261 +add_action( 'wp_ajax_automatorwp_update_automation_items_order', 'automatorwp_ajax_update_automation_items_order' );
262 +
263 +/**
264 + * Update a trigger option through ajax
265 + *
266 + * @since 1.0.0
267 + */
268 +function automatorwp_ajax_update_item_option() {
269 +
270 + // Security check, forces to die if not security passed
271 + check_ajax_referer( 'automatorwp_admin', 'nonce' );
272 +
273 + // Permissions check
274 + if( ! current_user_can( automatorwp_get_manager_capability() ) ) {
275 + wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'automatorwp' ) );
276 + }
277 +
278 + // Sanitize parameters
279 + $id = absint( $_POST['id'] );
280 + $item_type = sanitize_text_field( $_POST['item_type'] );
281 + $option = sanitize_text_field( $_POST['option_name'] );
282 +
283 + // Check parameters
284 + if( $id === 0 ) {
285 + wp_send_json_error( __( 'Invalid trigger.', 'automatorwp' ) );
286 + }
287 +
288 + if( ! in_array( $item_type, array( 'trigger', 'action' ) ) ) {
289 + wp_send_json_error( __( 'Invalid item type.', 'automatorwp' ) );
290 + }
291 +
292 + if( $item_type === 'trigger' ) {
293 + $automation = automatorwp_get_trigger_automation( $id );
294 + } else if( $item_type === 'action' ) {
295 + $automation = automatorwp_get_action_automation( $id );
296 + }
297 +
298 + ct_setup_table( "automatorwp_{$item_type}s" );
299 +
300 + // Check object
301 + $object = ct_get_object( $id );
302 +
303 + ct_reset_setup_table();
304 +
305 + if( ! $object ) {
306 + wp_send_json_error( __( 'Invalid item.', 'automatorwp' ) );
307 + }
308 +
309 + $type_args = automatorwp_automation_item_type_args( $object, $item_type );
310 +
311 + // Check if trigger is registered
312 + if( ! $type_args ) {
313 + wp_send_json_error( __( 'Invalid item.', 'automatorwp' ) );
314 + }
315 +
316 + // Get the option form
317 + $cmb2 = automatorwp_get_automation_item_option_form( $object, $item_type, $option, $automation );
318 +
319 + if( ! $cmb2 ) {
320 + wp_send_json_error( __( 'Invalid option.', 'automatorwp' ) );
321 + }
322 +
323 + // Get option sanitized values
324 + $sanitized_values = $cmb2->get_sanitized_values( $_POST );
325 +
326 + // Fields not in sanitized values need to recover its default value
327 + foreach ( $type_args['options'][$option]['fields'] as $field_id => $field ) {
328 +
329 + // Skip fields in sanitized values
330 + if( isset( $sanitized_values[$field_id] ) ) {
331 + continue;
332 + }
333 +
334 + // If field has a default value, add it to the array of sanitize values
335 + if( isset( $field['default'] ) ) {
336 + $sanitized_values[$field_id] = sanitize_text_field( $field['default'] );
337 + }
338 +
339 + }
340 +
341 + // Field groups requires a custom way to handle their values saving
342 + foreach ( $type_args['options'][$option]['fields'] as $field_id => $field ) {
343 +
344 + // Skip fields that are not group
345 + if( $field['type'] !== 'group' ) {
346 + continue;
347 + }
348 +
349 + // Skip group fields that have not been received any value
350 + if( ! isset( $_POST[$field_id] ) ) {
351 + continue;
352 + }
353 +
354 + if( ! is_array( $_POST[$field_id] ) ) {
355 + continue;
356 + }
357 +
358 + $sanitized_values[$field_id] = array();
359 +
360 + // Group fields are correctly setup on $_POST and needs get sanitized
361 + foreach( $_POST[$field_id] as $i => $field_values ) {
362 +
363 + $values = array();
364 +
365 + foreach( $field_values as $field_group_id => $value ) {
366 +
367 + // Skip if this field is not registered
368 + if( ! isset( $field['fields'][$field_group_id] ) ) {
369 + continue;
370 + }
371 +
372 + if( ! empty( $value ) ) {
373 + // Add the value from $_POST
374 + $values[$field_group_id] = sanitize_text_field( $value );
375 + } else if( isset( $field['fields'][$field_group_id]['default'] ) ) {
376 + // If field has a default value, add it to the array of sanitize values
377 + $values[$field_group_id] = sanitize_text_field( $field['fields'][$field_group_id]['default'] );
378 + }
379 + }
380 +
381 + $sanitized_values[$field_id][] = $values;
382 +
383 + }
384 +
385 + }
386 +
387 + // Setup the table here to ensure to store meta data on the correct table
388 + ct_setup_table( "automatorwp_{$item_type}s" );
389 +
390 + foreach( $sanitized_values as $field_id => $value ) {
391 + ct_update_object_meta( $object->id, $field_id, $value );
392 + }
393 +
394 + // Flush cache to ensure that option replacement gets the newest value
395 + wp_cache_flush();
396 +
397 + // Update the trigger title
398 + ct_update_object( array(
399 + 'id' => $id,
400 + 'title' => automatorwp_parse_automation_item_edit_label( $object, $item_type, 'view' )
401 + ) );
402 +
403 + ct_reset_setup_table();
404 +
405 + $tags_html = '';
406 +
407 + // Setup the tags html
408 + if( $item_type === 'trigger' ) {
409 + // Get the trigger tags
410 + $tags = automatorwp_get_trigger_tags( (object) $object );
411 +
412 + if( ! empty( $tags ) && isset( $tags[$id] ) ) {
413 + $tags_html = automatorwp_get_tags_selector_group_html( $id, $tags[$id] );
414 + }
415 + }
416 +
417 + $response = array(
418 + 'edit_html' => automatorwp_parse_automation_item_edit_label( (object) $object, $item_type ),
419 + 'tags_html' => $tags_html
420 + );
421 +
422 + // Setup the tags html
423 + if( $item_type === 'action' ) {
424 + // Get the action tags
425 + $tags = automatorwp_get_action_tags( (object) $object );
426 +
427 + if( ! empty( $tags ) && isset( $tags[$id] ) ) {
428 + $tags_html = automatorwp_get_tags_selector_group_html( $id, $tags[$id] );
429 + }
430 + }
431 +
432 + $response = array(
433 + 'edit_html' => automatorwp_parse_automation_item_edit_label( (object) $object, $item_type ),
434 + 'tags_html' => $tags_html
435 + );
436 +
437 + // Special condition for filters
438 + if( $object->type === 'filter' ) {
439 +
440 + ob_start();
441 + automatorwp_automation_item_edit_html( $object, $item_type, $automation );
442 + $edit_html = ob_get_clean();
443 +
444 + $response['item_html'] = $edit_html;
445 + }
446 +
447 + wp_send_json_success( $response );
448 +
449 +}
450 +add_action( 'wp_ajax_automatorwp_update_item_option', 'automatorwp_ajax_update_item_option' );
451 +
452 +/**
453 + * Run automation through ajax
454 + *
455 + * @since 2.2.2
456 + */
457 +function automatorwp_ajax_run_automation() {
458 +
459 + // Security check, forces to die if not security passed
460 + check_ajax_referer( 'automatorwp_admin', 'nonce' );
461 +
462 + // Permissions check
463 + if( ! current_user_can( automatorwp_get_manager_capability() ) ) {
464 + wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'automatorwp' ) );
465 + }
466 +
467 + // Sanitize parameters
468 + $automation_id = absint( $_POST['automation_id'] );
469 +
470 + $automation = automatorwp_get_automation_object( $automation_id );
471 +
472 + // Bail if automation not found
473 + if( ! $automation ) {
474 + wp_send_json_error( sprintf( __( 'Automation with ID %d not found.', 'automatorwp' ), $automation_id ) );
475 + }
476 +
477 + /**
478 + * Hook when running automation through ajax
479 + *
480 + * @since 2.2.2
481 + *
482 + * @param stdClass $automation The automation object
483 + */
484 + do_action( 'automatorwp_ajax_run_automation', $automation );
485 +
486 + // Run the automation
487 + $result = automatorwp_run_automation( $automation_id );
488 +
489 + if( $result ) {
490 + wp_send_json_success( automatorwp_get_automation_run_details( $automation ) );
491 + } else {
492 + wp_send_json_error( array(
493 + 'message' => automatorwp_get_run_automation_error()
494 + ) );
495 + }
496 +
497 +
498 +}
499 +add_action( 'wp_ajax_automatorwp_run_automation', 'automatorwp_ajax_run_automation' );
500 +
501 +/**
502 + * Cancel automation run through ajax
503 + *
504 + * @since 2.2.2
505 + */
506 +function automatorwp_ajax_cancel_automation_run() {
507 +
508 + // Security check, forces to die if not security passed
509 + check_ajax_referer( 'automatorwp_admin', 'nonce' );
510 +
511 + // Permissions check
512 + if( ! current_user_can( automatorwp_get_manager_capability() ) ) {
513 + wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'automatorwp' ) );
514 + }
515 +
516 + // Sanitize parameters
517 + $automation_id = absint( $_POST['automation_id'] );
518 +
519 + $automation = automatorwp_get_automation_object( $automation_id );
520 +
521 + // Bail if automation not found
522 + if( ! $automation ) {
523 + wp_send_json_error( sprintf( __( 'Automation with ID %d not found.', 'automatorwp' ), $automation_id ) );
524 + }
525 +
526 + // Cancel the automation run
527 + $result = automatorwp_cancel_automation_run( $automation_id );
528 +
529 + if( $result ) {
530 + wp_send_json_success();
531 + } else {
532 + wp_send_json_error( array(
533 + 'message' => automatorwp_get_run_automation_error()
534 + ) );
535 + }
536 +
537 +}
538 +add_action( 'wp_ajax_automatorwp_cancel_automation_run', 'automatorwp_ajax_cancel_automation_run' );
539 +
540 +/**
541 + * AJAX Helper for selecting posts
542 + *
543 + * @since 1.0.0
544 + */
545 +function automatorwp_ajax_get_posts() {
546 + // Security check, forces to die if not security passed
547 + check_ajax_referer( 'automatorwp_admin', 'nonce' );
548 +
549 + // Permissions check
550 + if( ! current_user_can( automatorwp_get_manager_capability() ) ) {
551 + wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'automatorwp' ) );
552 + }
553 +
554 + global $wpdb;
555 +
556 + // Pull back the search string
557 + $search = isset( $_REQUEST['q'] ) ? $wpdb->esc_like( $_REQUEST['q'] ) : '';
558 +
559 + // Setup where conditions (initialized with 1=1)
560 + $where = '1=1';
561 +
562 + // Post type conditional
563 + $post_type = ( isset( $_REQUEST['post_type'] ) && ! empty( $_REQUEST['post_type'] ) ? $_REQUEST['post_type'] : array( 'post', 'page' ) );
564 +
565 + // Add support to the post_type_cb parameter (used on post selector fields)
566 + if( isset( $_REQUEST['post_type_cb'] ) && ! empty( $_REQUEST['post_type_cb'] ) ) {
567 +
568 + $post_type_cb = sanitize_text_field( $_REQUEST['post_type_cb'] );
569 +
570 + if( is_callable( $post_type_cb ) ) {
571 + $post_type = call_user_func( $post_type_cb );
572 + }
573 +
574 + }
575 +
576 + $post_type_any = false;
577 +
578 + if ( is_array( $post_type ) ) {
579 +
580 + // Support for any post type
581 + if( ! in_array( 'any', $post_type ) ) {
582 +
583 + // Sanitize all post types given
584 + foreach( $post_type as $i => $value ) {
585 + $post_type[$i] = sanitize_text_field( $value );
586 + }
587 +
588 + $where .= sprintf( ' AND p.post_type IN(\'%s\')', implode( "','", $post_type ) );
589 +
590 + } else {
591 + $post_type_any = true;
592 + }
593 +
594 + } else {
595 +
596 + // Support for any post type
597 + if( $post_type !== 'any' ) {
598 +
599 + // Sanitize the post type
600 + $post_type = sanitize_text_field( $post_type );
601 +
602 + $where .= sprintf( ' AND p.post_type = \'%s\'', $post_type );
603 + } else {
604 + $post_type_any = true;
605 + }
606 + }
607 +
608 + // Exclude some undesired post types if showing all posts types
609 + if( $post_type_any ) {
610 + $post_types_excluded = array(
611 + 'revision',
612 + 'nav_menu_item',
613 + 'custom_css',
614 + 'customize_changeset',
615 + 'user_request',
616 + 'oembed_cache',
617 + 'wp_block',
618 + 'wp_template',
619 + );
620 +
621 + $where .= sprintf( ' AND p.post_type NOT IN(\'%s\')', implode( "','", $post_types_excluded ) );
622 + }
623 +
624 + // Post title conditional
625 + $where .= " AND p.post_title LIKE %s";
626 +
627 + // Post status conditional
628 + $where .= " AND p.post_status NOT IN ( 'pending', 'draft' )";
629 +
630 + // Check for trigger type extra conditionals
631 + if( isset( $_REQUEST['trigger_type'] ) ) {
632 +
633 + $query_args = array();
634 + $trigger_type = sanitize_text_field( $_REQUEST['trigger_type'] );
635 +
636 + /**
637 + * Specific activity triggers query args (used on requirements UI and on ajax get posts)
638 + * Note: Use $_REQUEST for all given parameters
639 + *
640 + * @since 1.0.0
641 + *
642 + * @param array|string $query_args
643 + * @param string $trigger_type
644 + *
645 + * @return array|string
646 + */
647 + $query_args = apply_filters( 'automatorwp_specific_trigger_type_query_args', $query_args, $trigger_type );
648 +
649 + if( ! empty( $query_args ) ) {
650 +
651 + if( is_array( $query_args ) ) {
652 + // If is an array of conditionals, then build the new conditionals
653 + foreach( $query_args as $field => $value ) {
654 + $where .= " AND p.{$field} = '$value'";
655 + }
656 + } else {
657 + // Leave an extra space if query args doesn't have one
658 + $where .= ' ' . $query_args;
659 + }
660 +
661 + }
662 +
663 + }
664 +
665 + /**
666 + * Ajax posts query args (used on almost every post selector)
667 + * Note: Use $_REQUEST for all given parameters
668 + *
669 + * @since 1.0.0
670 + *
671 + * @param string $query_args
672 + *
673 + * @return array|string
674 + */
675 + $extra_query_args = apply_filters( 'automatorwp_ajax_get_posts_query_args', '' );
676 +
677 + // Check for extra conditionals
678 + if( ! empty( $extra_query_args ) ) {
679 +
680 + if( is_array( $extra_query_args ) ) {
681 + // If is an array of conditionals, then build the new conditionals
682 + foreach( $extra_query_args as $field => $value ) {
683 + $where .= " AND p.{$field} = '$value'";
684 + }
685 + } else {
686 + // Leave an extra space if extra query args doesn't have one
687 + $where .= ' ' . $extra_query_args;
688 + }
689 +
690 + }
691 +
692 + // Setup from (from is filtered to allow joins)
693 + $from = "{$wpdb->posts} AS p";
694 +
695 + /**
696 + * Ajax posts from (used on almost every post selector)
697 + * Note: Use $_REQUEST for all given parameters
698 + *
699 + * @since 1.0.0
700 + *
701 + * @param string $from By default '{$wpdb->posts} AS p'
702 + *
703 + * @return string
704 + */
705 + $from = apply_filters( 'automatorwp_ajax_get_posts_from', $from );
706 +
707 + /**
708 + * Ajax posts where (used on almost every post selector)
709 + * Note: Use $_REQUEST for all given parameters
710 + *
711 + * @since 1.0.0
712 + *
713 + * @param string $where Contains all wheres
714 + *
715 + * @return string
716 + */
717 + $where = apply_filters( 'automatorwp_ajax_get_posts_where', $where );
718 +
719 + // Setup order by
720 + $order_by = "p.post_type ASC, p.menu_order DESC";
721 +
722 + /**
723 + * Ajax posts order by (used on almost every post selector)
724 + * Note: Use $_REQUEST for all given parameters
725 + *
726 + * @since 1.0.0
727 + *
728 + * @param string $order_by By default 'p.post_type ASC, p.menu_order DESC'
729 + *
730 + * @return string
731 + */
732 + $order_by = apply_filters( 'automatorwp_ajax_get_posts_order_by', $order_by );
733 +
734 + // Pagination args
735 + $page = isset( $_REQUEST['page'] ) ? absint( $_REQUEST['page'] ) : 1;
736 + $limit = 20;
737 + $offset = $limit * ( $page - 1 );
738 +
739 + // On this query, keep $wpdb->posts to get current site posts
740 + $results = $wpdb->get_results( $wpdb->prepare(
741 + "SELECT p.ID, p.post_title, p.post_type
742 + FROM {$from}
743 + WHERE {$where}
744 + ORDER BY {$order_by}
745 + LIMIT {$offset}, {$limit}",
746 + "%%{$search}%%"
747 + ) );
748 +
749 + $count = absint( $wpdb->get_var( $wpdb->prepare(
750 + "SELECT COUNT(*) FROM {$from} WHERE {$where}",
751 + "%%{$search}%%"
752 + ) ) );
753 +
754 + /**
755 + * Ajax posts results (used on almost every post selector)
756 + * Note: Use $_REQUEST for all given parameters
757 + *
758 + * @since 1.0.0
759 + *
760 + * @param array $results
761 + *
762 + * @return array
763 + */
764 + $results = apply_filters( 'automatorwp_ajax_get_posts_results', $results );
765 +
766 + $response = array(
767 + 'results' => $results,
768 + 'more_results' => $count > $limit && $count > $offset,
769 + );
770 +
771 + // Return our results
772 + wp_send_json_success( $response );
773 +
774 +}
775 +add_action( 'wp_ajax_automatorwp_get_posts', 'automatorwp_ajax_get_posts' );
776 +
777 +/**
778 + * Parse the posts results to prepend custom options
779 + *
780 + * @since 1.0.0
781 + *
782 + * @param array $results
783 + *
784 + * @return array
785 + */
786 +function automatorwp_ajax_parse_posts_results( $results ) {
787 + return automatorwp_ajax_parse_extra_options( $results, 'ID', 'post_title' );
788 +}
789 +add_filter( 'automatorwp_ajax_get_posts_results', 'automatorwp_ajax_parse_posts_results' );
790 +
791 +/**
792 + * AJAX Helper for selecting terms
793 + *
794 + * @since 1.0.0
795 + */
796 +function automatorwp_ajax_get_terms() {
797 + // Security check, forces to die if not security passed
798 + check_ajax_referer( 'automatorwp_admin', 'nonce' );
799 +
800 + // Permissions check
801 + if( ! current_user_can( automatorwp_get_manager_capability() ) ) {
802 + wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'automatorwp' ) );
803 + }
804 +
805 + // Pull back the search string
806 + $search = isset( $_REQUEST['q'] ) ? sanitize_text_field( $_REQUEST['q'] ) : '';
807 +
808 + // Taxonomy conditional
809 + $taxonomy = ( isset( $_REQUEST['taxonomy'] ) && ! empty( $_REQUEST['taxonomy'] ) ? sanitize_text_field( $_REQUEST['taxonomy'] ) : 'category' );
810 +
811 + // Pagination args
812 + $page = isset( $_REQUEST['page'] ) ? absint( $_REQUEST['page'] ) : 1;
813 + $limit = 20;
814 + $offset = $limit * ( $page - 1 );
815 +
816 + $term_query = new WP_Term_Query( array(
817 + 'search' => $search,
818 + 'taxonomy' => $taxonomy,
819 + 'hide_empty' => false,
820 + 'number' => $limit,
821 + 'offset' => $offset,
822 + ) );
823 +
824 + $results = $term_query->get_terms();
825 +
826 + $count_term_query = new WP_Term_Query( array(
827 + 'fields' => 'count',
828 + 'taxonomy' => $taxonomy,
829 + 'hide_empty' => false,
830 + ) );
831 +
832 + $count = $count_term_query->get_terms();
833 +
834 + /**
835 + * Ajax posts results (used on almost every post selector)
836 + * Note: Use $_REQUEST for all given parameters
837 + *
838 + * @since 1.0.0
839 + *
840 + * @param array $results
841 + *
842 + * @return array
843 + */
844 + $results = apply_filters( 'automatorwp_ajax_get_terms_results', $results );
845 +
846 + $response = array(
847 + 'results' => $results,
848 + 'more_results' => $count > $limit && $count > $offset,
849 + );
850 +
851 + // Return our results
852 + wp_send_json_success( $response );
853 +
854 +}
855 +add_action( 'wp_ajax_automatorwp_get_terms', 'automatorwp_ajax_get_terms' );
856 +
857 +/**
858 + * Parse the terms results to prepend custom options
859 + *
860 + * @since 1.0.0
861 + *
862 + * @param array $results
863 + *
864 + * @return array
865 + */
866 +function automatorwp_ajax_parse_terms_results( $results ) {
867 + return automatorwp_ajax_parse_extra_options( $results, 'term_id', 'name' );
868 +}
869 +add_filter( 'automatorwp_ajax_get_terms_results', 'automatorwp_ajax_parse_terms_results' );
870 +
871 +/**
872 + * AJAX Helper for selecting users
873 + *
874 + * @since 1.0.0
875 + */
876 +function automatorwp_ajax_get_users() {
877 + // Security check, forces to die if not security passed
878 + check_ajax_referer( 'automatorwp_admin', 'nonce' );
879 +
880 + // Permissions check
881 + if( ! current_user_can( automatorwp_get_manager_capability() ) ) {
882 + wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'automatorwp' ) );
883 + }
884 +
885 + // If no word query sent, initialize it
886 + if ( ! isset( $_REQUEST['q'] ) ) {
887 + $_REQUEST['q'] = '';
888 + }
889 +
890 + global $wpdb;
891 +
892 + // Pull back the search string
893 + $search = esc_sql( $wpdb->esc_like( $_REQUEST['q'] ) );
894 + $where = '';
895 +
896 + if ( ! empty( $search ) ) {
897 + $where = " WHERE user_login LIKE '%{$search}%'";
898 + $where .= " OR user_email LIKE '%{$search}%'";
899 + $where .= " OR display_name LIKE '%{$search}%'";
900 + }
901 +
902 + // Pagination args
903 + $page = isset( $_REQUEST['page'] ) ? absint( $_REQUEST['page'] ) : 1;
904 + $limit = 20;
905 + $offset = $limit * ( $page - 1 );
906 +
907 + // Fetch our results (store as associative array)
908 + $results = $wpdb->get_results(
909 + "SELECT ID, user_login, user_email, display_name
910 + FROM {$wpdb->users}
911 + {$where}
912 + LIMIT {$offset}, {$limit}",
913 + 'ARRAY_A'
914 + );
915 +
916 + $count = $wpdb->get_var(
917 + "SELECT COUNT(*)
918 + FROM {$wpdb->users}
919 + {$where}"
920 + );
921 +
922 + $response = array(
923 + 'results' => $results,
924 + 'more_results' => absint( $count ) > $offset,
925 + );
926 +
927 + // Return our results
928 + wp_send_json_success( $response );
929 +}
930 +add_action( 'wp_ajax_automatorwp_get_users', 'automatorwp_ajax_get_users' );
931 +
932 +/**
933 + * AJAX Helper for selecting objects
934 + *
935 + * @since 1.0.0
936 + */
937 +function automatorwp_ajax_get_objects() {
938 + // Security check, forces to die if not security passed
939 + check_ajax_referer( 'automatorwp_admin', 'nonce' );
940 +
941 + // Permissions check
942 + if( ! current_user_can( automatorwp_get_manager_capability() ) ) {
943 + wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'automatorwp' ) );
944 + }
945 +
946 + global $ct_registered_tables;
947 +
948 + // Pull back the search string
949 + $search = isset( $_REQUEST['q'] ) ? sanitize_text_field( $_REQUEST['q'] ) : '';
950 +
951 + // Table conditional
952 + $table = ( isset( $_REQUEST['table'] ) ? sanitize_text_field( $_REQUEST['table'] ) : '' );
953 +
954 + if( ! isset( $ct_registered_tables[$table] ) ) {
955 + wp_send_json_error( __( 'Table not found.', 'automatorwp' ) );
956 + }
957 +
958 + $ct_table = ct_setup_table( $table );
959 +
960 + // Pagination args
961 + $page = isset( $_REQUEST['page'] ) ? absint( $_REQUEST['page'] ) : 1;
962 + $limit = 20;
963 + $offset = $limit * ( $page - 1 );
964 +
965 + $ct_query_args = array(
966 + 's' => $search,
967 + 'items_per_page' => $limit,
968 + 'page' => $page,
969 + );
970 +
971 + /**
972 + * Ajax objects query parameters (used on almost every object selector)
973 + * Note: Use $_REQUEST for all given parameters
974 + *
975 + * @since 1.0.0
976 + *
977 + * @param array $ct_query_args
978 + * @param CT_Table $ct_table
979 + *
980 + * @return array
981 + */
982 + $ct_query_args = apply_filters( 'automatorwp_ajax_get_objects_query_args', $ct_query_args, $ct_table );
983 +
984 + $ct_query = new CT_Query( $ct_query_args );
985 +
986 + $results = $ct_query->get_results();
987 + $count = $ct_query->found_results;
988 +
989 + /**
990 + * Ajax objects results (used on almost every object selector)
991 + * Note: Use $_REQUEST for all given parameters
992 + *
993 + * @since 1.0.0
994 + *
995 + * @param array $results
996 + * @param CT_Table $ct_table
997 + *
998 + * @return array Should return elements with an array of array( 'id' => 1, 'text' => '' )
999 + */
1000 + $results = apply_filters( 'automatorwp_ajax_get_objects_results', $results, $ct_table );
1001 +
1002 + ct_reset_setup_table();
1003 +
1004 + $response = array(
1005 + 'results' => $results,
1006 + 'more_results' => $count > $limit && $count > $offset,
1007 + );
1008 +
1009 + // Return our results
1010 + wp_send_json_success( $response );
1011 +
1012 +}
1013 +add_action( 'wp_ajax_automatorwp_get_objects', 'automatorwp_ajax_get_objects' );
1014 +
1015 +/**
1016 + * Parse automations objects results
1017 + *
1018 + * @since 1.0.0
1019 + *
1020 + * @param array $results
1021 + * @param CT_Table $ct_table
1022 + *
1023 + * @return array
1024 + */
1025 +function automatorwp_ajax_get_automations_results( $results, $ct_table ) {
1026 +
1027 + if( $ct_table->name !== 'automatorwp_automations' ) {
1028 + return $results;
1029 + }
1030 +
1031 + $new_results = array();
1032 +
1033 + foreach( $results as $object ) {
1034 +
1035 + $title = ( ! empty( $object->title ) ? $object->title : __( '(No title)', 'automatorwp' ) );
1036 +
1037 + $new_results[] = array(
1038 + 'id' => $object->id,
1039 + 'text' => $title,
1040 + );
1041 + }
1042 +
1043 + return $new_results;
1044 +}
1045 +add_filter( 'automatorwp_ajax_get_objects_results', 'automatorwp_ajax_get_automations_results', 10, 2 );
1046 +
1047 +/**
1048 + * Parse the objects results to prepend custom options
1049 + *
1050 + * @since 1.0.0
1051 + *
1052 + * @param array $results
1053 + *
1054 + * @return array
1055 + */
1056 +function automatorwp_ajax_parse_objects_results( $results ) {
1057 + return automatorwp_ajax_parse_extra_options( $results );
1058 +}
1059 +add_filter( 'automatorwp_ajax_get_objects_results', 'automatorwp_ajax_parse_objects_results', 11 );
1060 +
1061 +/**
1062 + * Helper function to prepend the option none to the ajax results
1063 + *
1064 + * @since 1.0.0
1065 + *
1066 + * @deprecated use automatorwp_ajax_parse_extra_options() instead
1067 + * Note: Keep for backward compatibility
1068 + *
1069 + * @param array $results
1070 + *
1071 + * @return array
1072 + */
1073 +function automatorwp_ajax_get_ajax_results_option_none( $results ) {
1074 + return automatorwp_ajax_parse_extra_options( $results );
1075 +}
1076 +
1077 +/**
1078 + * Helper function to prepend extra options to the ajax results
1079 + *
1080 + * @since 1.0.0
1081 + *
1082 + * @param array $results
1083 + * @param string $id_key
1084 + * @param string $text_key
1085 + *
1086 + * @return array
1087 + */
1088 +function automatorwp_ajax_parse_extra_options( $results, $id_key = 'id', $text_key = 'text' ) {
1089 +
1090 + global $wpdb;
1091 +
1092 + // Pull back the search string
1093 + $search = isset( $_REQUEST['q'] ) ? $wpdb->esc_like( $_REQUEST['q'] ) : '';
1094 + $page = isset( $_REQUEST['page'] ) ? absint( $_REQUEST['page'] ) : 1;
1095 +
1096 + // Option none
1097 + $option_none = isset( $_REQUEST['option_none'] ) ? absint( $_REQUEST['option_none'] ) : 0;
1098 + $option_none_value = isset( $_REQUEST['option_none_value'] ) ? sanitize_text_field( $_REQUEST['option_none_value'] ) : '';
1099 + $option_none_label = isset( $_REQUEST['option_none_label'] ) ? sanitize_text_field( $_REQUEST['option_none_label'] ) : '';
1100 +
1101 + if( $option_none && ! empty( $option_none_value ) && ! empty( $option_none_label ) ) {
1102 +
1103 + if( ( $page === 1 && empty( $search ) ) // Prepend option none if is first page
1104 + || ( strpos( $option_none_label , $search ) ) // Prepend if search matches option none label
1105 + ) {
1106 + array_unshift( $results, array( $id_key => $option_none_value, $text_key => $option_none_label ) );
1107 + }
1108 +
1109 + }
1110 +
1111 + // Option custom
1112 + $option_custom = isset( $_REQUEST['option_custom'] ) ? absint( $_REQUEST['option_custom'] ) : 0;
1113 + $option_custom_value = isset( $_REQUEST['option_custom_value'] ) ? sanitize_text_field( $_REQUEST['option_custom_value'] ) : '';
1114 + $option_custom_label = isset( $_REQUEST['option_custom_label'] ) ? sanitize_text_field( $_REQUEST['option_custom_label'] ) : '';
1115 +
1116 + if( $option_custom && ! empty( $option_custom_value ) && ! empty( $option_custom_label ) ) {
1117 +
1118 + if( ( $page === 1 && empty( $search ) ) // Prepend option custom if is first page
1119 + || ( strpos( $option_custom_label , $search ) ) // Prepend if search matches option custom label
1120 + ) {
1121 + array_unshift( $results, array( $id_key => $option_custom_value, $text_key => $option_custom_label ) );
1122 + }
1123 +
1124 + }
1125 +
1126 + return $results;
1127 +
1128 +}