PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 8.0.1
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v8.0.1
8.0.1 8.0.2 8.0.0 7.9.9.7 7.9.9.6 7.9.9.5 7.9.9.4 7.9.9.3 7.9.9.2 7.9.9.1 7.9.9 7.9.8 7.9.7 7.9.6 7.9.5 7.9.4 7.9.3 7.9.2 7.9.1 7.9.0 7.8.9 7.8.8 7.8.7 7.8.6 7.8.5 All 44 releases
gamipress / includes / listeners.php

listeners.php in GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI 8.0.1, at includes/listeners.php

693 lines 21.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Activity Listeners
4 *
5 * @package GamiPress\Listeners
6 * @author GamiPress <contact@gamipress.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 * Listener for user log in
14 *
15 * Triggers: gamipress_register
16 *
17 * @since 1.5.9
18 *
19 * @param int $user_id New registered user ID.
20 */
21 function gamipress_register_listener( $user_id ) {
22
23 // Sometimes this event is triggered before gamipress_load_activity_triggers()
24 // so to avoid issues, method has changed to trigger the event directly
25 do_action( 'gamipress_register', $user_id );
26
27 gamipress_trigger_event( array(
28 'event' => 'gamipress_register',
29 'user_id' => $user_id,
30 ) );
31
32 }
33 add_action( 'user_register', 'gamipress_register_listener' );
34
35 /**
36 * Listener for user log in
37 *
38 * Triggers: gamipress_login
39 *
40 * @since 1.1.0
41 * @updated 1.4.3 Changed event triggering by calling directly to gamipress_trigger_event()
42 *
43 * @param string $user_login Username.
44 * @param WP_User $user WP_User object of the logged-in user.
45 */
46 function gamipress_login_listener( $user_login, $user = null ) {
47
48 // Some login form plugins call this hook just passing the user ID so let's check if user is registered
49 if( ! $user ) {
50 $user = get_user_by( 'email', $user_login );
51
52 // Bail if user can't be found through email
53 if( ! $user ) {
54 return;
55 }
56 }
57
58 // Sometimes this event is triggered before gamipress_load_activity_triggers()
59 // so to avoid issues, method has changed to trigger the event directly
60
61 // Action is maintained for backward compatibility
62 do_action( 'gamipress_login', $user->ID, $user );
63
64 gamipress_trigger_event( array(
65 'event' => 'gamipress_login',
66 'user_id' => $user->ID,
67 ) );
68
69 }
70 add_action( 'wp_login', 'gamipress_login_listener', 10, 2 );
71
72 /**
73 * Listener for content publishing
74 *
75 * Triggers: gamipress_publish_{$post_type}
76 *
77 * @since 1.0.0
78 * @updated 1.8.9 Changed event triggering by calling directly to gamipress_trigger_event()
79 *
80 * @param string $new_status The new post status
81 * @param string $old_status The old post status
82 * @param WP_Post $post The post
83 *
84 * @return void
85 */
86 function gamipress_transition_post_status_listener( $new_status, $old_status, $post ) {
87
88 // Statuses to check the old status
89 $old_statuses = apply_filters( 'gamipress_publish_listener_old_status', array( 'new', 'auto-draft', 'draft', 'private', 'pending', 'future' ), $post->ID );
90
91 // Statuses to check the new status
92 $new_statuses = apply_filters( 'gamipress_publish_listener_new_status', array( 'publish', 'private' ), $post->ID );
93
94 // Check if post status transition come to publish
95 if ( in_array( $old_status, $old_statuses ) && in_array( $new_status, $new_statuses ) ) {
96
97 // Trigger content publishing actions
98 gamipress_trigger_event( array(
99 'event' => "gamipress_publish_{$post->post_type}",
100 'post_id' => $post->ID,
101 'user_id' => $post->post_author,
102 'post' => $post,
103 ) );
104
105 // Trigger post type publishing actions
106 gamipress_trigger_event( array(
107 'event' => 'gamipress_publish_post_type',
108 'post_id' => $post->ID,
109 'user_id' => $post->post_author,
110 'post_type' => $post->post_type,
111 'post' => $post,
112 ) );
113 }
114
115 }
116 add_action( 'transition_post_status', 'gamipress_transition_post_status_listener', 10, 3 );
117
118 /**
119 * Listener for content deletion
120 *
121 * Triggers: gamipress_delete_{$post_type}
122 *
123 * @since 1.3.7
124 * @updated 1.8.9 Changed event triggering by calling directly to gamipress_trigger_event()
125 *
126 * @param integer $post_id The deleted post ID
127 * @param object|string $post_data
128 *
129 * @return void
130 */
131 function gamipress_delete_post_listener( $post_id = 0, $post_data = null ) {
132
133 $post = get_post( $post_id );
134
135 if( ! $post ) {
136 return;
137 }
138
139 if( $post_data === null ) {
140 return;
141 }
142
143 // trashed_post hook returns string with previous status
144 // before_delete_post hook returns WP_post with eliminated post data
145 $post_status = ( is_object( $post_data ) ) ? $post_data->post_status : $post_data;
146
147 if( ! in_array( $post_status, array( 'publish', 'private' ) ) ) {
148 return;
149 }
150
151 // Trigger content deletion actions
152 gamipress_trigger_event( array(
153 'event' => "gamipress_delete_{$post->post_type}",
154 'post_id' => $post->ID,
155 'user_id' => $post->post_author,
156 'post' => $post,
157 ) );
158
159 // Trigger post type deletion actions
160 gamipress_trigger_event( array(
161 'event' => 'gamipress_delete_post_type',
162 'post_id' => $post->ID,
163 'user_id' => $post->post_author,
164 'post_type' => $post->post_type,
165 'post' => $post,
166 ) );
167
168 }
169 add_action( 'trashed_post', 'gamipress_delete_post_listener', 10, 2 );
170 add_action( 'before_delete_post', 'gamipress_delete_post_listener', 10, 2 );
171
172 /**
173 * Listener for comment publishing
174 *
175 * Triggers: gamipress_new_comment, gamipress_specific_new_comment
176 *
177 * @since 1.0.0
178 *
179 * @param integer $comment_ID The comment ID
180 * @param array|object $comment The comment array
181 *
182 * @return void
183 */
184 function gamipress_approved_comment_listener( $comment_ID, $comment ) {
185
186 // Ensure comment as array (wp_insert_comment uses object, comment_{status}_comment uses array)
187 if ( is_object( $comment ) ) {
188 $comment = get_object_vars( $comment );
189 }
190
191 // Check if comment is approved
192 if ( (int) $comment['comment_approved'] !== 1 ) {
193 return;
194 }
195
196 // Setup vars
197 $comment_id = (int) $comment_ID;
198 $user_id = (int) $comment['user_id'];
199 $post_id = absint( $comment[ 'comment_post_ID' ] );
200 $post_type = get_post_type( $post_id );
201 $post_author = absint( get_post_field( 'post_author', $post_id ) );
202
203 if ( $user_id !== $post_author ) {
204 // Trigger comment actions
205 do_action( 'gamipress_new_comment', $comment_id, $user_id, $post_id, $comment );
206 do_action( 'gamipress_specific_new_comment', $comment_id, $user_id, $post_id, $comment );
207 do_action( 'gamipress_new_comment_post_type', $comment_id, $user_id, $post_id, $post_type, $comment );
208
209 if( $post_id !== 0 ) {
210
211 // Trigger comment actions to author
212 do_action( 'gamipress_user_post_comment', $comment_id, $post_author, $post_id, $comment );
213 do_action( 'gamipress_user_specific_post_comment', $comment_id, $post_author, $post_id, $comment );
214 do_action( 'gamipress_user_post_comment_post_type', $comment_id, $post_author, $post_id, $post_type, $comment );
215 }
216 }
217
218
219
220 }
221 add_action( 'comment_approved_', 'gamipress_approved_comment_listener', 10, 2 );
222 add_action( 'comment_approved_comment', 'gamipress_approved_comment_listener', 10, 2 );
223 add_action( 'wp_insert_comment', 'gamipress_approved_comment_listener', 10, 2 );
224
225 /**
226 * Listener for comment marked as spam
227 *
228 * Triggers: gamipress_spam_comment, gamipress_specific_spam_comment
229 *
230 * @since 1.7.3
231 *
232 * @param integer $comment_ID The comment ID
233 * @param array|object $comment The comment array
234 *
235 * @return void
236 */
237 function gamipress_spam_comment_listener( $comment_ID, $comment ) {
238
239 // Ensure comment as array
240 if ( is_object( $comment ) ) {
241 $comment = get_object_vars( $comment );
242 }
243
244 // Setup vars
245 $comment_id = (int) $comment_ID;
246 $user_id = (int) $comment['user_id'];
247 $post_id = absint( $comment[ 'comment_post_ID' ] );
248 $post_type = get_post_type( $post_id );
249
250 // Trigger comment actions
251 do_action( 'gamipress_spam_comment', $comment_id, $user_id, $post_id, $comment );
252 do_action( 'gamipress_specific_spam_comment', $comment_id, $user_id, $post_id, $comment );
253 do_action( 'gamipress_spam_comment_post_type', $comment_id, $user_id, $post_id, $post_type, $comment );
254
255 }
256 add_action( 'comment_spam_', 'gamipress_spam_comment_listener', 10, 2 );
257 add_action( 'comment_spam_comment', 'gamipress_spam_comment_listener', 10, 2 );
258
259 /**
260 * Listener for sote daily visits
261 *
262 * Triggers: gamipress_site_visit
263 *
264 * @since 1.0.0
265 * @updated 1.5.1 Now is triggered through ajax
266 * @updated 6.6.0 Triggered through WordPress hook
267 *
268 * @return void
269 */
270 function gamipress_site_visit_listener() {
271
272 // Current time
273 $now = strtotime( date( 'Y-m-d 00:00:00', current_time( 'timestamp' ) ) );
274
275 // ---------------------------
276 // Website daily visit
277 // ---------------------------
278
279 global $post;
280
281 // Bail if in admin area
282 if( is_admin() ) {
283 return;
284 }
285
286 // Bail if not post instanced
287 if( ! $post instanceof WP_Post ) {
288 return;
289 }
290
291 $user_id = get_current_user_id();
292
293 // Bail if user is not logged in
294 if( $user_id === 0 ) {
295 return;
296 }
297
298 /**
299 * Filter to set if site visits should be tracked or not
300 *
301 * @since 1.5.1
302 *
303 * @param bool $track_visits Whatever if visits should be tracked (default true)
304 * @param int $user_id The user ID that made the visit
305 *
306 * @return bool
307 */
308 $track_visits = apply_filters( 'gamipress_track_site_visits', true, $user_id );
309
310 if( $track_visits && gamipress_trigger_has_listeners( 'gamipress_site_visit', get_current_blog_id(), array( 'gamipress_site_visit', $user_id ) ) ) {
311
312 $count = gamipress_get_user_trigger_count( $user_id, 'gamipress_site_visit', $now );
313
314 // Trigger daily visit action if not triggered today
315 if( $count === 0 ) {
316 do_action( 'gamipress_site_visit', $user_id );
317 }
318
319 }
320
321 }
322 add_action( 'template_redirect', 'gamipress_site_visit_listener' );
323
324 /**
325 * Listener for daily post visits
326 *
327 * Triggers: gamipress_specific_post_visit, gamipress_user_post_visit, gamipress_user_specific_post_visit
328 *
329 * @since 1.0.0
330 * @updated 1.5.1 Now is triggered through ajax
331 * @updated 6.6.0 Triggered through WordPress hook
332 *
333 * @return void
334 */
335 function gamipress_post_visit_listener() {
336
337 // Current time
338 $now = strtotime( date( 'Y-m-d 00:00:00', current_time( 'timestamp' ) ) );
339
340 // ---------------------------
341 // Website daily visit
342 // ---------------------------
343
344 if ( ! is_singular() ) {
345 return;
346 }
347
348 global $post;
349
350 // Bail if in admin area
351 if( is_admin() ) {
352 return;
353 }
354
355 // Bail if not post instanced
356 if( ! $post instanceof WP_Post ) {
357 return;
358 }
359
360 // Get current post if no ID
361 if ( ! $post->ID ) {
362 $post = get_post( get_queried_object_id() );
363 }
364
365 $user_id = get_current_user_id();
366
367 // Bail if user is not logged in
368 if( $user_id === 0 ) {
369 return;
370 }
371
372 // ---------------------------
373 // Post daily visit
374 // ---------------------------
375
376 /**
377 * Filter to set if post visits should be tracked or not
378 *
379 * Note: Post visits event will award to the visitor
380 *
381 * @since 1.5.1
382 *
383 * @param bool $track_visits Whatever if post visits should be tracked (default true)
384 * @param int $user_id The user ID that made the visit
385 * @param int $post_id The post ID that has been visited
386 * @param int $post The post object that has been visited
387 *
388 * @return bool
389 */
390 $track_post_visits = apply_filters( 'gamipress_track_post_visits', true, $user_id, $post->ID, $post );
391
392 if( $track_post_visits ) {
393
394 if ( gamipress_trigger_has_listeners( 'gamipress_post_visit', get_current_blog_id(), array( 'gamipress_post_visit', $post->ID, $user_id, $post ) ) ) {
395
396 $log_meta = array(
397 'type' => 'event_trigger',
398 'trigger_type' => 'gamipress_post_visit',
399 'post_id' => $post->ID,
400 );
401
402 // Get the trigger count
403 $count = gamipress_get_user_log_count( $user_id, $log_meta, $now );
404
405 // Trigger daily post visit action if not triggered today
406 if( $count === 0 ) {
407 // Trigger any post visit
408 do_action( 'gamipress_post_visit', $post->ID, $user_id, $post );
409 }
410 }
411
412
413 if ( gamipress_trigger_has_listeners( 'gamipress_post_type_visit', get_current_blog_id(), array( 'gamipress_post_type_visit', $post->ID, $user_id, $post->post_type, $post ) ) ) {
414
415 $log_meta_post_type = array(
416 'type' => 'event_trigger',
417 'trigger_type' => 'gamipress_post_type_visit',
418 'post_id' => $post->ID,
419 );
420
421 // Get the trigger count
422 $count_type = gamipress_get_user_log_count( $user_id, $log_meta_post_type, $now );
423
424 // Trigger daily post visit action if not triggered today
425 if( $count_type === 0 ) {
426 // Trigger post of type visit
427 do_action( 'gamipress_post_type_visit', $post->ID, $user_id, $post->post_type, $post );
428 }
429 }
430
431 $specific_count = gamipress_get_user_trigger_count( $user_id, 'gamipress_specific_post_visit', $now, 0, array( $post->ID, $user_id, $post ) );
432
433 // Trigger daily specific post visit action if not triggered today
434 if( $specific_count === 0 ) {
435 // Trigger specific post visit
436 do_action( 'gamipress_specific_post_visit', $post->ID, $user_id, $post );
437 }
438
439 }
440
441 // ---------------------------
442 // User post daily visit
443 // ---------------------------
444
445 $post_author = absint( $post->post_author );
446
447 /**
448 * Filter to set if user post visits should be tracked or not
449 *
450 * Note: User post visits event will award to the post author
451 *
452 * @since 1.5.1
453 *
454 * @param bool $track_visits Whatever if user post visits should be tracked (default true)
455 * @param int $user_id The user ID that made the visit
456 * @param int $post_author The post author ID that receive the visit
457 * @param int $post_id The post ID that has been visited
458 * @param int $post The post object that has been visited
459 *
460 * @return bool
461 */
462 $track_user_post_visits = apply_filters( 'gamipress_track_user_post_visits', true, $user_id, $post_author, $post->ID, $post );
463
464 if( $track_user_post_visits ) {
465
466 // Trigger user post visit action to the author if visitor not is the author
467 if( $post_author && $post_author !== $user_id ) {
468
469 // Trigger user post visit
470 do_action( 'gamipress_user_post_visit', $post->ID, $post_author, $user_id, $post );
471
472 // Trigger user specific post visit
473 do_action( 'gamipress_user_specific_post_visit', $post->ID, $post_author, $user_id, $post );
474
475 // Trigger user post of type visit
476 do_action( 'gamipress_user_post_type_visit', $post->ID, $post_author, $user_id, $post->post_type, $post );
477
478 }
479
480 }
481
482 }
483 add_action( 'template_redirect', 'gamipress_post_visit_listener' );
484
485 /**
486 * Listener for expend points
487 *
488 * Triggers: gamipress_expend_points
489 *
490 * @since 1.3.7
491 *
492 * @param integer $post_id The item unlocked ID (achievement or rank)
493 * @param integer $user_id The user ID
494 * @param integer $points The amount of points expended
495 * @param string $points_type The points type of the amount of points expended
496 *
497 * @return void
498 */
499 function gamipress_expend_points_listener( $post_id, $user_id, $points, $points_type ) {
500
501 // Trigger user expend points action
502 do_action( 'gamipress_expend_points', $post_id, $user_id, $points, $points_type );
503
504 }
505 add_action( 'gamipress_achievement_unlocked_with_points', 'gamipress_expend_points_listener', 10, 4 );
506 add_action( 'gamipress_rank_unlocked_with_points', 'gamipress_expend_points_listener', 10, 4 );
507
508 /**
509 * Listener for user role changes
510 *
511 * @since 1.8.8
512 *
513 * @param int $user_id The user ID.
514 * @param string $role The role.
515 */
516 function gamipress_user_role_listener( $user_id, $role ) {
517
518 $action = str_replace( '_user_role', '', current_filter() );
519
520 // Trigger add/set/remove any role
521 do_action( "gamipress_{$action}_role", $user_id, $role );
522
523 // Trigger add/set/remove specific role
524 do_action( "gamipress_{$action}_specific_role", $user_id, $role );
525
526 }
527 add_action( 'add_user_role', 'gamipress_user_role_listener', 10, 2 );
528 add_action( 'set_user_role', 'gamipress_user_role_listener', 10, 2 );
529 add_action( 'remove_user_role', 'gamipress_user_role_listener', 10, 2 );
530
531 /**
532 * Listener for user meta update
533 *
534 * @since 2.5.1
535 *
536 * @param int $meta_id ID of updated metadata entry.
537 * @param int $object_id ID of the object metadata is for.
538 * @param string $meta_key Metadata key.
539 * @param mixed $_meta_value Metadata value. Serialized if non-scalar.
540 */
541 function gamipress_user_meta_update_listener( $meta_id, $object_id, $meta_key, $_meta_value ) {
542
543 $user_id = $object_id;
544
545 // Login is required
546 if ( $user_id === 0 ) return;
547
548 $excluded_metas = array(
549 '_gamipress_triggered_triggers',
550 '_gamipress_achievements',
551 'gamipress_email_settings',
552 );
553
554 /**
555 * Exclude user metas to get triggered
556 *
557 * @since 2.5.3
558 *
559 * @param array $excluded_metas The excluded metas
560 * @param int $meta_id ID of updated metadata entry.
561 * @param int $object_id ID of the object metadata is for.
562 * @param string $meta_key Metadata key.
563 * @param mixed $_meta_value Metadata value. Serialized if non-scalar.
564 *
565 * @return array
566 */
567 $excluded_metas = apply_filters( 'gamipress_update_user_meta_trigger_excluded_metas', $excluded_metas, $meta_id, $object_id, $meta_key, $_meta_value );
568
569 // Bail if meta excluded
570 if( in_array( $meta_key, $excluded_metas ) ) {
571 return;
572 }
573
574 $meta_keys_in_use = gamipress_get_meta_keys_in_use();
575
576 // Bail if meta key not in use
577 if( ! in_array( $meta_key, $meta_keys_in_use ) ) {
578 return;
579 }
580
581 // Trigger update any value
582 do_action( "gamipress_update_user_meta_any_value", $user_id, $meta_id, $meta_key, $_meta_value, $object_id );
583
584 // Trigger update specific value
585 do_action( "gamipress_update_user_meta_specific_value", $user_id, $meta_id, $meta_key, $_meta_value, $object_id );
586
587 }
588 add_action( 'updated_user_meta', 'gamipress_user_meta_update_listener', 10, 4 );
589 add_action( 'added_user_meta', 'gamipress_user_meta_update_listener', 10, 4 );
590
591 /**
592 * Listener for post meta update
593 *
594 * @since 2.5.1
595 *
596 * @param int $meta_id ID of updated metadata entry.
597 * @param int $object_id ID of the object metadata is for.
598 * @param string $meta_key Metadata key.
599 * @param mixed $_meta_value Metadata value. Serialized if non-scalar.
600 */
601 function gamipress_post_meta_update_listener( $meta_id, $object_id, $meta_key, $_meta_value ) {
602
603 $user_id = get_current_user_id();
604
605 // Login is required
606 if ( $user_id === 0 ) return;
607
608 $excluded_metas = array();
609
610 /**
611 * Exclude post metas to get triggered
612 *
613 * @since 2.5.3
614 *
615 * @param array $excluded_metas The excluded metas
616 * @param int $meta_id ID of updated metadata entry.
617 * @param int $object_id ID of the object metadata is for.
618 * @param string $meta_key Metadata key.
619 * @param mixed $_meta_value Metadata value. Serialized if non-scalar.
620 *
621 * @return array
622 */
623 $excluded_metas = apply_filters( 'gamipress_update_post_meta_trigger_excluded_metas', $excluded_metas, $meta_id, $object_id, $meta_key, $_meta_value );
624
625 if( in_array( $meta_key, $excluded_metas ) ) {
626 return;
627 }
628
629 $meta_keys_in_use = gamipress_get_meta_keys_in_use();
630
631 // Bail if meta key not in use
632 if( ! in_array( $meta_key, $meta_keys_in_use ) ) {
633 return;
634 }
635
636 // Trigger update any value
637 do_action( "gamipress_update_post_meta_any_value", $user_id, $meta_id, $meta_key, $_meta_value, $object_id );
638
639 // Trigger update specific value
640 do_action( "gamipress_update_post_meta_specific_value", $user_id, $meta_id, $meta_key, $_meta_value, $object_id );
641
642 }
643 add_action( 'updated_post_meta', 'gamipress_post_meta_update_listener', 10, 4 );
644 add_action( 'added_post_meta', 'gamipress_post_meta_update_listener', 10, 4 );
645
646 /**
647 * Helper function to get meta keys in use
648 *
649 * @since 2.5.4
650 *
651 * @return array
652 */
653 function gamipress_get_meta_keys_in_use() {
654
655 $cache = gamipress_get_cache( 'gamipress_meta_keys_in_use', false );
656
657 // If result already cached, return it
658 if( is_array( $cache ) ) {
659 return $cache;
660 }
661
662 global $wpdb;
663
664 $postmeta = GamiPress()->db->postmeta;
665
666 // Get an array with the meta keys in use
667 $meta_keys_in_use = $wpdb->get_col(
668 "SELECT pm.meta_value AS 'meta_value'
669 FROM {$postmeta} AS pm
670 WHERE pm.meta_key = '_gamipress_meta_key_required'
671 AND pm.meta_value != ''
672 GROUP BY pm.meta_value"
673 );
674
675 if( ! is_array( $meta_keys_in_use ) ) {
676 $meta_keys_in_use = array();
677 }
678
679 // Cache listeners count
680 gamipress_save_cache( "gamipress_meta_keys_in_use", $meta_keys_in_use );
681
682 /**
683 * Filter to override meta keys in use
684 *
685 * @since 2.5.4
686 *
687 * @param array $listeners_count
688 *
689 * @return array
690 */
691 return apply_filters( 'gamipress_get_meta_keys_in_use', $meta_keys_in_use );
692
693 }