PluginProbe
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI / 5.8.5
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI v5.8.5
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 / events.php

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

2,083 lines 68.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Events
4 *
5 * @package AutomatorWP\Events
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 * Handles an event trigger
14 *
15 * @since 1.0.0
16 *
17 * @param array $event Event information
18 *
19 * @return array|false An array of triggered triggers or false if event is not correctly triggered
20 */
21 function automatorwp_trigger_event( $event ) {
22
23 global $automatorwp_completed_triggers, $automatorwp_event;
24
25 $automatorwp_event = false;
26
27 // Check the event received
28 if( ! automatorwp_is_event_correct( $event ) ) {
29 return false;
30 }
31
32 $automatorwp_event = $event;
33
34 // Initialize completed triggers count
35 if( ! is_array( $automatorwp_completed_triggers ) ) {
36 $automatorwp_completed_triggers = array();
37 }
38
39 // Get triggered triggers
40 $triggers = automatorwp_get_event_triggered_triggers( $event['trigger'] );
41
42 foreach( $triggers as $trigger ) {
43
44 if( automatorwp_maybe_completed_trigger( $trigger, $event ) ) {
45 $automatorwp_completed_triggers[] = $trigger;
46 }
47
48 }
49
50 return ( count( $automatorwp_completed_triggers ) ? $automatorwp_completed_triggers : false );
51
52 }
53
54 /**
55 * Checks if event contains the required attributes (by default, user_id and trigger)
56 *
57 * @since 1.0.0
58 *
59 * @param array $event Event information
60 *
61 * @return bool
62 */
63 function automatorwp_is_event_correct( $event = array() ) {
64
65 // Check trigger
66 if( ! isset( $event['trigger'] ) ) {
67 return false;
68 }
69
70 if( ! isset( AutomatorWP()->triggers[$event['trigger']] ) ) {
71 return false;
72 }
73
74 $trigger = AutomatorWP()->triggers[$event['trigger']];
75
76 // Check the user ID if trigger is not anonymous
77 if( ! $trigger['anonymous'] ) {
78
79 // Check user
80 if( ! isset( $event['user_id'] ) ) {
81 return false;
82 }
83
84 $event['user_id'] = absint( $event['user_id'] );
85
86 if( $event['user_id'] === 0 ) {
87 return false;
88 }
89
90 }
91
92 /**
93 * Filter to add custom checks to event checking
94 *
95 * @since 1.0.0
96 *
97 * @param bool $is_correct If event is correct or not
98 * @param array $event Event information
99 *
100 * @return bool
101 */
102 return apply_filters( 'automatorwp_is_event_correct', true, $event );
103
104 }
105
106 /**
107 * Get triggers by type commonly triggered by automatorwp_trigger_event() function
108 *
109 * @since 1.0.0
110 *
111 * @param string $trigger_type The trigger type triggered in event
112 *
113 * @return array
114 */
115 function automatorwp_get_event_triggered_triggers( $trigger_type ) {
116
117 ct_setup_table( 'automatorwp_triggers' );
118
119 $ct_query = new CT_Query( array(
120 'type' => $trigger_type,
121 'orderby' => 'position',
122 'order' => 'ASC',
123 'items_per_page' => -1,
124 ) );
125
126 $triggers = $ct_query->get_results();
127
128 ct_reset_setup_table();
129
130 if( is_array( $triggers ) ) {
131 return $triggers;
132 } else {
133 return array();
134 }
135
136 }
137
138 /**
139 * Check if trigger can be marked as completed
140 *
141 * @since 1.0.0
142 *
143 * @param stdClass $trigger The trigger object
144 * @param array $event Event information
145 *
146 * @return bool
147 */
148 function automatorwp_maybe_completed_trigger( $trigger, $event = array() ) {
149
150 // Check if trigger is correct
151 if( ! is_object( $trigger ) ) {
152 return false;
153 }
154
155 // Check if automation is correct
156 $automation = automatorwp_get_trigger_automation( $trigger->id );
157
158 if( ! is_object( $automation ) ) {
159 return false;
160 }
161
162 // Check if automation is expired to deactivate it
163 if( automatorwp_is_automation_expired( $automation ) ) {
164 automatorwp_deactivate_automation( $automation->id );
165
166 // The automation has expired so bail here
167 return false;
168 }
169
170 $trigger_args = automatorwp_get_trigger( $trigger->type );
171
172 if( $automation->type === 'anonymous' ) {
173 // Anonymous automation
174
175 // Bail if user trigger is used on an anonymous automation
176 if( ! $trigger_args['anonymous'] ) {
177 return false;
178 }
179
180 return automatorwp_maybe_anonymous_completed_trigger( $trigger, $event );
181
182 } else {
183 // User automation
184
185 // Bail if anonymous trigger is used on a user automation
186 if( $trigger_args['anonymous'] ) {
187 return false;
188 }
189
190 // Args has been checked on automatorwp_is_event_correct() function
191 $user_id = $event['user_id'];
192
193 return automatorwp_maybe_user_completed_trigger( $trigger, $user_id, $event );
194
195 }
196
197 }
198
199 // -------------------------------------------
200 // Guest event
201 // -------------------------------------------
202
203 /**
204 * Check if anonymous has completed a trigger
205 *
206 * @since 1.3.0
207 *
208 * @param stdClass $trigger The trigger object
209 * @param array $event Event information
210 *
211 * @return bool
212 */
213 function automatorwp_maybe_anonymous_completed_trigger( $trigger, $event = array() ) {
214
215 // Check if trigger is correct
216 if( ! is_object( $trigger ) ) {
217 return false;
218 }
219
220 // Check if automation is correct
221 $automation = automatorwp_get_trigger_automation( $trigger->id );
222
223 if( ! is_object( $automation ) ) {
224 return false;
225 }
226
227 // Get the trigger stored options
228 $trigger_options = automatorwp_get_trigger_stored_options( $trigger->id );
229
230 foreach( $trigger_options as $option => $value ) {
231 // Replace all tags by their replacements
232 $trigger_options[$option] = automatorwp_parse_automation_tags( $automation->id, 0, $value );
233 }
234
235 // Check if anonymous has access to the trigger
236 if( ! automatorwp_anonymous_has_access_to_trigger( $trigger, $event, $trigger_options, $automation ) ) {
237 return false;
238 }
239
240 // Check if anonymous deserves the trigger
241 if( ! automatorwp_anonymous_deserves_trigger( $trigger, $event, $trigger_options, $automation ) ) {
242 return false;
243 }
244
245 // Mark trigger as completed
246 $trigger_completed = automatorwp_anonymous_completed_trigger( $trigger, $event, $trigger_options, $automation );
247
248 if( ! $trigger_completed ) {
249 return false;
250 }
251
252 $user_id = automatorwp_get_anonymous_automation_user_id( $automation, $event );
253
254 // Bail if user can't be created
255 if( ! $user_id ) {
256 return false;
257 }
258
259 // Update anonymous log user ID
260 automatorwp_update_anonymous_completed_trigger_log_user_id( $user_id );
261
262 automatorwp_maybe_user_completed_automation( $automation, $user_id, $event );
263
264 return true;
265
266 }
267
268 /**
269 * Check if anonymous has access to trigger
270 *
271 * @since 1.3.0
272 *
273 * @param stdClass $trigger The trigger object
274 * @param array $event Event information
275 * @param array $trigger_options The trigger's stored options
276 * @param stdClass $automation The trigger's automation object
277 *
278 * @return bool True if anonymous has access, false otherwise
279 */
280 function automatorwp_anonymous_has_access_to_trigger( $trigger = null, $event = array(), $trigger_options = array(), $automation = null ) {
281
282 // Check if trigger is correct
283 if( ! is_object( $trigger ) ) {
284 return false;
285 }
286
287 // Check if automation is correct
288 if( $automation === null ) {
289 $automation = automatorwp_get_trigger_automation( $trigger->id );
290
291 if( ! is_object( $automation ) ) {
292 return false;
293 }
294 }
295
296 $has_access = true;
297
298 // Bail if automation is not active
299 if( $automation->status !== 'active' ) {
300 $has_access = false;
301 }
302
303 // Bail if is a future automation
304 if( $has_access && automatorwp_is_automation_scheduled( $automation ) ) {
305 $has_access = false;
306 }
307
308 // Bail if expired automation
309 if( $has_access && automatorwp_is_automation_expired( $automation ) ) {
310 $has_access = false;
311 }
312
313 // Check if exceeded automation completion times
314 $times = absint( $automation->times );
315
316 if( $has_access && $times > 0 ) {
317 $completion_times = automatorwp_get_object_completion_times( $automation->id, 'automation' );
318
319 if( $completion_times >= $times ) {
320 $has_access = false;
321 }
322 }
323
324 /**
325 * Filter to override the has access check.
326 * This filter is to check the automation configuration.
327 * Triggers should use the 'automatorwp_anonymous_deserves_trigger' filter instead.
328 *
329 * @since 1.3.0
330 *
331 * @param bool $has_access True if anonymous has access, false otherwise
332 * @param stdClass $trigger The trigger object
333 * @param array $event Event information
334 * @param array $trigger_options The trigger's stored options
335 * @param stdClass $automation The trigger's automation object
336 *
337 * @return bool True if anonymous has access, false otherwise
338 */
339 return apply_filters( 'automatorwp_anonymous_has_access_to_trigger', $has_access, $trigger, $event, $trigger_options, $automation );
340
341 }
342
343 /**
344 * Check if anonymous deserves trigger
345 *
346 * @since 1.3.0
347 *
348 * @param stdClass $trigger The trigger object
349 * @param array $event Event information
350 * @param array $trigger_options The trigger's stored options
351 * @param stdClass $automation The trigger's automation object
352 *
353 * @return bool True if anonymous deserves trigger, false otherwise
354 */
355 function automatorwp_anonymous_deserves_trigger( $trigger = null, $event = array(), $trigger_options = array(), $automation = null ) {
356
357 // Check if trigger is correct
358 if( ! is_object( $trigger ) ) {
359 return false;
360 }
361
362 // Check if automation is correct
363 if( $automation === null ) {
364 $automation = automatorwp_get_trigger_automation( $trigger->id );
365
366 if( ! is_object( $automation ) ) {
367 return false;
368 }
369 }
370
371 $deserves_trigger = true;
372
373 /**
374 * Filter to override the anonymous deserves trigger check.
375 * This filter is to check the trigger configuration.
376 * Triggers should use this filter.
377 *
378 * @since 1.3.0
379 *
380 * @param bool $deserves_trigger True if anonymous deserves trigger, false otherwise
381 * @param stdClass $trigger The trigger object
382 * @param array $event Event information
383 * @param array $trigger_options The trigger's stored options
384 * @param stdClass $automation The trigger's automation object
385 *
386 * @return bool True if anonymous deserves trigger, false otherwise
387 * @return bool True if anonymous deserves trigger, false otherwise
388 */
389 return apply_filters( 'automatorwp_anonymous_deserves_trigger', $deserves_trigger, $trigger, $event, $trigger_options, $automation );
390
391 }
392
393 /**
394 * Registers the trigger completion
395 *
396 * @since 1.3.0
397 *
398 * @param stdClass $trigger The trigger object
399 * @param array $event Event information
400 * @param array $trigger_options The trigger's stored options
401 * @param stdClass $automation The trigger's automation object
402 *
403 * @return bool
404 */
405 function automatorwp_anonymous_completed_trigger( $trigger = null, $event = array(), $trigger_options = array(), $automation = null ) {
406
407 global $automatorwp_last_anonymous_trigger_log_id;
408
409 // Initialize last anonymous trigger log ID
410 $automatorwp_last_anonymous_trigger_log_id = 0;
411
412 // Check if trigger is correct
413 if( ! is_object( $trigger ) ) {
414 return false;
415 }
416
417 // Check if automation is correct
418 if( $automation === null ) {
419 $automation = automatorwp_get_trigger_automation( $trigger->id );
420
421 if( ! is_object( $automation ) ) {
422 return false;
423 }
424 }
425
426 // Get the trigger completion times
427 $log_meta = array(
428 'times' => 1
429 );
430
431 if( isset( $event['comment_id'] ) ) {
432 $log_meta['comment_id'] = $event['comment_id'];
433 }
434
435 /**
436 * Filter to add custom log meta to meet that user has completed this trigger
437 *
438 * @since 1.3.0
439 *
440 * @param array $log_meta Log meta data
441 * @param stdClass $trigger The trigger object
442 * @param array $event Event information
443 * @param array $trigger_options The trigger's stored options
444 * @param stdClass $automation The trigger's automation object
445 *
446 * @return array
447 */
448 $log_meta = apply_filters( 'automatorwp_anonymous_completed_trigger_log_meta', $log_meta, $trigger, $event, $trigger_options, $automation );
449
450 /**
451 * Backward compatibility filter!
452 *
453 * Filter to add custom log meta to meet that user has completed this trigger
454 *
455 * @since 1.0.0
456 *
457 * @param array $log_meta Log meta data
458 * @param stdClass $trigger The trigger object
459 * @param int $user_id The user ID (here will be 0, since user hasn't been created yet)
460 * @param array $event Event information
461 * @param array $trigger_options The trigger's stored options
462 * @param stdClass $automation The trigger's automation object
463 *
464 * @return array
465 */
466 $log_meta = apply_filters( 'automatorwp_user_completed_trigger_log_meta', $log_meta, $trigger, 0, $event, $trigger_options, $automation );
467
468 // Insert a new log entry to register the trigger completion
469 $automatorwp_last_anonymous_trigger_log_id = automatorwp_insert_log( array(
470 'title' => automatorwp_parse_automation_item_log_label( $trigger, 'trigger', 'view' ),
471 'type' => 'trigger',
472 'object_id' => $trigger->id,
473 'user_id' => 0,
474 'post_id' => ( isset( $event['post_id'] ) ? $event['post_id'] : 0 ),
475 'date' => automatorwp_get_event_log_date(),
476 ), $log_meta );
477
478 if( is_wp_error( $automatorwp_last_anonymous_trigger_log_id ) ) {
479 $automatorwp_last_anonymous_trigger_log_id = 0;
480 }
481
482 /**
483 * Available action to hook on a trigger completion
484 *
485 * @since 1.3.0
486 *
487 * @param stdClass $trigger The trigger object
488 * @param array $event Event information
489 * @param array $trigger_options The trigger's stored options
490 * @param stdClass $automation The trigger's automation object
491 */
492 do_action( 'automatorwp_anonymous_completed_trigger', $trigger, $event, $trigger_options, $automation );
493
494 return true;
495
496 }
497
498 /**
499 * Get the anonymous automation user ID
500 *
501 * @since 1.3.0
502 *
503 * @param stdClass $automation The automation object
504 * @param array $event Event information
505 *
506 * @return int|false The user ID, false otherwise
507 */
508 function automatorwp_get_anonymous_automation_user_id( $automation = null, $event = array() ) {
509
510 if( ! is_object( $automation ) ) {
511 return false;
512 }
513
514 $actions = automatorwp_get_automation_actions( $automation->id );
515
516 // Check if isset the first action
517 if( ! isset( $actions[0] ) ) {
518 return false;
519 }
520
521 // Check if anonymous user action exists
522 if( isset( $actions[0] ) && $actions[0]->type !== 'automatorwp_anonymous_user' ) {
523 return false;
524 }
525
526 $action = $actions[0];
527
528 // Get all action options to parse all replacements
529 $action_options = automatorwp_get_action_stored_options( $action->id );
530
531 foreach( $action_options as $option => $value ) {
532 // Replace all tags by their replacements
533 $action_options[$option] = automatorwp_parse_automation_tags( $automation->id, 0, $value );
534 }
535
536 // Execute the anonymous user action to decide the user to assign the logs
537 $user_id = false;
538
539 /**
540 * Filter to decide to which user ID will be assigned to the automation
541 *
542 * @since 1.0.0
543 *
544 * @param int $user_id The user ID
545 * @param stdClass $action The action object
546 * @param array $action_options The action's stored options (with tags already passed)
547 * @param stdClass $automation The action's automation object
548 *
549 * @return int|false The user ID, false otherwise
550 */
551 return apply_filters( 'automatorwp_get_anonymous_automation_user_id', $user_id, $action, $action_options, $automation );
552
553 }
554
555 /**
556 * Update the trigger log user ID for anonymous events
557 *
558 * @since 1.3.0
559 *
560 * @param int $user_id The user ID
561 */
562 function automatorwp_update_anonymous_completed_trigger_log_user_id( $user_id ) {
563
564 global $automatorwp_last_anonymous_trigger_log_id;
565
566 // Bail if not ID found
567 if( absint( $automatorwp_last_anonymous_trigger_log_id ) === 0 ) {
568 return;
569 }
570
571 ct_setup_table( 'automatorwp_logs' );
572
573 // Update the log user ID
574 ct_update_object( array(
575 'id' => $automatorwp_last_anonymous_trigger_log_id,
576 'user_id' => $user_id,
577 ) );
578
579 ct_reset_setup_table();
580
581 }
582
583 // -------------------------------------------
584 // User event
585 // -------------------------------------------
586
587 /**
588 * Check if user has completed a trigger
589 *
590 * @since 1.0.0
591 *
592 * @param stdClass $trigger The trigger object
593 * @param int $user_id The user ID
594 * @param array $event Event information
595 *
596 * @return bool
597 */
598 function automatorwp_maybe_user_completed_trigger( $trigger, $user_id = 0, $event = array() ) {
599
600 // Check if trigger is correct
601 if( ! is_object( $trigger ) ) {
602 return false;
603 }
604
605 // Check the user ID
606 if( $user_id === 0 ) {
607 return false;
608 }
609
610 // Check if automation is correct
611 $automation = automatorwp_get_trigger_automation( $trigger->id );
612
613 if( ! is_object( $automation ) ) {
614 return false;
615 }
616
617 // Get the trigger stored options
618 $trigger_options = automatorwp_get_trigger_stored_options( $trigger->id );
619
620 foreach( $trigger_options as $option => $value ) {
621 // Replace all tags by their replacements
622 $trigger_options[$option] = automatorwp_parse_automation_tags( $automation->id, $user_id, $value );
623 }
624
625 // Check if user has access to the trigger
626 if( ! automatorwp_user_has_access_to_trigger( $trigger, $user_id, $event, $trigger_options, $automation ) ) {
627 return false;
628 }
629
630 // Check if user deserves the trigger
631 if( ! automatorwp_user_deserves_trigger( $trigger, $user_id, $event, $trigger_options, $automation ) ) {
632 return false;
633 }
634
635 // Check if user deserves the trigger filters
636 if( ! automatorwp_user_deserves_trigger_filters( $trigger, $user_id, $event, $trigger_options, $automation ) ) {
637 return false;
638 }
639
640 // Mark trigger as completed
641 return automatorwp_user_completed_trigger( $trigger, $user_id, $event, $trigger_options, $automation );
642
643 }
644
645 /**
646 * Check if user has access to trigger
647 *
648 * @since 1.0.0
649 *
650 * @param stdClass $trigger The trigger object
651 * @param int $user_id The user ID
652 * @param array $event Event information
653 * @param array $trigger_options The trigger's stored options
654 * @param stdClass $automation The trigger's automation object
655 *
656 * @return bool True if user has access, false otherwise
657 */
658 function automatorwp_user_has_access_to_trigger( $trigger = null, $user_id = 0, $event = array(), $trigger_options = array(), $automation = null ) {
659
660 // Check if trigger is correct
661 if( ! is_object( $trigger ) ) {
662 return false;
663 }
664
665 // Check the user ID
666 if( $user_id === 0 ) {
667 return false;
668 }
669
670 // Check if automation is correct
671 if( $automation === null ) {
672 $automation = automatorwp_get_trigger_automation( $trigger->id );
673
674 if( ! is_object( $automation ) ) {
675 return false;
676 }
677 }
678
679 $has_access = true;
680
681 // Bail if automation is not active
682 if( $automation->status !== 'active' ) {
683 $has_access = false;
684 }
685
686 // Bail if is a future automation
687 if( $has_access && automatorwp_is_automation_scheduled( $automation ) ) {
688 $has_access = false;
689 }
690
691 // Bail if expired automation
692 if( $has_access && automatorwp_is_automation_expired( $automation ) ) {
693 $has_access = false;
694 }
695
696 // Check if user exceeded completion times
697 $times_per_user = absint( $automation->times_per_user );
698
699 if( $has_access && $times_per_user > 0 ) {
700 $user_completion_times = automatorwp_get_user_completion_times( $automation->id, $user_id, 'automation' );
701
702 if( $user_completion_times >= $times_per_user ) {
703 $has_access = false;
704 }
705 }
706
707 // Check if exceeded automation completion times
708 $times = absint( $automation->times );
709
710 if( $has_access && $times > 0 ) {
711 $completion_times = automatorwp_get_object_completion_times( $automation->id, 'automation' );
712
713 if( $completion_times >= $times ) {
714 $has_access = false;
715 }
716 }
717
718 // Check if automation is sequential
719 if( $has_access && $automation->sequential ) {
720
721 $automation_triggers = automatorwp_get_automation_triggers( $automation->id );
722
723 // Loop all automation triggers to check if all previous triggers has been completed
724 foreach( $automation_triggers as $automation_trigger ) {
725
726 // If both triggers has the same position, then we have reached our current trigger
727 if( $automation_trigger->position === $trigger->position ) {
728 break;
729 }
730
731 // If user has not completed a previous trigger, set access to false
732 if( ! automatorwp_has_user_completed_trigger( $automation_trigger->id, $user_id ) ) {
733 $has_access = false;
734 break;
735 }
736
737 }
738
739 }
740
741 /**
742 * Filter to override the has access check.
743 * This filter is to check the automation configuration.
744 * Triggers should use the 'automatorwp_user_deserves_trigger' filter instead.
745 *
746 * @since 1.0.0
747 *
748 * @param bool $has_access True if user has access, false otherwise
749 * @param stdClass $trigger The trigger object
750 * @param int $user_id The user ID
751 * @param array $event Event information
752 * @param array $trigger_options The trigger's stored options
753 * @param stdClass $automation The trigger's automation object
754 *
755 * @return bool True if user has access, false otherwise
756 */
757 return apply_filters( 'automatorwp_user_has_access_to_trigger', $has_access, $trigger, $user_id, $event, $trigger_options, $automation );
758
759 }
760
761 /**
762 * Check if user deserves trigger
763 *
764 * @since 1.0.0
765 *
766 * @param stdClass $trigger The trigger object
767 * @param int $user_id The user ID
768 * @param array $event Event information
769 * @param array $trigger_options The trigger's stored options
770 * @param stdClass $automation The trigger's automation object
771 *
772 * @return bool True if user deserves trigger, false otherwise
773 */
774 function automatorwp_user_deserves_trigger( $trigger = null, $user_id = 0, $event = array(), $trigger_options = array(), $automation = null ) {
775
776 // Check if trigger is correct
777 if( ! is_object( $trigger ) ) {
778 return false;
779 }
780
781 // Check the user ID
782 if( $user_id === 0 ) {
783 return false;
784 }
785
786 // Check if automation is correct
787 if( $automation === null ) {
788 $automation = automatorwp_get_trigger_automation( $trigger->id );
789
790 if( ! is_object( $automation ) ) {
791 return false;
792 }
793 }
794
795 if( automatorwp_has_user_completed_trigger( $trigger->id, $user_id ) ) {
796
797 $automation_triggers = automatorwp_get_automation_triggers( $automation->id );
798
799 // Only pass this check if automation has more than 1 trigger
800 if( count( $automation_triggers ) > 1 ) {
801 return false;
802 }
803 }
804
805 $deserves_trigger = true;
806
807 /**
808 * Filter to override the user deserves trigger check.
809 * This filter is to check the trigger configuration.
810 * Triggers should use this filter.
811 *
812 * @since 1.0.0
813 *
814 * @param bool $deserves_trigger True if user deserves trigger, false otherwise
815 * @param stdClass $trigger The trigger object
816 * @param int $user_id The user ID
817 * @param array $event Event information
818 * @param array $trigger_options The trigger's stored options
819 * @param stdClass $automation The trigger's automation object
820 *
821 * @return bool True if user deserves trigger, false otherwise
822 */
823 return apply_filters( 'automatorwp_user_deserves_trigger', $deserves_trigger, $trigger, $user_id, $event, $trigger_options, $automation );
824
825 }
826
827 /**
828 * Check if user deserves trigger filters
829 *
830 * @since 1.0.0
831 *
832 * @param stdClass $trigger The trigger object
833 * @param int $user_id The user ID
834 * @param array $event Event information
835 * @param array $trigger_options The trigger's stored options
836 * @param stdClass $automation The trigger's automation object
837 *
838 * @return bool True if user deserves trigger, false otherwise
839 */
840 function automatorwp_user_deserves_trigger_filters( $trigger = null, $user_id = 0, $event = array(), $trigger_options = array(), $automation = null ) {
841
842 global $automatorwp_completed_trigger_filters;
843
844 // Check if trigger is correct
845 if( ! is_object( $trigger ) ) {
846 return false;
847 }
848
849 // Check the user ID
850 if( $user_id === 0 ) {
851 return false;
852 }
853
854 // Check if automation is correct
855 if( $automation === null ) {
856 $automation = automatorwp_get_trigger_automation( $trigger->id );
857
858 if( ! is_object( $automation ) ) {
859 return false;
860 }
861 }
862
863 if( automatorwp_has_user_completed_trigger( $trigger->id, $user_id ) ) {
864 $automation_triggers = automatorwp_get_automation_triggers( $automation->id );
865
866 // Only pass this check if automation has more than 1 trigger
867 if( count( $automation_triggers ) > 1 ) {
868 return false;
869 }
870 }
871
872 $deserves_trigger_filters = true;
873
874 // Bail if is a filter
875 if( $trigger->type === 'filter' ) {
876 return $deserves_trigger_filters;
877 }
878
879 // Initialize completed filters
880 $automatorwp_completed_trigger_filters = array();
881
882 $filters = automatorwp_get_trigger_filters( $trigger );
883
884 foreach( $filters as $i => $filter ) {
885
886 $deserves_filter = true;
887
888 // Get the trigger stored options
889 $filter_options = automatorwp_get_filter_stored_options( $filter->id, 'trigger' );
890
891 foreach( $filter_options as $option => $value ) {
892 // Replace all tags by their replacements
893 $filter_options[$option] = automatorwp_parse_automation_tags( $automation->id, $user_id, $value );
894 }
895
896 /**
897 * Filter to override the user deserves filter check.
898 * This filter is to check the filter configuration.
899 * Filters should use this filter.
900 *
901 * @since 1.0.0
902 *
903 * @param bool $deserves_filter True if user deserves filter, false otherwise
904 * @param stdClass $filter The filter object
905 * @param int $user_id The user ID
906 * @param array $event Event information
907 * @param array $filter_options The filter's stored options
908 * @param stdClass $automation The filter's automation object
909 *
910 * @return bool True if user deserves filter, false otherwise
911 */
912 $deserves_filter = apply_filters( 'automatorwp_user_deserves_trigger_filter', $deserves_filter, $filter, $user_id, $event, $filter_options, $automation );
913
914 if( $i === 0 ) {
915 // On first filter there is no need to apply the operator
916 $deserves_trigger_filters = $deserves_filter;
917 } else {
918 // Apply the operator
919 if( $filter_options['operator'] === 'and' ) {
920 $deserves_trigger_filters = $deserves_trigger_filters && $deserves_filter;
921 } else {
922 $deserves_trigger_filters = $deserves_trigger_filters || $deserves_filter;
923 }
924 }
925
926 // Store completed filters
927 if( $deserves_filter ) {
928 $automatorwp_completed_trigger_filters[] = $filter;
929 }
930
931 // Break this loop if the trigger filters are not passed
932 if( ! $deserves_trigger_filters ) {
933
934 // For OR operators, prevent to bail until check all of them
935 if( $i < count( $filters ) && $filter_options['operator'] === 'or' ) {
936 continue;
937 }
938
939 // Register why user has not completed this filter
940 $log_meta = array(
941 'item_type' => 'trigger'
942 );
943
944 /**
945 * Filter to add custom log meta to meet that user has completed this trigger
946 *
947 * @since 1.0.0
948 *
949 * @param array $log_meta Log meta data
950 * @param stdClass $filter The filter object
951 * @param int $user_id The user ID
952 * @param array $event Event information
953 * @param array $filter_options The filter's stored options
954 * @param stdClass $automation The filter's automation object
955 *
956 * @return array
957 */
958 $log_meta = apply_filters( 'automatorwp_user_not_passed_filter_log_meta', $log_meta, $filter, $user_id, $event, $filter_options, $automation );
959
960 // Insert a new log entry to register why user not passed the trigger filter
961 automatorwp_insert_log( array(
962 'title' => automatorwp_parse_automation_item_log_label( $filter, 'trigger', 'view' ),
963 'type' => 'filter',
964 'object_id' => $filter->id,
965 'user_id' => $user_id,
966 'post_id' => ( isset( $event['post_id'] ) ? $event['post_id'] : 0 ),
967 'date' => automatorwp_get_event_log_date(),
968 ), $log_meta );
969
970 // Force to clear the cache for this filter
971 automatorwp_clear_user_last_completion_cache( $filter, $user_id, 'filter' );
972
973 break;
974 }
975
976 }
977
978 /**
979 * Filter to override the user deserves trigger filters check.
980 *
981 * @since 1.0.0
982 *
983 * @param bool $deserves_trigger_filters True if user deserves the trigger filters, false otherwise
984 * @param stdClass $trigger The trigger object
985 * @param int $user_id The user ID
986 * @param array $event Event information
987 * @param array $trigger_options The trigger's stored options
988 * @param stdClass $automation The trigger's automation object
989 *
990 * @return bool True if user deserves trigger, false otherwise
991 */
992 return apply_filters( 'automatorwp_user_deserves_trigger_filters', $deserves_trigger_filters, $trigger, $user_id, $event, $trigger_options, $automation );
993
994 }
995
996 /**
997 * Registers the trigger completion
998 *
999 * @since 1.0.0
1000 *
1001 * @param stdClass $trigger The trigger object
1002 * @param int $user_id The user ID
1003 * @param array $event Event information
1004 * @param array $trigger_options The trigger's stored options
1005 * @param stdClass $automation The trigger's automation object
1006 *
1007 * @return bool
1008 */
1009 function automatorwp_user_completed_trigger( $trigger = null, $user_id = 0, $event = array(), $trigger_options = array(), $automation = null ) {
1010
1011 global $automatorwp_completed_trigger_filters;
1012
1013 if( ! is_array( $automatorwp_completed_trigger_filters ) ) {
1014 $automatorwp_completed_trigger_filters = array();
1015 }
1016
1017 // Check if trigger is correct
1018 if( ! is_object( $trigger ) ) {
1019 return false;
1020 }
1021
1022 // Check the user ID
1023 if( $user_id === 0 ) {
1024 return false;
1025 }
1026
1027 // Check if automation is correct
1028 if( $automation === null ) {
1029 $automation = automatorwp_get_trigger_automation( $trigger->id );
1030
1031 if( ! is_object( $automation ) ) {
1032 return false;
1033 }
1034 }
1035
1036 // Get the trigger completion times
1037 $completion_times = automatorwp_get_user_trigger_completion_times( $trigger->id, $user_id );
1038
1039 $log_meta = array(
1040 'times' => ( $completion_times + 1 )
1041 );
1042
1043 if( isset( $event['comment_id'] ) ) {
1044 $log_meta['comment_id'] = $event['comment_id'];
1045 }
1046
1047 /**
1048 * Filter to add custom log meta to meet that user has completed this trigger
1049 *
1050 * @since 1.0.0
1051 *
1052 * @param array $log_meta Log meta data
1053 * @param stdClass $trigger The trigger object
1054 * @param int $user_id The user ID
1055 * @param array $event Event information
1056 * @param array $trigger_options The trigger's stored options
1057 * @param stdClass $automation The trigger's automation object
1058 *
1059 * @return array
1060 */
1061 $log_meta = apply_filters( 'automatorwp_user_completed_trigger_log_meta', $log_meta, $trigger, $user_id, $event, $trigger_options, $automation );
1062
1063 // Insert a new log entry to register the trigger completion
1064 automatorwp_insert_log( array(
1065 'title' => automatorwp_parse_automation_item_log_label( $trigger, 'trigger', 'view' ),
1066 'type' => 'trigger',
1067 'object_id' => $trigger->id,
1068 'user_id' => $user_id,
1069 'post_id' => ( isset( $event['post_id'] ) ? $event['post_id'] : 0 ),
1070 'date' => automatorwp_get_event_log_date(),
1071 ), $log_meta );
1072
1073 /**
1074 * Available action to hook on a trigger completion
1075 *
1076 * @since 1.0.0
1077 *
1078 * @param stdClass $trigger The trigger object
1079 * @param int $user_id The user ID
1080 * @param array $event Event information
1081 * @param array $trigger_options The trigger's stored options
1082 * @param stdClass $automation The trigger's automation object
1083 */
1084 do_action( 'automatorwp_user_completed_trigger', $trigger, $user_id, $event, $trigger_options, $automation );
1085
1086 if( $trigger->type !== 'filter' ) {
1087
1088 // Mark all completed filters
1089 foreach( $automatorwp_completed_trigger_filters as $filter ) {
1090
1091 // Get the trigger stored options
1092 $filter_options = automatorwp_get_filter_stored_options( $filter->id, 'trigger' );
1093
1094 // Registers the passed filter (as a trigger entry)
1095 automatorwp_user_completed_trigger( $filter, $user_id, $event, $filter_options, $automation );
1096
1097 }
1098
1099 // Check if user has completed the automation
1100 automatorwp_maybe_user_completed_automation( $automation, $user_id, $event );
1101
1102 }
1103
1104 return true;
1105
1106 }
1107
1108 /**
1109 * Registers the automation completion
1110 *
1111 * @since 1.0.0
1112 *
1113 * @param stdClass $automation The automation object
1114 * @param int $user_id The user ID
1115 * @param array $event Event information
1116 *
1117 * @return bool
1118 */
1119 function automatorwp_maybe_user_completed_automation( $automation = null, $user_id = 0, $event = array() ) {
1120
1121 // Check if automation is correct
1122 if( ! is_object( $automation ) ) {
1123 return false;
1124 }
1125
1126 // Check the user ID
1127 if( $user_id === 0 ) {
1128 return false;
1129 }
1130
1131 $triggers = automatorwp_get_automation_triggers( $automation->id );
1132
1133 $all_completed = true;
1134
1135 // Check if user has completed all automation trigger
1136 foreach( $triggers as $trigger ) {
1137
1138 if( $trigger->type === 'filter' ) {
1139 continue;
1140 }
1141
1142 // If user has not completed this trigger the number of times required then break to finish this function
1143 if( ! automatorwp_has_user_completed_trigger( $trigger->id, $user_id ) ) {
1144 $all_completed = false;
1145 break;
1146 }
1147
1148 }
1149
1150 // Bail if user has not completed all automation triggers
1151 if( ! $all_completed ) {
1152 return false;
1153 }
1154
1155 // Mark trigger as completed
1156 return automatorwp_user_completed_automation( $automation, $user_id, $event );
1157
1158 }
1159
1160 /**
1161 * Registers the automation completion
1162 *
1163 * @since 1.0.0
1164 *
1165 * @param stdClass $automation The automation object
1166 * @param int $user_id The user ID
1167 * @param array $event Event information
1168 *
1169 * @return bool
1170 */
1171 function automatorwp_user_completed_automation( $automation = null, $user_id = 0, $event = array() ) {
1172
1173 // Check if automation is correct
1174 if( ! is_object( $automation ) ) {
1175 return false;
1176 }
1177
1178 // Check the user ID
1179 if( $user_id === 0 ) {
1180 return false;
1181 }
1182
1183 // Execute all automation actions
1184 automatorwp_execute_all_automation_actions( $automation, $user_id, $event );
1185
1186 /**
1187 * Available filter to determine if user has completed an automation
1188 *
1189 * @since 1.2.4
1190 *
1191 * @param bool $complete Determines if the automation should be marked as completed, by default true
1192 * @param stdClass $automation The automation object
1193 * @param int $user_id The user ID
1194 * @param array $event Event information
1195 *
1196 * @return bool
1197 */
1198 $complete = apply_filters( 'automatorwp_can_user_complete_automation', true, $automation, $user_id, $event );
1199
1200 if( ! $complete ) {
1201 return false;
1202 }
1203
1204 // Insert a new log entry to register the automation completion
1205 automatorwp_insert_log( array(
1206 'title' => $automation->title,
1207 'type' => 'automation',
1208 'object_id' => $automation->id,
1209 'user_id' => $user_id,
1210 'post_id' => ( isset( $event['post_id'] ) ? $event['post_id'] : 0 ),
1211 'date' => automatorwp_get_event_log_date(),
1212 ) );
1213
1214 // Increment the completions
1215 $completions = absint( automatorwp_get_automation_meta( $automation->id, 'completions', true ) );
1216 automatorwp_update_automation_meta( $automation->id, 'completions', $completions + 1 );
1217
1218 /**
1219 * Available action to hook on an automation completion
1220 *
1221 * @since 1.0.0
1222 *
1223 * @param stdClass $automation The automation object
1224 * @param int $user_id The user ID
1225 * @param array $event Event information
1226 */
1227 do_action( 'automatorwp_user_completed_automation', $automation, $user_id, $event );
1228
1229 return true;
1230
1231 }
1232
1233 /**
1234 * Execute all automation actions
1235 *
1236 * @since 1.0.0
1237 *
1238 * @param stdClass $automation The automation object
1239 * @param int $user_id The user ID
1240 * @param array $event Event information
1241 *
1242 * @return bool
1243 */
1244 function automatorwp_execute_all_automation_actions( $automation = null, $user_id = 0, $event = array() ) {
1245
1246 // Check if automation is correct
1247 if( ! is_object( $automation ) ) {
1248 return false;
1249 }
1250
1251 // Check the user ID
1252 if( $user_id === 0 ) {
1253 return false;
1254 }
1255
1256 // Get all automation action to execute them
1257 $actions = automatorwp_get_automation_actions( $automation->id );
1258
1259 foreach( $actions as $action ) {
1260 automatorwp_execute_action( $action, $user_id, $event );
1261 }
1262
1263 return true;
1264
1265 }
1266
1267 /**
1268 * Execute an action
1269 *
1270 * @since 1.0.0
1271 *
1272 * @param stdClass $action The action object
1273 * @param int $user_id The user ID
1274 * @param array $event Event information
1275 *
1276 * @return bool
1277 */
1278 function automatorwp_execute_action( $action = null, $user_id = 0, $event = array() ) {
1279
1280 // Check if action is correct
1281 if( ! is_object( $action ) ) {
1282 return false;
1283 }
1284
1285 // Check the user ID
1286 if( $user_id === 0 ) {
1287 return false;
1288 }
1289
1290 // Setup the automation assigned to this action
1291 $automation = automatorwp_get_automation_object( $action->automation_id );
1292
1293 // Check if automation is correct
1294 if( ! is_object( $automation ) ) {
1295 return false;
1296 }
1297
1298 // Get all action options to parse all replacements
1299 $action_options = automatorwp_get_action_stored_options( $action->id );
1300
1301 foreach( $action_options as $option => $value ) {
1302 // Replace all tags by their replacements
1303 $action_options[$option] = automatorwp_parse_automation_tags( $automation->id, $user_id, $value );
1304 }
1305
1306 // Bail if action can not be executed
1307 if( ! automatorwp_can_execute_action( $action, $user_id, $event, $action_options, $automation ) ) {
1308 return false;
1309 }
1310
1311 // Check if user deserves the action filters
1312 if( ! automatorwp_user_deserves_action_filters( $action, $user_id, $event, $action_options, $automation ) ) {
1313 return false;
1314 }
1315
1316 /**
1317 * Available action to hook for execute an action function
1318 *
1319 * @since 1.0.0
1320 *
1321 * @param stdClass $action The action object
1322 * @param int $user_id The user ID
1323 * @param array $event Event information
1324 * @param array $action_options The action's stored options (with tags already passed)
1325 * @param stdClass $automation The action's automation object
1326 */
1327 do_action( 'automatorwp_execute_action', $action, $user_id, $event, $action_options, $automation );
1328
1329 $log_meta = array();
1330
1331 /**
1332 * Filter to add custom log meta to meet that and action has been executed to a specific user
1333 *
1334 * @since 1.0.0
1335 *
1336 * @param array $log_meta Log meta data
1337 * @param stdClass $action The action object
1338 * @param int $user_id The user ID
1339 * @param array $action_options The action's stored options (with tags already passed)
1340 * @param stdClass $automation The action's automation object
1341 *
1342 * @return array
1343 */
1344 $log_meta = apply_filters( 'automatorwp_user_completed_action_log_meta', $log_meta, $action, $user_id, $action_options, $automation );
1345
1346 /**
1347 * Filter to assign a custom post ID to this action
1348 *
1349 * @since 1.0.0
1350 *
1351 * @param int $post_id The post ID, by default 0
1352 * @param stdClass $action The action object
1353 * @param int $user_id The user ID
1354 * @param array $event Event information
1355 * @param array $action_options The action's stored options (with tags already passed)
1356 * @param stdClass $automation The action's automation object
1357 *
1358 * @return int
1359 */
1360 $post_id = apply_filters( 'automatorwp_user_completed_action_post_id', 0, $action, $user_id, $event, $action_options, $automation );
1361
1362 // Parse the log label (including the automation tags)
1363 $log_title = automatorwp_parse_automation_item_log_label( $action, 'action', 'view' );
1364 $log_title = automatorwp_parse_automation_tags( $automation->id, $user_id, $log_title );
1365
1366 // Insert a new log entry to register the trigger completion
1367 automatorwp_insert_log( array(
1368 'title' => $log_title,
1369 'type' => 'action',
1370 'object_id' => $action->id,
1371 'user_id' => $user_id,
1372 'post_id' => $post_id,
1373 'date' => automatorwp_get_event_log_date(),
1374 ), $log_meta );
1375
1376 /**
1377 * Available action to hook on an action completion
1378 *
1379 * @since 1.0.0
1380 *
1381 * @param stdClass $action The action object
1382 * @param int $user_id The user ID
1383 * @param array $event Event information
1384 * @param array $action_options The action's stored options (with tags already passed)
1385 * @param stdClass $automation The action's automation object
1386 */
1387 do_action( 'automatorwp_user_completed_action', $action, $user_id, $event, $action_options, $automation );
1388
1389 return true;
1390
1391 }
1392
1393 /**
1394 * Checks if an action should be executed or not
1395 *
1396 * @since 1.2.4
1397 *
1398 * @param stdClass $action The action object
1399 * @param int $user_id The user ID
1400 * @param array $event Event information
1401 * @param array $action_options The action's stored options (with tags already passed)
1402 * @param stdClass $automation The action's automation object
1403 *
1404 * @return bool
1405 */
1406 function automatorwp_can_execute_action( $action = null, $user_id = 0, $event = array(), $action_options = array(), $automation = null ) {
1407
1408 // Check if action is correct
1409 if( ! is_object( $action ) ) {
1410 return false;
1411 }
1412
1413 // Check the user ID
1414 if( $user_id === 0 ) {
1415 return false;
1416 }
1417
1418 // Check if automation is correct
1419 if( $automation === null ) {
1420 $automation = automatorwp_get_action_automation( $action->id );
1421
1422 if( ! is_object( $automation ) ) {
1423 return false;
1424 }
1425 }
1426
1427 $execute = true;
1428
1429 /**
1430 * Available filter to determine if an action should be executed or not
1431 *
1432 * @since 1.2.4
1433 *
1434 * @param bool $execute Determines if the action should be executed, by default true
1435 * @param stdClass $action The action object
1436 * @param int $user_id The user ID
1437 * @param array $event Event information
1438 * @param array $action_options The action's stored options (with tags already passed)
1439 * @param stdClass $automation The action's automation object
1440 *
1441 * @return bool
1442 */
1443 return apply_filters( 'automatorwp_can_execute_action', $execute, $action, $user_id, $event, $action_options, $automation );
1444
1445 }
1446
1447 /**
1448 * Check if user deserves action filters
1449 *
1450 * @since 1.0.0
1451 *
1452 * @param stdClass $action The action object
1453 * @param int $user_id The user ID
1454 * @param array $event Event information
1455 * @param array $action_options The action's stored options
1456 * @param stdClass $automation The action's automation object
1457 *
1458 * @return bool True if user deserves action, false otherwise
1459 */
1460 function automatorwp_user_deserves_action_filters( $action = null, $user_id = 0, $event = array(), $action_options = array(), $automation = null ) {
1461
1462 global $automatorwp_completed_action_filters, $automatorwp_last_action_passed_all_filters;
1463
1464 // Check if action is correct
1465 if( ! is_object( $action ) ) {
1466 return false;
1467 }
1468
1469 // Check the user ID
1470 if( $user_id === 0 ) {
1471 return false;
1472 }
1473
1474 // Check if automation is correct
1475 if( $automation === null ) {
1476 $automation = automatorwp_get_action_automation( $action->id );
1477
1478 if( ! is_object( $automation ) ) {
1479 return false;
1480 }
1481 }
1482
1483 $deserves_action_filters = true;
1484
1485 // Bail if is a filter
1486 if( $action->type === 'filter' ) {
1487
1488 if( ! is_array( $automatorwp_completed_action_filters ) ) {
1489 return false;
1490 }
1491
1492 if( ! $automatorwp_last_action_passed_all_filters ) {
1493 return false;
1494 }
1495
1496 $found = false;
1497
1498 foreach ( $automatorwp_completed_action_filters as $filter ) {
1499 if( absint( $filter->id ) === absint( $action->id ) ) {
1500 $found = true;
1501 }
1502 }
1503
1504 // If filter has not been passed, prevent its execution
1505 if( ! $found ) {
1506 return false;
1507 }
1508
1509 return $deserves_action_filters;
1510 }
1511
1512 // Initialize completed actions
1513 $automatorwp_completed_action_filters = array();
1514 $automatorwp_last_action_passed_all_filters = false;
1515
1516 $filters = automatorwp_get_action_filters( $action );
1517
1518 foreach( $filters as $i => $filter ) {
1519
1520 $deserves_filter = true;
1521
1522 // Get the action stored options
1523 $filter_options = automatorwp_get_filter_stored_options( $filter->id, 'action' );
1524
1525 foreach( $filter_options as $option => $value ) {
1526 // Replace all tags by their replacements
1527 $filter_options[$option] = automatorwp_parse_automation_tags( $automation->id, $user_id, $value );
1528 }
1529
1530 /**
1531 * Filter to override the user deserves filter check.
1532 * This filter is to check the filter configuration.
1533 * Filters should use this filter.
1534 *
1535 * @since 1.0.0
1536 *
1537 * @param bool $deserves_filter True if user deserves filter, false otherwise
1538 * @param stdClass $filter The filter object
1539 * @param int $user_id The user ID
1540 * @param array $event Event information
1541 * @param array $filter_options The filter's stored options
1542 * @param stdClass $automation The filter's automation object
1543 *
1544 * @return bool True if user deserves filter, false otherwise
1545 */
1546 $deserves_filter = apply_filters( 'automatorwp_user_deserves_action_filter', $deserves_filter, $filter, $user_id, $event, $filter_options, $automation );
1547
1548 if( $i === 0 ) {
1549 // On first filter there is no need to apply the operator
1550 $deserves_action_filters = $deserves_filter;
1551 } else {
1552 // Apply the operator
1553 if( $filter_options['operator'] === 'and' ) {
1554 $deserves_action_filters = $deserves_action_filters && $deserves_filter;
1555 } else {
1556 $deserves_action_filters = $deserves_action_filters || $deserves_filter;
1557 }
1558 }
1559
1560 // Store completed filters
1561 if( $deserves_filter ) {
1562 $automatorwp_completed_action_filters[] = $filter;
1563 }
1564
1565 // Break this loop if the action filters are not passed
1566 if( ! $deserves_action_filters ) {
1567
1568 // For OR operators, prevent to bail until check all of them
1569 if( $i < count( $filters ) && $filter_options['operator'] === 'or' ) {
1570 continue;
1571 }
1572
1573 // Register why user has not completed this filter
1574 $log_meta = array(
1575 'item_type' => 'action'
1576 );
1577
1578 /**
1579 * Filter to add custom log meta to meet that user has completed this action
1580 *
1581 * @since 1.0.0
1582 *
1583 * @param array $log_meta Log meta data
1584 * @param stdClass $filter The filter object
1585 * @param int $user_id The user ID
1586 * @param array $event Event information
1587 * @param array $filter_options The filter's stored options
1588 * @param stdClass $automation The filter's automation object
1589 *
1590 * @return array
1591 */
1592 $log_meta = apply_filters( 'automatorwp_user_not_passed_filter_log_meta', $log_meta, $filter, $user_id, $event, $filter_options, $automation );
1593
1594 // Parse the log label (including the automation tags)
1595 $log_title = automatorwp_parse_automation_item_log_label( $filter, 'action', 'view' );
1596 $log_title = automatorwp_parse_automation_tags( $automation->id, $user_id, $log_title );
1597
1598 // Insert a new log entry to register why user not passed the action filter
1599 automatorwp_insert_log( array(
1600 'title' => $log_title,
1601 'type' => 'filter',
1602 'object_id' => $filter->id,
1603 'user_id' => $user_id,
1604 'post_id' => ( isset( $event['post_id'] ) ? $event['post_id'] : 0 ),
1605 'date' => automatorwp_get_event_log_date(),
1606 ), $log_meta );
1607
1608 // Force to clear the cache for this filter
1609 automatorwp_clear_user_last_completion_cache( $filter, $user_id, 'filter' );
1610
1611 break;
1612 }
1613
1614 }
1615
1616 /**
1617 * Filter to override the user deserves action filters check.
1618 *
1619 * @since 1.0.0
1620 *
1621 * @param bool $deserves_action_filters True if user deserves the action filters, false otherwise
1622 * @param stdClass $action The action object
1623 * @param int $user_id The user ID
1624 * @param array $event Event information
1625 * @param array $action_options The action's stored options
1626 * @param stdClass $automation The action's automation object
1627 *
1628 * @return bool True if user deserves action, false otherwise
1629 */
1630 $deserves_action_filters = apply_filters( 'automatorwp_user_deserves_action_filters', $deserves_action_filters, $action, $user_id, $event, $action_options, $automation );
1631
1632 // Used to meet if should register the rest of filter actions
1633 $automatorwp_last_action_passed_all_filters = $deserves_action_filters;
1634
1635 return $deserves_action_filters;
1636 }
1637
1638 // -------------------------------------------
1639 // Automation execution
1640 // -------------------------------------------
1641
1642 /**
1643 * Run an automation
1644 *
1645 * @since 2.2.2
1646 *
1647 * @param int $automation_id The automation ID
1648 *
1649 * @return bool
1650 */
1651 function automatorwp_run_automation( $automation_id ) {
1652
1653 global $automatorwp_run_automation_error;
1654
1655 // Initialize error
1656 $automatorwp_run_automation_error = '';
1657
1658 // Sanitization
1659 $automation_id = absint( $automation_id );
1660
1661 // Bail if automation id not provided
1662 if( $automation_id === 0 ) {
1663 $automatorwp_run_automation_error = __( 'Invalid automation ID.', 'automatorwp' );
1664 return false;
1665 }
1666
1667 // Get the automation
1668 $automation = automatorwp_get_automation_object( $automation_id );
1669
1670 // Bail if automation not found
1671 if( ! $automation ) {
1672 $automatorwp_run_automation_error = sprintf( __( 'Automation with ID %d not found.', 'automatorwp' ), $automation_id );
1673 return false;
1674 }
1675
1676 // Only loop automations can be run here
1677 if( ! in_array( $automation->type, automatorwp_get_automation_loop_types() ) ) {
1678 $automatorwp_run_automation_error = __( 'Invalid automation type.', 'automatorwp' );
1679 return false;
1680 }
1681
1682 // Check if exceeded automation completion times
1683 $times = absint( $automation->times );
1684
1685 if( $times > 0 ) {
1686 $completion_times = automatorwp_get_object_completion_times( $automation->id, 'automation' );
1687
1688 if( $completion_times >= $times ) {
1689 $automatorwp_run_automation_error = __( 'Automation has been run the number of times allowed. Change the "Total times" setting for this automation to allow run it again.', 'automatorwp' );
1690 return false;
1691 }
1692 }
1693
1694 $result = apply_filters( 'automatorwp_run_automation_result', false, $automation );
1695
1696 // Bail if automation has not run correctly
1697 if( ! $result ) {
1698 return false;
1699 }
1700
1701 // Check if run finished
1702 if( automatorwp_maybe_run_automation_finished( $automation ) ) {
1703 // Call the automation run finished function
1704 automatorwp_run_automation_finished( $automation );
1705 } else {
1706 // Increase loop
1707 $loop = absint( automatorwp_get_automation_meta( $automation->id, 'current_loop', true ) );
1708 automatorwp_update_automation_meta( $automation->id, 'current_loop', $loop + 1 );
1709
1710 // Check if is a manual run
1711 $manual_run = (bool) automatorwp_get_automation_meta( $automation->id, 'manual_run', true );
1712
1713 if( ! $manual_run ) {
1714
1715 // Get the delay amount and seconds from the automation
1716 $delay_amount = absint( automatorwp_get_automation_meta( $automation->id, 'delay_amount', true ) );
1717 $delay_seconds = absint( automatorwp_get_automation_meta( $automation->id, 'delay_seconds', true ) );
1718
1719 $delay = $delay_amount * $delay_seconds;
1720
1721 if( $delay <= 0 ) {
1722 $delay = 60;
1723 }
1724
1725 /**
1726 * Available filter to override the delay between runs
1727 *
1728 * @since 1.0.0
1729 *
1730 * @param int $delay By default, 60 (1 minute)
1731 * @param stdClass $automation The automation object
1732 *
1733 * @return int
1734 */
1735 $delay = apply_filters( 'automatorwp_run_automation_delay_between_runs', $delay, $automation );
1736
1737 // if not is a manual run, schedule this function after a delay
1738 if( function_exists( 'as_schedule_single_action' ) ) {
1739 as_schedule_single_action( current_time( 'timestamp' ) + $delay, 'automatorwp_continue_automation_run', array( $automation->id ) );
1740 } else {
1741 wp_schedule_single_event( current_time( 'timestamp' ) + $delay, 'automatorwp_continue_automation_run', array( $automation->id ) );
1742 }
1743 }
1744 }
1745
1746 return $result;
1747
1748 }
1749 add_action( 'automatorwp_run_automation', 'automatorwp_run_automation' );
1750
1751 /**
1752 * Continue an all users automation run (used to check if automation run has been cancelled)
1753 * Note: This function is only called by the single action/event schedule function
1754 *
1755 * @since 2.2.2
1756 *
1757 * @param int $automation_id The automation ID
1758 *
1759 * @return bool
1760 */
1761 function automatorwp_continue_automation_run( $automation_id ) {
1762
1763 global $automatorwp_run_automation_error;
1764
1765 // Initialize error
1766 $automatorwp_run_automation_error = '';
1767
1768 // Sanitization
1769 $automation_id = absint( $automation_id );
1770
1771 // Bail if automation id not provided
1772 if( $automation_id === 0 ) {
1773 $automatorwp_run_automation_error = __( 'Invalid automation ID.', 'automatorwp' );
1774 return false;
1775 }
1776
1777 // Get the automation
1778 $automation = automatorwp_get_automation_object( $automation_id );
1779
1780 // Bail if automation not found
1781 if( ! $automation ) {
1782 $automatorwp_run_automation_error = sprintf( __( 'Automation with ID %d not found.', 'automatorwp' ), $automation_id );
1783 return false;
1784 }
1785
1786 if( $automation->status !== 'in-progress' ) {
1787 $automatorwp_run_automation_error = __( 'Automation run has been cancelled.', 'automatorwp' );
1788 return false;
1789 }
1790
1791 // Continue running the automation
1792 automatorwp_run_automation( $automation->id );
1793
1794 }
1795 add_action( 'automatorwp_continue_automation_run', 'automatorwp_continue_automation_run' );
1796
1797 /**
1798 * Automation run started
1799 *
1800 * @since 2.2.2
1801 *
1802 * @param stdClass $automation The automation object
1803 * @param stdClass $trigger The trigger object
1804 * @param array $trigger_options The trigger stored option
1805 */
1806 function automatorwp_run_automation_started( $automation, $trigger, $trigger_options ) {
1807
1808 global $automatorwp_completed_triggers;
1809
1810 // Initialize completed triggers count
1811 if( ! is_array( $automatorwp_completed_triggers ) ) {
1812 $automatorwp_completed_triggers = array();
1813 }
1814
1815 if( ! is_object( $automation ) ) {
1816 return;
1817 }
1818
1819 // Store the original status
1820 automatorwp_update_automation_meta( $automation->id, 'original_status', $automation->status );
1821
1822 $ct_table = ct_setup_table( 'automatorwp_automations' );
1823
1824 // Update the automation status
1825 $ct_table->db->update(
1826 array( 'status' => 'in-progress' ),
1827 array( 'id' => $automation->id )
1828 );
1829
1830 ct_reset_setup_table();
1831
1832 // Get the trigger completion times
1833 $completion_times = automatorwp_get_object_completion_times( $trigger->id, 'trigger' );
1834
1835 $log_meta = array(
1836 'times' => ( $completion_times + 1 )
1837 );
1838
1839 /**
1840 * Filter to add custom log meta to meet that user has completed this trigger
1841 *
1842 * @since 1.0.0
1843 *
1844 * @param array $log_meta Log meta data
1845 * @param stdClass $trigger The trigger object
1846 * @param int $user_id The user ID
1847 * @param array $event Event information
1848 * @param array $trigger_options The trigger's stored options
1849 * @param stdClass $automation The trigger's automation object
1850 *
1851 * @return array
1852 */
1853 $log_meta = apply_filters( 'automatorwp_user_completed_trigger_log_meta', $log_meta, $trigger, 0, array(), $trigger_options, $automation );
1854
1855 // Insert a new log entry to register the trigger completion
1856 automatorwp_insert_log( array(
1857 'title' => automatorwp_parse_automation_item_log_label( $trigger, 'trigger', 'view' ),
1858 'type' => 'trigger',
1859 'object_id' => $trigger->id,
1860 'user_id' => 0,
1861 'post_id' => 0,
1862 'date' => automatorwp_get_event_log_date(),
1863 ), $log_meta );
1864
1865 $automatorwp_completed_triggers[] = $trigger;
1866
1867 }
1868
1869 /**
1870 * Check if automation run has been finished
1871 *
1872 * @since 2.2.2
1873 *
1874 * @param stdClass $automation The automation object
1875 *
1876 * @return bool
1877 */
1878 function automatorwp_maybe_run_automation_finished( $automation ) {
1879
1880 global $automatorwp_run_automation_error;
1881
1882 if( ! is_object( $automation ) ) {
1883 $automatorwp_run_automation_error = __( 'Invalid automation.', 'automatorwp' );
1884 return false;
1885 }
1886
1887 $details = automatorwp_get_automation_run_details( $automation );
1888
1889 if( ! $details ) {
1890 $automatorwp_run_automation_error = __( 'Can not retrieve run details.', 'automatorwp' );
1891 return false;
1892 }
1893
1894 // Check if finished
1895 if( $details['processed'] >= $details['count'] ) {
1896 return true;
1897 }
1898
1899 return false;
1900
1901 }
1902
1903 /**
1904 * Automation run finished
1905 *
1906 * @since 2.2.2
1907 *
1908 * @param stdClass $automation The automation object
1909 */
1910 function automatorwp_run_automation_finished( $automation ) {
1911
1912 global $automatorwp_run_automation_error;
1913
1914 if( ! is_object( $automation ) ) {
1915 $automatorwp_run_automation_error = __( 'Invalid automation.', 'automatorwp' );
1916 return;
1917 }
1918
1919 // Restore automation status
1920 $original_status = automatorwp_get_automation_meta( $automation->id, 'original_status', true );
1921
1922 if( empty( $original_status ) ) {
1923 $original_status = 'active';
1924 }
1925
1926 $ct_table = ct_setup_table( 'automatorwp_automations' );
1927
1928 // Update the automation status
1929 $ct_table->db->update(
1930 array( 'status' => $original_status ),
1931 array( 'id' => $automation->id )
1932 );
1933
1934 ct_reset_setup_table();
1935
1936 // Insert a new log entry to register the automation completion
1937 automatorwp_insert_log( array(
1938 'title' => $automation->title,
1939 'type' => 'automation',
1940 'object_id' => $automation->id,
1941 'user_id' => 0,
1942 'post_id' => 0,
1943 'date' => automatorwp_get_event_log_date(),
1944 ) );
1945
1946 // Increment the completions
1947 $completions = absint( automatorwp_get_automation_meta( $automation->id, 'completions', true ) );
1948 automatorwp_update_automation_meta( $automation->id, 'completions', $completions + 1 );
1949
1950 // Restore loop
1951 automatorwp_update_automation_meta( $automation->id, 'current_loop', 0 );
1952
1953 // Restore manual run flag
1954 automatorwp_update_automation_meta( $automation->id, 'manual_run', '' );
1955
1956 // Get the automation maximum completion times
1957 $times = absint( $automation->times );
1958
1959 // Prevent to update the next run date if automation already reached the total times allowed
1960 if( $times > 0 ) {
1961 if( $completions >= $times ) {
1962 return;
1963 }
1964 }
1965
1966 // Update the next run date
1967 automatorwp_update_automation_next_run_date( $automation->id );
1968
1969 }
1970
1971 /**
1972 * Cancel an all users automation rum
1973 *
1974 * @since 2.2.2
1975 *
1976 * @param int $automation_id The automation ID
1977 *
1978 * @return bool
1979 */
1980 function automatorwp_cancel_automation_run( $automation_id ) {
1981
1982 global $automatorwp_run_automation_error;
1983
1984 // Initialize error
1985 $automatorwp_run_automation_error = '';
1986
1987 // Sanitization
1988 $automation_id = absint( $automation_id );
1989
1990 // Bail if automation id not provided
1991 if( $automation_id === 0 ) {
1992 $automatorwp_run_automation_error = __( 'Invalid automation ID.', 'automatorwp' );
1993 return false;
1994 }
1995
1996 // Get the automation
1997 $automation = automatorwp_get_automation_object( $automation_id );
1998
1999 // Bail if automation not found
2000 if( ! $automation ) {
2001 $automatorwp_run_automation_error = sprintf( __( 'Automation with ID %d not found.', 'automatorwp' ), $automation_id );
2002 return false;
2003 }
2004
2005 if( $automation->status !== 'in-progress' ) {
2006 $automatorwp_run_automation_error = __( 'Can not cancel automation run because is not running.', 'automatorwp' );
2007 return false;
2008 }
2009
2010 // Restore automation status
2011 $original_status = automatorwp_get_automation_meta( $automation->id, 'original_status', true );
2012
2013 if( empty( $original_status ) ) {
2014 $original_status = 'active';
2015 }
2016
2017 $ct_table = ct_setup_table( 'automatorwp_automations' );
2018
2019 // Update the automation status
2020 $ct_table->db->update(
2021 array( 'status' => $original_status ),
2022 array( 'id' => $automation->id )
2023 );
2024
2025 ct_reset_setup_table();
2026
2027 // Insert a new log entry to register the automation completion
2028 automatorwp_insert_log( array(
2029 'title' => sprintf( __( '%s run cancelled by the user', 'automatorwp' ), $automation->title ),
2030 'type' => 'automation',
2031 'object_id' => $automation->id,
2032 'user_id' => get_current_user_id(),
2033 'post_id' => 0,
2034 'date' => automatorwp_get_event_log_date(),
2035 ) );
2036
2037 // Restore loop
2038 automatorwp_update_automation_meta( $automation->id, 'current_loop', 0 );
2039
2040 // Restore manual run flag
2041 automatorwp_update_automation_meta( $automation->id, 'manual_run', '' );
2042
2043 // Update the next run date
2044 automatorwp_update_automation_next_run_date( $automation->id );
2045
2046 return true;
2047
2048 }
2049
2050 /**
2051 * Helper function to get the last error happened in the run automation function
2052 *
2053 * @since 2.2.2
2054 *
2055 * @return string|null
2056 */
2057 function automatorwp_get_run_automation_error() {
2058
2059 global $automatorwp_run_automation_error;
2060
2061 return $automatorwp_run_automation_error;
2062 }
2063
2064 /**
2065 * Helper function to get the current log date on the events engine
2066 *
2067 * @since 1.0.0
2068 *
2069 * @return string
2070 */
2071 function automatorwp_get_event_log_date() {
2072
2073 global $automatorwp_completed_triggers;
2074
2075 // The global $automatorwp_completed_triggers is used to increase log time by the number of loops perform
2076 // This prevents unlimited completions when multiple triggers has been triggered
2077 if( ! is_array( $automatorwp_completed_triggers ) ) {
2078 $automatorwp_completed_triggers = array();
2079 }
2080
2081 return date( 'Y-m-d H:i:s', current_time( 'timestamp' ) + count( $automatorwp_completed_triggers ) );
2082
2083 }