PluginProbe
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI / 6.0.2
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI v6.0.2
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 5.6.2 All 33 releases
automatorwp / includes / events.php

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

2,085 lines 68.2 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 <contact@automatorwp.com>, Ruben Garcia <rubengcdev@gmail.com>
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 // Run hook based on action type
1329 do_action( "automatorwp_execute_action_{$action->type}", $action, $user_id, $event, $action_options, $automation );
1330
1331 $log_meta = array();
1332
1333 /**
1334 * Filter to add custom log meta to meet that and action has been executed to a specific user
1335 *
1336 * @since 1.0.0
1337 *
1338 * @param array $log_meta Log meta data
1339 * @param stdClass $action The action object
1340 * @param int $user_id The user ID
1341 * @param array $action_options The action's stored options (with tags already passed)
1342 * @param stdClass $automation The action's automation object
1343 *
1344 * @return array
1345 */
1346 $log_meta = apply_filters( 'automatorwp_user_completed_action_log_meta', $log_meta, $action, $user_id, $action_options, $automation );
1347
1348 /**
1349 * Filter to assign a custom post ID to this action
1350 *
1351 * @since 1.0.0
1352 *
1353 * @param int $post_id The post ID, by default 0
1354 * @param stdClass $action The action object
1355 * @param int $user_id The user ID
1356 * @param array $event Event information
1357 * @param array $action_options The action's stored options (with tags already passed)
1358 * @param stdClass $automation The action's automation object
1359 *
1360 * @return int
1361 */
1362 $post_id = apply_filters( 'automatorwp_user_completed_action_post_id', 0, $action, $user_id, $event, $action_options, $automation );
1363
1364 // Parse the log label (including the automation tags)
1365 $log_title = automatorwp_parse_automation_item_log_label( $action, 'action', 'view' );
1366 $log_title = automatorwp_parse_automation_tags( $automation->id, $user_id, $log_title );
1367
1368 // Insert a new log entry to register the trigger completion
1369 automatorwp_insert_log( array(
1370 'title' => $log_title,
1371 'type' => 'action',
1372 'object_id' => $action->id,
1373 'user_id' => $user_id,
1374 'post_id' => $post_id,
1375 'date' => automatorwp_get_event_log_date(),
1376 ), $log_meta );
1377
1378 /**
1379 * Available action to hook on an action completion
1380 *
1381 * @since 1.0.0
1382 *
1383 * @param stdClass $action The action object
1384 * @param int $user_id The user ID
1385 * @param array $event Event information
1386 * @param array $action_options The action's stored options (with tags already passed)
1387 * @param stdClass $automation The action's automation object
1388 */
1389 do_action( 'automatorwp_user_completed_action', $action, $user_id, $event, $action_options, $automation );
1390
1391 return true;
1392
1393 }
1394
1395 /**
1396 * Checks if an action should be executed or not
1397 *
1398 * @since 1.2.4
1399 *
1400 * @param stdClass $action The action object
1401 * @param int $user_id The user ID
1402 * @param array $event Event information
1403 * @param array $action_options The action's stored options (with tags already passed)
1404 * @param stdClass $automation The action's automation object
1405 *
1406 * @return bool
1407 */
1408 function automatorwp_can_execute_action( $action = null, $user_id = 0, $event = array(), $action_options = array(), $automation = null ) {
1409
1410 // Check if action is correct
1411 if( ! is_object( $action ) ) {
1412 return false;
1413 }
1414
1415 // Check the user ID
1416 if( $user_id === 0 ) {
1417 return false;
1418 }
1419
1420 // Check if automation is correct
1421 if( $automation === null ) {
1422 $automation = automatorwp_get_action_automation( $action->id );
1423
1424 if( ! is_object( $automation ) ) {
1425 return false;
1426 }
1427 }
1428
1429 $execute = true;
1430
1431 /**
1432 * Available filter to determine if an action should be executed or not
1433 *
1434 * @since 1.2.4
1435 *
1436 * @param bool $execute Determines if the action should be executed, by default true
1437 * @param stdClass $action The action object
1438 * @param int $user_id The user ID
1439 * @param array $event Event information
1440 * @param array $action_options The action's stored options (with tags already passed)
1441 * @param stdClass $automation The action's automation object
1442 *
1443 * @return bool
1444 */
1445 return apply_filters( 'automatorwp_can_execute_action', $execute, $action, $user_id, $event, $action_options, $automation );
1446
1447 }
1448
1449 /**
1450 * Check if user deserves action filters
1451 *
1452 * @since 1.0.0
1453 *
1454 * @param stdClass $action The action object
1455 * @param int $user_id The user ID
1456 * @param array $event Event information
1457 * @param array $action_options The action's stored options
1458 * @param stdClass $automation The action's automation object
1459 *
1460 * @return bool True if user deserves action, false otherwise
1461 */
1462 function automatorwp_user_deserves_action_filters( $action = null, $user_id = 0, $event = array(), $action_options = array(), $automation = null ) {
1463
1464 global $automatorwp_completed_action_filters, $automatorwp_last_action_passed_all_filters;
1465
1466 // Check if action is correct
1467 if( ! is_object( $action ) ) {
1468 return false;
1469 }
1470
1471 // Check the user ID
1472 if( $user_id === 0 ) {
1473 return false;
1474 }
1475
1476 // Check if automation is correct
1477 if( $automation === null ) {
1478 $automation = automatorwp_get_action_automation( $action->id );
1479
1480 if( ! is_object( $automation ) ) {
1481 return false;
1482 }
1483 }
1484
1485 $deserves_action_filters = true;
1486
1487 // Bail if is a filter
1488 if( $action->type === 'filter' ) {
1489
1490 if( ! is_array( $automatorwp_completed_action_filters ) ) {
1491 return false;
1492 }
1493
1494 if( ! $automatorwp_last_action_passed_all_filters ) {
1495 return false;
1496 }
1497
1498 $found = false;
1499
1500 foreach ( $automatorwp_completed_action_filters as $filter ) {
1501 if( absint( $filter->id ) === absint( $action->id ) ) {
1502 $found = true;
1503 }
1504 }
1505
1506 // If filter has not been passed, prevent its execution
1507 if( ! $found ) {
1508 return false;
1509 }
1510
1511 return $deserves_action_filters;
1512 }
1513
1514 // Initialize completed actions
1515 $automatorwp_completed_action_filters = array();
1516 $automatorwp_last_action_passed_all_filters = false;
1517
1518 $filters = automatorwp_get_action_filters( $action );
1519
1520 foreach( $filters as $i => $filter ) {
1521
1522 $deserves_filter = true;
1523
1524 // Get the action stored options
1525 $filter_options = automatorwp_get_filter_stored_options( $filter->id, 'action' );
1526
1527 foreach( $filter_options as $option => $value ) {
1528 // Replace all tags by their replacements
1529 $filter_options[$option] = automatorwp_parse_automation_tags( $automation->id, $user_id, $value );
1530 }
1531
1532 /**
1533 * Filter to override the user deserves filter check.
1534 * This filter is to check the filter configuration.
1535 * Filters should use this filter.
1536 *
1537 * @since 1.0.0
1538 *
1539 * @param bool $deserves_filter True if user deserves filter, false otherwise
1540 * @param stdClass $filter The filter object
1541 * @param int $user_id The user ID
1542 * @param array $event Event information
1543 * @param array $filter_options The filter's stored options
1544 * @param stdClass $automation The filter's automation object
1545 *
1546 * @return bool True if user deserves filter, false otherwise
1547 */
1548 $deserves_filter = apply_filters( 'automatorwp_user_deserves_action_filter', $deserves_filter, $filter, $user_id, $event, $filter_options, $automation );
1549
1550 if( $i === 0 ) {
1551 // On first filter there is no need to apply the operator
1552 $deserves_action_filters = $deserves_filter;
1553 } else {
1554 // Apply the operator
1555 if( $filter_options['operator'] === 'and' ) {
1556 $deserves_action_filters = $deserves_action_filters && $deserves_filter;
1557 } else {
1558 $deserves_action_filters = $deserves_action_filters || $deserves_filter;
1559 }
1560 }
1561
1562 // Store completed filters
1563 if( $deserves_filter ) {
1564 $automatorwp_completed_action_filters[] = $filter;
1565 }
1566
1567 // Break this loop if the action filters are not passed
1568 if( ! $deserves_action_filters ) {
1569
1570 // For OR operators, prevent to bail until check all of them
1571 if( $i < count( $filters ) && $filter_options['operator'] === 'or' ) {
1572 continue;
1573 }
1574
1575 // Register why user has not completed this filter
1576 $log_meta = array(
1577 'item_type' => 'action'
1578 );
1579
1580 /**
1581 * Filter to add custom log meta to meet that user has completed this action
1582 *
1583 * @since 1.0.0
1584 *
1585 * @param array $log_meta Log meta data
1586 * @param stdClass $filter The filter object
1587 * @param int $user_id The user ID
1588 * @param array $event Event information
1589 * @param array $filter_options The filter's stored options
1590 * @param stdClass $automation The filter's automation object
1591 *
1592 * @return array
1593 */
1594 $log_meta = apply_filters( 'automatorwp_user_not_passed_filter_log_meta', $log_meta, $filter, $user_id, $event, $filter_options, $automation );
1595
1596 // Parse the log label (including the automation tags)
1597 $log_title = automatorwp_parse_automation_item_log_label( $filter, 'action', 'view' );
1598 $log_title = automatorwp_parse_automation_tags( $automation->id, $user_id, $log_title );
1599
1600 // Insert a new log entry to register why user not passed the action filter
1601 automatorwp_insert_log( array(
1602 'title' => $log_title,
1603 'type' => 'filter',
1604 'object_id' => $filter->id,
1605 'user_id' => $user_id,
1606 'post_id' => ( isset( $event['post_id'] ) ? $event['post_id'] : 0 ),
1607 'date' => automatorwp_get_event_log_date(),
1608 ), $log_meta );
1609
1610 // Force to clear the cache for this filter
1611 automatorwp_clear_user_last_completion_cache( $filter, $user_id, 'filter' );
1612
1613 break;
1614 }
1615
1616 }
1617
1618 /**
1619 * Filter to override the user deserves action filters check.
1620 *
1621 * @since 1.0.0
1622 *
1623 * @param bool $deserves_action_filters True if user deserves the action filters, false otherwise
1624 * @param stdClass $action The action object
1625 * @param int $user_id The user ID
1626 * @param array $event Event information
1627 * @param array $action_options The action's stored options
1628 * @param stdClass $automation The action's automation object
1629 *
1630 * @return bool True if user deserves action, false otherwise
1631 */
1632 $deserves_action_filters = apply_filters( 'automatorwp_user_deserves_action_filters', $deserves_action_filters, $action, $user_id, $event, $action_options, $automation );
1633
1634 // Used to meet if should register the rest of filter actions
1635 $automatorwp_last_action_passed_all_filters = $deserves_action_filters;
1636
1637 return $deserves_action_filters;
1638 }
1639
1640 // -------------------------------------------
1641 // Automation execution
1642 // -------------------------------------------
1643
1644 /**
1645 * Run an automation
1646 *
1647 * @since 2.2.2
1648 *
1649 * @param int $automation_id The automation ID
1650 *
1651 * @return bool
1652 */
1653 function automatorwp_run_automation( $automation_id ) {
1654
1655 global $automatorwp_run_automation_error;
1656
1657 // Initialize error
1658 $automatorwp_run_automation_error = '';
1659
1660 // Sanitization
1661 $automation_id = absint( $automation_id );
1662
1663 // Bail if automation id not provided
1664 if( $automation_id === 0 ) {
1665 $automatorwp_run_automation_error = __( 'Invalid automation ID.', 'automatorwp' );
1666 return false;
1667 }
1668
1669 // Get the automation
1670 $automation = automatorwp_get_automation_object( $automation_id );
1671
1672 // Bail if automation not found
1673 if( ! $automation ) {
1674 $automatorwp_run_automation_error = sprintf( __( 'Automation with ID %d not found.', 'automatorwp' ), $automation_id );
1675 return false;
1676 }
1677
1678 // Only loop automations can be run here
1679 if( ! in_array( $automation->type, automatorwp_get_automation_loop_types() ) ) {
1680 $automatorwp_run_automation_error = __( 'Invalid automation type.', 'automatorwp' );
1681 return false;
1682 }
1683
1684 // Check if exceeded automation completion times
1685 $times = absint( $automation->times );
1686
1687 if( $times > 0 ) {
1688 $completion_times = automatorwp_get_object_completion_times( $automation->id, 'automation' );
1689
1690 if( $completion_times >= $times ) {
1691 $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' );
1692 return false;
1693 }
1694 }
1695
1696 $result = apply_filters( 'automatorwp_run_automation_result', false, $automation );
1697
1698 // Bail if automation has not run correctly
1699 if( ! $result ) {
1700 return false;
1701 }
1702
1703 // Check if run finished
1704 if( automatorwp_maybe_run_automation_finished( $automation ) ) {
1705 // Call the automation run finished function
1706 automatorwp_run_automation_finished( $automation );
1707 } else {
1708 // Increase loop
1709 $loop = absint( automatorwp_get_automation_meta( $automation->id, 'current_loop', true ) );
1710 automatorwp_update_automation_meta( $automation->id, 'current_loop', $loop + 1 );
1711
1712 // Check if is a manual run
1713 $manual_run = (bool) automatorwp_get_automation_meta( $automation->id, 'manual_run', true );
1714
1715 if( ! $manual_run ) {
1716
1717 // Get the delay amount and seconds from the automation
1718 $delay_amount = absint( automatorwp_get_automation_meta( $automation->id, 'delay_amount', true ) );
1719 $delay_seconds = absint( automatorwp_get_automation_meta( $automation->id, 'delay_seconds', true ) );
1720
1721 $delay = $delay_amount * $delay_seconds;
1722
1723 if( $delay <= 0 ) {
1724 $delay = 60;
1725 }
1726
1727 /**
1728 * Available filter to override the delay between runs
1729 *
1730 * @since 1.0.0
1731 *
1732 * @param int $delay By default, 60 (1 minute)
1733 * @param stdClass $automation The automation object
1734 *
1735 * @return int
1736 */
1737 $delay = apply_filters( 'automatorwp_run_automation_delay_between_runs', $delay, $automation );
1738
1739 // if not is a manual run, schedule this function after a delay
1740 if( function_exists( 'as_schedule_single_action' ) ) {
1741 as_schedule_single_action( current_time( 'timestamp' ) + $delay, 'automatorwp_continue_automation_run', array( $automation->id ) );
1742 } else {
1743 wp_schedule_single_event( current_time( 'timestamp' ) + $delay, 'automatorwp_continue_automation_run', array( $automation->id ) );
1744 }
1745 }
1746 }
1747
1748 return $result;
1749
1750 }
1751 add_action( 'automatorwp_run_automation', 'automatorwp_run_automation' );
1752
1753 /**
1754 * Continue an all users automation run (used to check if automation run has been cancelled)
1755 * Note: This function is only called by the single action/event schedule function
1756 *
1757 * @since 2.2.2
1758 *
1759 * @param int $automation_id The automation ID
1760 *
1761 * @return bool
1762 */
1763 function automatorwp_continue_automation_run( $automation_id ) {
1764
1765 global $automatorwp_run_automation_error;
1766
1767 // Initialize error
1768 $automatorwp_run_automation_error = '';
1769
1770 // Sanitization
1771 $automation_id = absint( $automation_id );
1772
1773 // Bail if automation id not provided
1774 if( $automation_id === 0 ) {
1775 $automatorwp_run_automation_error = __( 'Invalid automation ID.', 'automatorwp' );
1776 return false;
1777 }
1778
1779 // Get the automation
1780 $automation = automatorwp_get_automation_object( $automation_id );
1781
1782 // Bail if automation not found
1783 if( ! $automation ) {
1784 $automatorwp_run_automation_error = sprintf( __( 'Automation with ID %d not found.', 'automatorwp' ), $automation_id );
1785 return false;
1786 }
1787
1788 if( $automation->status !== 'in-progress' ) {
1789 $automatorwp_run_automation_error = __( 'Automation run has been cancelled.', 'automatorwp' );
1790 return false;
1791 }
1792
1793 // Continue running the automation
1794 automatorwp_run_automation( $automation->id );
1795
1796 }
1797 add_action( 'automatorwp_continue_automation_run', 'automatorwp_continue_automation_run' );
1798
1799 /**
1800 * Automation run started
1801 *
1802 * @since 2.2.2
1803 *
1804 * @param stdClass $automation The automation object
1805 * @param stdClass $trigger The trigger object
1806 * @param array $trigger_options The trigger stored option
1807 */
1808 function automatorwp_run_automation_started( $automation, $trigger, $trigger_options ) {
1809
1810 global $automatorwp_completed_triggers;
1811
1812 // Initialize completed triggers count
1813 if( ! is_array( $automatorwp_completed_triggers ) ) {
1814 $automatorwp_completed_triggers = array();
1815 }
1816
1817 if( ! is_object( $automation ) ) {
1818 return;
1819 }
1820
1821 // Store the original status
1822 automatorwp_update_automation_meta( $automation->id, 'original_status', $automation->status );
1823
1824 $ct_table = ct_setup_table( 'automatorwp_automations' );
1825
1826 // Update the automation status
1827 $ct_table->db->update(
1828 array( 'status' => 'in-progress' ),
1829 array( 'id' => $automation->id )
1830 );
1831
1832 ct_reset_setup_table();
1833
1834 // Get the trigger completion times
1835 $completion_times = automatorwp_get_object_completion_times( $trigger->id, 'trigger' );
1836
1837 $log_meta = array(
1838 'times' => ( $completion_times + 1 )
1839 );
1840
1841 /**
1842 * Filter to add custom log meta to meet that user has completed this trigger
1843 *
1844 * @since 1.0.0
1845 *
1846 * @param array $log_meta Log meta data
1847 * @param stdClass $trigger The trigger object
1848 * @param int $user_id The user ID
1849 * @param array $event Event information
1850 * @param array $trigger_options The trigger's stored options
1851 * @param stdClass $automation The trigger's automation object
1852 *
1853 * @return array
1854 */
1855 $log_meta = apply_filters( 'automatorwp_user_completed_trigger_log_meta', $log_meta, $trigger, 0, array(), $trigger_options, $automation );
1856
1857 // Insert a new log entry to register the trigger completion
1858 automatorwp_insert_log( array(
1859 'title' => automatorwp_parse_automation_item_log_label( $trigger, 'trigger', 'view' ),
1860 'type' => 'trigger',
1861 'object_id' => $trigger->id,
1862 'user_id' => 0,
1863 'post_id' => 0,
1864 'date' => automatorwp_get_event_log_date(),
1865 ), $log_meta );
1866
1867 $automatorwp_completed_triggers[] = $trigger;
1868
1869 }
1870
1871 /**
1872 * Check if automation run has been finished
1873 *
1874 * @since 2.2.2
1875 *
1876 * @param stdClass $automation The automation object
1877 *
1878 * @return bool
1879 */
1880 function automatorwp_maybe_run_automation_finished( $automation ) {
1881
1882 global $automatorwp_run_automation_error;
1883
1884 if( ! is_object( $automation ) ) {
1885 $automatorwp_run_automation_error = __( 'Invalid automation.', 'automatorwp' );
1886 return false;
1887 }
1888
1889 $details = automatorwp_get_automation_run_details( $automation );
1890
1891 if( ! $details ) {
1892 $automatorwp_run_automation_error = __( 'Can not retrieve run details.', 'automatorwp' );
1893 return false;
1894 }
1895
1896 // Check if finished
1897 if( $details['processed'] >= $details['count'] ) {
1898 return true;
1899 }
1900
1901 return false;
1902
1903 }
1904
1905 /**
1906 * Automation run finished
1907 *
1908 * @since 2.2.2
1909 *
1910 * @param stdClass $automation The automation object
1911 */
1912 function automatorwp_run_automation_finished( $automation ) {
1913
1914 global $automatorwp_run_automation_error;
1915
1916 if( ! is_object( $automation ) ) {
1917 $automatorwp_run_automation_error = __( 'Invalid automation.', 'automatorwp' );
1918 return;
1919 }
1920
1921 // Restore automation status
1922 $original_status = automatorwp_get_automation_meta( $automation->id, 'original_status', true );
1923
1924 if( empty( $original_status ) ) {
1925 $original_status = 'active';
1926 }
1927
1928 $ct_table = ct_setup_table( 'automatorwp_automations' );
1929
1930 // Update the automation status
1931 $ct_table->db->update(
1932 array( 'status' => $original_status ),
1933 array( 'id' => $automation->id )
1934 );
1935
1936 ct_reset_setup_table();
1937
1938 // Insert a new log entry to register the automation completion
1939 automatorwp_insert_log( array(
1940 'title' => $automation->title,
1941 'type' => 'automation',
1942 'object_id' => $automation->id,
1943 'user_id' => 0,
1944 'post_id' => 0,
1945 'date' => automatorwp_get_event_log_date(),
1946 ) );
1947
1948 // Increment the completions
1949 $completions = absint( automatorwp_get_automation_meta( $automation->id, 'completions', true ) );
1950 automatorwp_update_automation_meta( $automation->id, 'completions', $completions + 1 );
1951
1952 // Restore loop
1953 automatorwp_update_automation_meta( $automation->id, 'current_loop', 0 );
1954
1955 // Restore manual run flag
1956 automatorwp_update_automation_meta( $automation->id, 'manual_run', '' );
1957
1958 // Get the automation maximum completion times
1959 $times = absint( $automation->times );
1960
1961 // Prevent to update the next run date if automation already reached the total times allowed
1962 if( $times > 0 ) {
1963 if( $completions >= $times ) {
1964 return;
1965 }
1966 }
1967
1968 // Update the next run date
1969 automatorwp_update_automation_next_run_date( $automation->id );
1970
1971 }
1972
1973 /**
1974 * Cancel an all users automation rum
1975 *
1976 * @since 2.2.2
1977 *
1978 * @param int $automation_id The automation ID
1979 *
1980 * @return bool
1981 */
1982 function automatorwp_cancel_automation_run( $automation_id ) {
1983
1984 global $automatorwp_run_automation_error;
1985
1986 // Initialize error
1987 $automatorwp_run_automation_error = '';
1988
1989 // Sanitization
1990 $automation_id = absint( $automation_id );
1991
1992 // Bail if automation id not provided
1993 if( $automation_id === 0 ) {
1994 $automatorwp_run_automation_error = __( 'Invalid automation ID.', 'automatorwp' );
1995 return false;
1996 }
1997
1998 // Get the automation
1999 $automation = automatorwp_get_automation_object( $automation_id );
2000
2001 // Bail if automation not found
2002 if( ! $automation ) {
2003 $automatorwp_run_automation_error = sprintf( __( 'Automation with ID %d not found.', 'automatorwp' ), $automation_id );
2004 return false;
2005 }
2006
2007 if( $automation->status !== 'in-progress' ) {
2008 $automatorwp_run_automation_error = __( 'Can not cancel automation run because is not running.', 'automatorwp' );
2009 return false;
2010 }
2011
2012 // Restore automation status
2013 $original_status = automatorwp_get_automation_meta( $automation->id, 'original_status', true );
2014
2015 if( empty( $original_status ) ) {
2016 $original_status = 'active';
2017 }
2018
2019 $ct_table = ct_setup_table( 'automatorwp_automations' );
2020
2021 // Update the automation status
2022 $ct_table->db->update(
2023 array( 'status' => $original_status ),
2024 array( 'id' => $automation->id )
2025 );
2026
2027 ct_reset_setup_table();
2028
2029 // Insert a new log entry to register the automation completion
2030 automatorwp_insert_log( array(
2031 'title' => sprintf( __( '%s run cancelled by the user', 'automatorwp' ), $automation->title ),
2032 'type' => 'automation',
2033 'object_id' => $automation->id,
2034 'user_id' => get_current_user_id(),
2035 'post_id' => 0,
2036 'date' => automatorwp_get_event_log_date(),
2037 ) );
2038
2039 // Restore loop
2040 automatorwp_update_automation_meta( $automation->id, 'current_loop', 0 );
2041
2042 // Restore manual run flag
2043 automatorwp_update_automation_meta( $automation->id, 'manual_run', '' );
2044
2045 // Update the next run date
2046 automatorwp_update_automation_next_run_date( $automation->id );
2047
2048 return true;
2049
2050 }
2051
2052 /**
2053 * Helper function to get the last error happened in the run automation function
2054 *
2055 * @since 2.2.2
2056 *
2057 * @return string|null
2058 */
2059 function automatorwp_get_run_automation_error() {
2060
2061 global $automatorwp_run_automation_error;
2062
2063 return $automatorwp_run_automation_error;
2064 }
2065
2066 /**
2067 * Helper function to get the current log date on the events engine
2068 *
2069 * @since 1.0.0
2070 *
2071 * @return string
2072 */
2073 function automatorwp_get_event_log_date() {
2074
2075 global $automatorwp_completed_triggers;
2076
2077 // The global $automatorwp_completed_triggers is used to increase log time by the number of loops perform
2078 // This prevents unlimited completions when multiple triggers has been triggered
2079 if( ! is_array( $automatorwp_completed_triggers ) ) {
2080 $automatorwp_completed_triggers = array();
2081 }
2082
2083 return date( 'Y-m-d H:i:s', current_time( 'timestamp' ) + count( $automatorwp_completed_triggers ) );
2084
2085 }