PluginProbe
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI / 5.8.6
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI v5.8.6
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
automatorwp / includes / ajax-functions.php

ajax-functions.php in AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI 5.8.6, at includes/ajax-functions.php

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