PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 8.0.3
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v8.0.3
8.0.3 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 All 45 releases
← All changes | includes/functions/ranks.php +1443 -0 7.9.28.0.3 View file →
@@ -1,0 +1,1443 @@
1 +<?php
2 +/**
3 + * Rank Functions
4 + *
5 + * @package GamiPress\Rank_Functions
6 + * @author GamiPress <contact@gamipress.com>, Ruben Garcia <rubengcdev@gmail.com>
7 + * @since 1.3.1
8 + */
9 +// Exit if accessed directly
10 +if( !defined( 'ABSPATH' ) ) exit;
11 +
12 +/**
13 + * Check if post is a registered GamiPress rank.
14 + *
15 + * @since 1.3.1
16 + *
17 + * @param object|int|string $post Post object or ID.
18 + * @return bool True if post is an rank, otherwise false.
19 + */
20 +function gamipress_is_rank( $post = null ) {
21 +
22 + $return = true;
23 +
24 + if( gettype($post) === 'string' ) {
25 + if( is_numeric($post) ) {
26 + $post_type = gamipress_get_post_type( $post );
27 + } else {
28 + $post_type = $post;
29 + }
30 + } else {
31 + $post_type = gamipress_get_post_type( $post );
32 + }
33 +
34 + // If post type is NOT a registered rank type, it cannot be an rank
35 + if ( ! in_array( $post_type, gamipress_get_rank_types_slugs() ) ) {
36 + $return = false;
37 + }
38 +
39 + // If we pass both previous tests, this is a valid rank (with filter to override)
40 + return apply_filters( 'gamipress_is_rank', $return, $post, $post_type );
41 +
42 +}
43 +
44 +/**
45 + * Return registered ranks
46 + *
47 + * @since 1.3.1
48 + *
49 + * @return array Array of ranks as WP_Post
50 + */
51 +function gamipress_get_ranks( $args = array() ) {
52 +
53 + // Setup our defaults
54 + $defaults = array(
55 + 'post_type' => array_merge( gamipress_get_rank_types_slugs(), gamipress_get_requirement_types_slugs() ),
56 + 'numberposts' => -1,
57 + 'orderby' => 'menu_order',
58 + 'suppress_filters' => false,
59 + 'rank_relationship' => 'any',
60 + );
61 +
62 + $args = wp_parse_args( $args, $defaults );
63 +
64 + // Since 1.5.1, requirements has their parent stored in the post_parent field, so it isn't required at all
65 + if ( isset( $args['parent_of'] ) ) {
66 +
67 + $post_parent = absint( gamipress_get_post_field( 'post_parent', $args['parent_of'] ) );
68 +
69 + if( $post_parent === 0 ) {
70 + return array();
71 + }
72 +
73 + $args['post__in'] = array( $post_parent );
74 +
75 + }
76 +
77 + // Since 1.5.1, requirements has their parent stored in the post_parent field, so it isn't required at all
78 + if ( isset( $args['children_of'] ) ) {
79 +
80 + $args['post_parent'] = $args['children_of'];
81 +
82 + // When looking to get rank requirements, order is important to sequential requirements
83 + $args['orderby'] = 'menu_order';
84 + $args['order'] = 'ASC';
85 +
86 + }
87 +
88 + // Get our ranks posts
89 + $ranks = get_posts( $args );
90 +
91 + return $ranks;
92 +
93 +}
94 +
95 +/**
96 + * Return user current rank id
97 + *
98 + * @since 1.3.1
99 + *
100 + * @param integer $user_id The given user's ID
101 + * @param string $rank_type The rank type
102 + *
103 + * @return integer
104 + */
105 +function gamipress_get_user_rank_id( $user_id = null, $rank_type = '' ) {
106 +
107 + global $wpdb;
108 +
109 + if( $user_id === null ) {
110 + $user_id = get_current_user_id();
111 + }
112 +
113 + $meta = '_gamipress_rank';
114 +
115 + if( ! empty( $rank_type ) ) {
116 + $meta = "_gamipress_{$rank_type}_rank";
117 + }
118 +
119 + $current_rank_id = absint( gamipress_get_user_meta( $user_id, $meta ) );
120 + $is_rank = $current_rank_id > 0 ? gamipress_is_rank( $current_rank_id ) : false;
121 +
122 + if( ! $is_rank ) {
123 +
124 + $posts = GamiPress()->db->posts;
125 +
126 + // Get lowest priority rank as default rank to all users
127 + $current_rank_id = $wpdb->get_var( $wpdb->prepare(
128 + "SELECT p.ID
129 + FROM {$posts} AS p
130 + WHERE p.post_type = %s
131 + AND p.post_status = %s
132 + ORDER BY menu_order ASC
133 + LIMIT 1",
134 + $rank_type,
135 + 'publish'
136 + ) );
137 +
138 + }
139 +
140 + return apply_filters( 'gamipress_get_user_rank_id', $current_rank_id, $user_id );
141 +
142 +}
143 +
144 +/**
145 + * Return user current rank
146 + *
147 + * @since 1.3.1
148 + *
149 + * @param integer $user_id The given user's ID
150 + * @param string $rank_type The rank type
151 + *
152 + * @return bool|WP_Post
153 + */
154 +function gamipress_get_user_rank( $user_id = null, $rank_type = '' ) {
155 +
156 + global $wpdb;
157 +
158 + if( $user_id === null ) {
159 + $user_id = get_current_user_id();
160 + }
161 +
162 + $current_rank_id = gamipress_get_user_rank_id( $user_id, $rank_type );
163 +
164 + $rank = gamipress_get_post( $current_rank_id );
165 +
166 + if( $rank ) {
167 + return apply_filters( 'gamipress_get_user_rank', $rank, $user_id, $current_rank_id );
168 + }
169 +
170 + return false;
171 +
172 +}
173 +
174 +/**
175 + * Return user next rank id
176 + *
177 + * @since 1.3.1
178 + *
179 + * @param integer $user_id The given user's ID
180 + * @param string $rank_type The rank type
181 + *
182 + * @return integer
183 + */
184 +function gamipress_get_next_user_rank_id( $user_id = null, $rank_type = '' ) {
185 +
186 + global $wpdb;
187 +
188 + if( $user_id === null ) {
189 + $user_id = get_current_user_id();
190 + }
191 +
192 + $current_rank_id = gamipress_get_user_rank_id( $user_id, $rank_type );
193 +
194 + $next_rank_id = gamipress_get_next_rank_id( $current_rank_id );
195 +
196 + return apply_filters( 'gamipress_get_next_user_rank_id', absint( $next_rank_id ), $user_id, $rank_type, $current_rank_id );
197 +
198 +}
199 +
200 +/**
201 + * Return user next rank
202 + *
203 + * @since 1.3.1
204 + *
205 + * @param integer $user_id The given user's ID
206 + * @param string $rank_type The rank type
207 + *
208 + * @return bool|WP_Post
209 + */
210 +function gamipress_get_next_user_rank( $user_id = null, $rank_type = '' ) {
211 +
212 + global $wpdb;
213 +
214 + if( $user_id === null ) {
215 + $user_id = get_current_user_id();
216 + }
217 +
218 + $current_rank_id = gamipress_get_user_rank_id( $user_id, $rank_type );
219 +
220 + $next_rank = gamipress_get_next_rank( $current_rank_id );
221 +
222 + if( $next_rank ) {
223 + return apply_filters( 'gamipress_get_next_user_rank', $next_rank, $user_id, $rank_type, $current_rank_id );
224 + }
225 +
226 + return false;
227 +
228 +}
229 +
230 +/**
231 + * Return next rank id based of given rank priority
232 + *
233 + * @since 1.3.1
234 + *
235 + * @param integer $rank_id The given rank's ID
236 + *
237 + * @return integer
238 + */
239 +function gamipress_get_next_rank_id( $rank_id = null ) {
240 +
241 + global $wpdb;
242 +
243 + if( $rank_id === null ) {
244 + $rank_id = get_the_ID();
245 + }
246 +
247 + $cache = gamipress_get_cache( 'next_rank_id', array(), false );
248 +
249 + // If result already cached, return it
250 + if( isset( $cache[$rank_id] ) ) {
251 + return $cache[$rank_id];
252 + }
253 +
254 + $rank_type = gamipress_get_post_type( $rank_id );
255 +
256 + $posts = GamiPress()->db->posts;
257 +
258 + // Get lowest priority rank but bigger than current one
259 + $next_rank_id = $wpdb->get_var( $wpdb->prepare(
260 + "SELECT p.ID
261 + FROM {$posts} AS p
262 + WHERE p.post_type = %s
263 + AND p.post_status = %s
264 + AND p.menu_order > %s
265 + ORDER BY menu_order ASC
266 + LIMIT 1",
267 + $rank_type,
268 + 'publish',
269 + gamipress_get_post_field( 'menu_order', $rank_id )
270 + ) );
271 +
272 + $next_rank_id = absint( $next_rank_id );
273 +
274 + if( $next_rank_id === $rank_id ) {
275 + $next_rank_id = 0;
276 + }
277 +
278 + $next_rank_id = apply_filters( 'gamipress_get_next_rank_id', $next_rank_id, $rank_id );
279 +
280 + // Cache function result
281 + $cache[$rank_id] = $next_rank_id;
282 +
283 + gamipress_set_cache( 'next_rank_id', $cache );
284 +
285 + return $next_rank_id;
286 +
287 +}
288 +
289 +/**
290 + * Return next rank based of given rank priority
291 + *
292 + * @since 1.3.1
293 + *
294 + * @param integer $rank_id The given rank's ID
295 + *
296 + * @return bool|WP_Post
297 + */
298 +function gamipress_get_next_rank( $rank_id = null ) {
299 +
300 + if( $rank_id === null ) {
301 + $rank_id = get_the_ID();
302 + }
303 +
304 + $next_rank_id = gamipress_get_next_rank_id( $rank_id );
305 +
306 + if( $next_rank_id === 0 ) {
307 + return false;
308 + }
309 +
310 + $rank = gamipress_get_post( $next_rank_id );
311 +
312 + if( $rank ) {
313 + return apply_filters( 'gamipress_get_next_rank', $rank, $next_rank_id, $rank_id );
314 + }
315 +
316 + return false;
317 +
318 +}
319 +
320 +/**
321 + * Return previous rank id based of given rank priority
322 + *
323 + * @since 1.3.1
324 + *
325 + * @param integer $rank_id The given rank's ID
326 + *
327 + * @return integer
328 + */
329 +function gamipress_get_prev_rank_id( $rank_id = null ) {
330 +
331 + global $wpdb;
332 +
333 + if( $rank_id === null ) {
334 + $rank_id = get_the_ID();
335 + }
336 +
337 + $cache = gamipress_get_cache( 'prev_rank_id', array(), false );
338 +
339 + // If result already cached, return it
340 + if( isset( $cache[$rank_id] ) ) {
341 + return $cache[$rank_id];
342 + }
343 +
344 + $rank_type = gamipress_get_post_type( $rank_id );
345 +
346 + $posts = GamiPress()->db->posts;
347 +
348 + // Get highest priority rank but less than current one
349 + $prev_rank_id = $wpdb->get_var( $wpdb->prepare(
350 + "SELECT p.ID
351 + FROM {$posts} AS p
352 + WHERE p.post_type = %s
353 + AND p.post_status = %s
354 + AND p.menu_order < %s
355 + ORDER BY menu_order DESC
356 + LIMIT 1",
357 + $rank_type,
358 + 'publish',
359 + gamipress_get_post_field( 'menu_order', $rank_id )
360 + ) );
361 +
362 + $prev_rank_id = absint( $prev_rank_id );
363 +
364 + if( $prev_rank_id === $rank_id ) {
365 + $prev_rank_id = 0;
366 + }
367 +
368 + $prev_rank_id = apply_filters( 'gamipress_get_prev_rank_id', $prev_rank_id, $rank_id );
369 +
370 + // Cache function result
371 + $cache[$rank_id] = $prev_rank_id;
372 +
373 + gamipress_set_cache( 'prev_rank_id', $cache );
374 +
375 + return $prev_rank_id;
376 +
377 +}
378 +
379 +/**
380 + * Return previous rank based of given rank priority
381 + *
382 + * @since 1.3.1
383 + *
384 + * @param integer $rank_id The given rank's ID
385 + *
386 + * @return bool|WP_Post
387 + */
388 +function gamipress_get_prev_rank( $rank_id = null ) {
389 +
390 + if( $rank_id === null ) {
391 + $rank_id = get_the_ID();
392 + }
393 +
394 + $prev_rank_id = gamipress_get_prev_rank_id( $rank_id );
395 +
396 + if( $prev_rank_id === 0 ) {
397 + return false;
398 + }
399 +
400 + $rank = gamipress_get_post( $prev_rank_id );
401 +
402 + if( $rank ) {
403 + return apply_filters( 'gamipress_get_prev_rank', $rank, $prev_rank_id, $rank_id );
404 + }
405 +
406 + return false;
407 +
408 +}
409 +
410 +/**
411 + * Return previous user rank
412 + *
413 + * @since 1.4.3
414 + *
415 + * @param integer $user_id The given user's ID
416 + * @param string $rank_type The given rank's type
417 + *
418 + * @return bool|int
419 + */
420 +function gamipress_get_prev_user_rank_id( $user_id = null, $rank_type = '' ) {
421 +
422 + if( $user_id === null ) {
423 + $user_id = get_current_user_id();
424 + }
425 +
426 + $old_meta = "_gamipress_{$rank_type}_previous_rank";
427 + $prev_user_rank_id = absint( gamipress_get_user_meta( $user_id, $old_meta ) );
428 +
429 + // Check if there is a previous rank stored, if not, try to get previous rank of current user rank
430 + if( $prev_user_rank_id === 0 ) {
431 +
432 + $user_rank_id = gamipress_get_user_rank_id( $user_id, $rank_type );
433 +
434 + // If there is not previous rank and not current rank, return lowest priority rank ID
435 + if( ! $user_rank_id ) {
436 + return gamipress_get_lowest_priority_rank_id( $rank_type );
437 + }
438 +
439 + $prev_user_rank_id = gamipress_get_prev_rank_id( $user_rank_id );
440 + }
441 +
442 + if( $prev_user_rank_id ) {
443 + return apply_filters( 'gamipress_get_prev_user_rank_id', $prev_user_rank_id, $user_id, $rank_type );
444 + }
445 +
446 + return false;
447 +
448 +}
449 +
450 +/**
451 + * Helper function to check if a rank is the lowest priority rank (aka the default rank to anyone)
452 + *
453 + * @since 1.3.6
454 + *
455 + * @param integer $rank_id The given rank's ID
456 + *
457 + * @return bool
458 + */
459 +function gamipress_is_lowest_priority_rank( $rank_id = null ) {
460 +
461 + if( $rank_id === null ) {
462 + $rank_id = get_the_ID();
463 + }
464 +
465 + $prev_rank_id = gamipress_get_prev_rank_id( $rank_id );
466 +
467 + // Return true if previous rank is 0 or the same that given one
468 + return (bool) ( $rank_id === $prev_rank_id || $prev_rank_id === 0 );
469 +
470 +}
471 +
472 +/**
473 + * Get the lowest priority rank ID of a rank type
474 + *
475 + * @since 1.4.3
476 + *
477 + * @param string $rank_type The given rank's type
478 + *
479 + * @return int
480 + */
481 +function gamipress_get_lowest_priority_rank_id( $rank_type = null ) {
482 +
483 + global $wpdb;
484 +
485 + $posts = GamiPress()->db->posts;
486 +
487 + // Get the lowest priority rank
488 + $rank_id = $wpdb->get_var( $wpdb->prepare(
489 + "SELECT p.ID
490 + FROM {$posts} AS p
491 + WHERE p.post_type = %s
492 + AND p.post_status = %s
493 + ORDER BY menu_order ASC
494 + LIMIT 1",
495 + $rank_type,
496 + 'publish'
497 + ) );
498 +
499 + // Return true if previous rank is 0 or the same that given one
500 + return apply_filters( 'gamipress_get_lowest_priority_rank_id', absint( $rank_id ), $rank_type );
501 +
502 +}
503 +
504 +/**
505 + * Award rank to a user
506 + *
507 + * @since 1.4.3
508 + *
509 + * @param integer $rank_id The rank is being awarded
510 + * @param integer $user_id The given user's ID
511 + * @param array $args Array of extra arguments
512 + *
513 + * @return bool|WP_Post WP Post object of newly rank awarded, false if process fails
514 + */
515 +function gamipress_award_rank_to_user( $rank_id = 0, $user_id = 0, $args = array() ) {
516 +
517 + // Bail if not is a valid rank
518 + if( ! gamipress_is_rank( $rank_id ) ) {
519 + return false;
520 + }
521 +
522 + // Initialize args
523 + $args = wp_parse_args( $args, array(
524 + 'admin_id' => 0,
525 + 'achievement_id' => null,
526 + ) );
527 +
528 + // Available action for triggering other processes
529 + do_action( 'gamipress_award_rank_to_user', $user_id, $rank_id, $args );
530 +
531 + return gamipress_update_user_rank( $user_id, $rank_id, $args['admin_id'], $args['achievement_id'] );
532 +
533 +}
534 +
535 +/**
536 + * Revoke rank to a user
537 + *
538 + * @since 1.4.3
539 + *
540 + * @param integer $user_id The given user's ID
541 + * @param integer $rank_id The rank is being revoked
542 + * @param integer $new_rank_id The new user rank, if not provided user will get the previous rank
543 + * @param array $args Array of extra arguments
544 + *
545 + * @return bool|WP_Post WP Post object of newly rank revoked, false if process fails
546 + */
547 +function gamipress_revoke_rank_to_user( $user_id = 0, $rank_id = 0, $new_rank_id = 0, $args = array() ) {
548 +
549 + // Bail if not is a valid rank
550 + if( ! gamipress_is_rank( $rank_id ) ) {
551 + return false;
552 + }
553 +
554 + // Initialize args
555 + $args = wp_parse_args( $args, array(
556 + 'admin_id' => 0,
557 + 'achievement_id' => null,
558 + ) );
559 +
560 + // If not new rank provided, then get the previous user rank
561 + if( $new_rank_id === 0 ) {
562 + $rank_type = gamipress_get_post_type( $rank_id );
563 +
564 + $new_rank_id = gamipress_get_prev_user_rank_id( $user_id, $rank_type );
565 + }
566 +
567 + // Available action for triggering other processes
568 + do_action( 'gamipress_revoke_rank_to_user', $user_id, $rank_id, $new_rank_id, $args );
569 +
570 + // Removes the rank from the user earnings table
571 + gamipress_revoke_achievement_to_user( $rank_id, $user_id );
572 +
573 + // Set the new rank to the user
574 + return gamipress_update_user_rank( $user_id, $new_rank_id, $args['admin_id'], $args['achievement_id'] );
575 +
576 +}
577 +
578 +/**
579 + * Upgrade the given user to the next rank of a rank type
580 + *
581 + * @since 1.4.3
582 + *
583 + * @param int $user_id The given user's ID
584 + * @param string $rank_type The given rank's type
585 + *
586 + * @return bool|WP_Post WP Post object of newly rank upgraded, false if process fails
587 + */
588 +function gamipress_upgrade_user_to_next_rank( $user_id = 0, $rank_type = '' ) {
589 +
590 + // Bail if not is a valid rank type
591 + if( ! gamipress_is_rank( $rank_type ) ) {
592 + return false;
593 + }
594 +
595 + $user_rank_id = gamipress_get_user_rank_id( $user_id, $rank_type );
596 + $next_rank_id = gamipress_get_next_rank_id( $user_rank_id );
597 +
598 + // User is already on higher rank, so bail here
599 + if( $next_rank_id === $user_rank_id ) {
600 + return false;
601 + }
602 +
603 + // Award the next rank to the user
604 + return gamipress_award_rank_to_user( $next_rank_id, $user_id );
605 +
606 +}
607 +
608 +/**
609 + * Downgrade the given user to the previous rank of a rank type
610 + *
611 + * @since 1.4.3
612 + *
613 + * @param int $user_id The given user's ID
614 + * @param string $rank_type The given rank's type
615 + *
616 + * @return bool|WP_Post WP Post object of newly rank downgraded, false if process fails
617 + */
618 +function gamipress_downgrade_user_to_prev_rank( $user_id = 0, $rank_type = '' ) {
619 +
620 + // Bail if not is a valid rank type
621 + if( ! gamipress_is_rank( $rank_type ) ) {
622 + return false;
623 + }
624 +
625 + $user_rank_id = gamipress_get_user_rank_id( $user_id, $rank_type );
626 + $prev_rank_id = gamipress_get_prev_rank_id( $user_rank_id );
627 +
628 + // User is already on lowest rank, so bail here
629 + if( $prev_rank_id === $user_rank_id ) {
630 + return false;
631 + }
632 +
633 + // Award the previous rank to the user
634 + return gamipress_revoke_rank_to_user( $user_id, $user_rank_id, $prev_rank_id );
635 +
636 +}
637 +
638 +/**
639 + * Update user rank to the given one
640 + *
641 + * @since 1.3.1
642 + *
643 + * @param integer $user_id The given user's ID
644 + * @param integer $rank_id The new rank the user is being awarded
645 + * @param integer $admin_id If being awarded by an admin, the admin's user ID
646 + * @param integer $achievement_id The achievement that generated the rank upgrade, if applicable
647 + *
648 + * @return bool|WP_Post
649 + */
650 +function gamipress_update_user_rank( $user_id = 0, $rank_id = 0, $admin_id = 0, $achievement_id = null ) {
651 +
652 + if( ! $rank_id )
653 + return false;
654 +
655 + if( ! $user_id )
656 + $user_id = get_current_user_id();
657 +
658 + $new_rank = gamipress_get_post( $rank_id );
659 +
660 + // Get user old rank if has one
661 + $old_rank = gamipress_get_user_rank( $user_id, $new_rank->post_type );
662 +
663 + // If is the same rank, return
664 + if( $old_rank && $new_rank && $new_rank->ID === $old_rank->ID )
665 + return $new_rank;
666 +
667 + // Check if is a valid rank and is not the same rank as current one
668 + if( $new_rank && gamipress_is_rank( $new_rank ) ) {
669 +
670 + $meta = "_gamipress_{$new_rank->post_type}_rank";
671 +
672 + // Update the user rank and the time when this rank has been earned
673 + gamipress_update_user_meta( $user_id, $meta, $new_rank->ID );
674 + gamipress_update_user_meta( $user_id, $meta . '_earned_time', current_time( 'timestamp' ) );
675 +
676 + if( $old_rank ) {
677 +
678 + // Stores the user old rank to meet it for revokes
679 + $old_meta = "_gamipress_{$new_rank->post_type}_previous_rank";
680 + gamipress_update_user_meta( $user_id, $old_meta, $old_rank->ID );
681 +
682 + }
683 +
684 + // Available action for triggering other processes
685 + do_action( 'gamipress_update_user_rank', $user_id, $new_rank, $old_rank, $admin_id, $achievement_id );
686 +
687 + // Maybe award some points-based achievements
688 + foreach ( gamipress_get_rank_based_achievements() as $achievement ) {
689 + gamipress_maybe_award_achievement_to_user( $achievement->ID, $user_id );
690 + }
691 +
692 + return $new_rank;
693 + }
694 +
695 + return false;
696 +
697 +}
698 +
699 +/**
700 + * Register a user's updated rank as user earning
701 + *
702 + * @since 1.3.1
703 + *
704 + * @param integer $user_id The user ID
705 + * @param WP_Post $new_rank New rank post object
706 + * @param WP_Post $old_rank Old rank post object
707 + * @param integer $admin_id An admin ID (if admin-awarded)
708 + * @param integer $achievement_id Achievement that has been triggered it
709 + */
710 +function gamipress_register_user_rank_earning( $user_id, $new_rank, $old_rank, $admin_id = 0, $achievement_id = null ) {
711 +
712 + // Setup our achievement object
713 + $achievement_object = gamipress_build_achievement_object( $new_rank->ID );
714 +
715 + // Update user's earned achievements
716 + gamipress_update_user_achievements( array( 'user_id' => $user_id, 'new_achievements' => array( $achievement_object ) ) );
717 +
718 +}
719 +add_action( 'gamipress_update_user_rank', 'gamipress_register_user_rank_earning', 10, 5 );
720 +
721 +/**
722 + * Log a user's updated rank
723 + *
724 + * @since 1.3.1
725 + *
726 + * @param integer $user_id The user ID
727 + * @param WP_Post $new_rank New rank post object
728 + * @param WP_Post $old_rank Old rank post object
729 + * @param integer $admin_id An admin ID (if admin-awarded)
730 + * @param integer $achievement_id Achievement that has been triggered it
731 + */
732 +function gamipress_log_user_rank( $user_id, $new_rank, $old_rank, $admin_id = 0, $achievement_id = null ) {
733 +
734 + $log_meta = array(
735 + 'rank_id' => ( $new_rank ? $new_rank->ID : 0 ),
736 + 'old_rank_id' => ( $old_rank ? $old_rank->ID : 0 ),
737 + );
738 +
739 + $access = 'public';
740 + $trigger = '';
741 +
742 + // Alter our log pattern if this was an admin action
743 + if ( $admin_id ) {
744 + $type = 'rank_award';
745 + $access = 'private';
746 +
747 + $log_meta['pattern'] = apply_filters( 'gamipress_rank_awarded_log_pattern', __( '{admin} ranked {user} to {rank_type} {rank}', 'gamipress' ) );
748 + $log_meta['admin_id'] = $admin_id;
749 + $trigger = 'gamipress_award_rank';
750 + } else {
751 + $type = 'rank_earn';
752 + $log_meta['pattern'] = apply_filters( 'gamipress_rank_earned_log_pattern', __( '{user} ranked to {rank_type} {rank}', 'gamipress' ) );
753 +
754 + if( $achievement_id ) {
755 + $log_meta['achievement_id'] = $achievement_id;
756 + $trigger = gamipress_get_post_meta( $achievement_id, '_gamipress_trigger_type' );
757 + }
758 +
759 + if( empty( $trigger ) ) {
760 + $trigger = 'gamipress_unlock_rank';
761 + }
762 + }
763 +
764 + // Create the log entry
765 + gamipress_insert_log( $type, $user_id, $access, $trigger, $log_meta );
766 +
767 +}
768 +add_action( 'gamipress_update_user_rank', 'gamipress_log_user_rank', 10, 5 );
769 +
770 +/**
771 + * Get rank requirement's rank
772 + *
773 + * @since 1.3.1
774 + *
775 + * @param integer $rank_requirement_id The given rank requirement's post ID
776 + *
777 + * @return object|bool The post object of the rank, or false if none
778 + */
779 +function gamipress_get_rank_requirement_rank( $rank_requirement_id = 0 ) {
780 +
781 + // Grab the current post ID if no rank requirement ID was specified
782 + if ( ! $rank_requirement_id ) {
783 + global $post;
784 + $rank_requirement_id = $post->ID;
785 + }
786 +
787 + // The rank requirement's rank is the post parent
788 + $rank_id = absint( gamipress_get_post_field( 'post_parent', $rank_requirement_id ) );
789 +
790 + // If has parent, return his post object
791 + if( $rank_id !== 0 )
792 + return gamipress_get_post( $rank_id );
793 + else
794 + return false;
795 +}
796 +
797 +/**
798 + * Get Rank Earned Time
799 + *
800 + * @since 1.3.1
801 + *
802 + * @param integer $user_id The given rank requirement's post ID
803 + * @param string $rank_type The given rank requirement's post ID
804 + *
805 + * @return integer Timestamp of user has earned the last rank of this type, if not, fall back to the rank created date
806 + */
807 +function gamipress_get_rank_earned_time( $user_id = 0, $rank_type = '' ) {
808 +
809 + $earned_time = absint( gamipress_get_user_meta( $user_id, "_gamipress_{$rank_type}_rank_earned_time" ) );
810 +
811 + // If user has not earned a rank of this type, try to get the lowest priority rank and get its publish date
812 + if( $earned_time === 0 ) {
813 + $rank = gamipress_get_user_rank( $user_id, $rank_type );
814 +
815 + if( $rank )
816 + $earned_time = strtotime( $rank->post_date );
817 + }
818 +
819 + return $earned_time;
820 +
821 +}
822 +
823 +/**
824 + * Get rank requirements
825 + *
826 + * @since 1.3.1
827 + * @updated 1.5.1 Added $post_status parameter
828 + *
829 + * @param integer $rank_id The given rank requirement's post ID
830 + * @param string $post_status The rank requirements status (publish by default)
831 + *
832 + * @return array An array of post objects with the rank requirements
833 + */
834 +function gamipress_get_rank_requirements( $rank_id = 0, $post_status = 'publish' ) {
835 +
836 + // Grab the current post ID if no rank_id was specified
837 + if ( ! $rank_id ) {
838 + global $post;
839 + $rank_id = $post->ID;
840 + }
841 +
842 + $cache = gamipress_get_cache( 'rank_requirements', array(), false );
843 +
844 + // If result already cached, return it
845 + if( isset( $cache[$rank_id] ) && isset( $cache[$rank_id][$post_status] ) ) {
846 + return $cache[$rank_id][$post_status];
847 + }
848 +
849 + $requirements = get_posts( array(
850 + 'post_type' => 'rank-requirement',
851 + 'post_parent' => $rank_id,
852 + 'post_status' => $post_status,
853 + 'orderby' => 'menu_order',
854 + 'order' => 'ASC',
855 + 'posts_per_page' => -1,
856 + 'suppress_filters' => false,
857 + ) );
858 +
859 + // Cache function result
860 + if( ! isset( $cache[$rank_id] ) ){
861 + $cache[$rank_id] = array();
862 + }
863 +
864 + $cache[$rank_id][$post_status] = $requirements;
865 +
866 + gamipress_set_cache( 'rank_requirements', $cache );
867 +
868 + // Return rank requirements array
869 + return $requirements;
870 +
871 +}
872 +
873 +/**
874 + * Helper function to retrieve an rank post thumbnail
875 + *
876 + * @since 1.3.1
877 + *
878 + * @param integer $post_id The rank's post ID
879 + * @param string|array $image_size Image size to use. Accepts any valid image size, or
880 + * an array of width and height values in pixels (in that order).
881 + * Default 'gamipress-rank'.
882 + * @param string $class A custom class to use for the image tag
883 + *
884 + * @return string Our formatted image tag
885 + */
886 +function gamipress_get_rank_post_thumbnail( $post_id = 0, $image_size = 'gamipress-rank', $class = 'gamipress-rank-thumbnail' ) {
887 +
888 + // Get our rank thumbnail
889 + $image = gamipress_get_the_post_thumbnail( $post_id, $image_size, array( 'class' => $class ) );
890 +
891 + // If we don't have an image...
892 + if ( ! $image ) {
893 +
894 + // Grab our rank type's post thumbnail
895 + $rank = get_page_by_path( gamipress_get_post_type( $post_id ), OBJECT, 'rank-type' );
896 + $image = is_object( $rank ) ? gamipress_get_the_post_thumbnail( $rank->ID, $image_size, array( 'class' => $class ) ) : false;
897 +
898 + // If we still have no image
899 + if ( ! $image ) {
900 +
901 + // If we already have an array for image size
902 + if ( is_array( $image_size ) ) {
903 + // Write our sizes to an associative array
904 + $image_sizes['width'] = $image_size[0];
905 + $image_sizes['height'] = $image_size[1];
906 +
907 + // Otherwise, attempt to grab the width/height from our specified image size
908 + } else {
909 + global $_wp_additional_image_sizes;
910 + if ( isset( $_wp_additional_image_sizes[$image_size] ) )
911 + $image_sizes = $_wp_additional_image_sizes[$image_size];
912 + }
913 +
914 + // If we can't get the defined width/height, set our own
915 + if ( empty( $image_sizes ) ) {
916 + $image_sizes = array(
917 + 'width' => 100,
918 + 'height' => 100
919 + );
920 + }
921 +
922 + // Available filter: 'gamipress_default_rank_post_thumbnail'
923 + $default_thumbnail = apply_filters( 'gamipress_default_rank_post_thumbnail', '', $rank, $image_sizes );
924 +
925 + if( ! empty( $default_thumbnail ) ) {
926 + $image = '<img src="' . $default_thumbnail . '" width="' . $image_sizes['width'] . '" height="' . $image_sizes['height'] . '" class="' . $class . '">';
927 + }
928 +
929 + }
930 + }
931 +
932 + // Return our image tag
933 + return $image;
934 +}
935 +
936 +/**
937 + * Get an array of all users who have currently on a given rank
938 + *
939 + * @since 1.3.1
940 + * @updated 1.6.7 Added $args parameter
941 + * @updated 1.6.9 Make earner list work on default ranks
942 + *
943 + * @param int $rank_id The given rank's post ID
944 + * @param array $args Array of arguments that modifies the earners list result
945 + *
946 + * @return array Array of user objects
947 + */
948 +function gamipress_get_rank_earners( $rank_id = 0, $args = array() ) {
949 +
950 + global $wpdb;
951 +
952 + // Setup the meta_key
953 + $rank_type = gamipress_get_post_type( $rank_id );
954 +
955 + $meta = '_gamipress_rank';
956 +
957 + if( ! empty( $rank_type ) ) {
958 + $meta = "_gamipress_{$rank_type}_rank";
959 + }
960 +
961 + if ( is_multisite() && ! gamipress_is_network_wide_active() ) {
962 + $meta = $wpdb->get_blog_prefix() . $meta;
963 + }
964 +
965 + // Setup vars
966 + $from = "{$wpdb->usermeta} AS u RIGHT JOIN {$wpdb->users} AS usr ON (usr.ID = u.user_id)";
967 + $where = "u.meta_key = '{$meta}' AND u.meta_value = '{$rank_id}' ";
968 +
969 + // On multisite, get earners only of the current site
970 + if( is_multisite() && ! gamipress_is_network_wide_active() ) {
971 + $from .= "RIGHT JOIN {$wpdb->usermeta} AS umcap ON (
972 + umcap.user_id = u.user_id
973 + AND umcap.meta_key = '" . $wpdb->get_blog_prefix( gamipress_get_original_site_id() ) . "capabilities'
974 + ) ";
975 + }
976 +
977 +
978 + // If is lowest priority rank then requires an extra check to get users that doesn't have the rank meta
979 + if( gamipress_is_lowest_priority_rank( $rank_id ) ) {
980 +
981 + $where .= "OR NOT EXISTS (
982 + SELECT meta.*
983 + FROM {$wpdb->usermeta} as meta
984 + WHERE meta.meta_key = '{$meta}'
985 + AND meta.user_id = u.user_id
986 + ) ";
987 +
988 + }
989 +
990 + $group_by = "u.user_id";
991 + $order_by = '';
992 + $limit = '';
993 +
994 + // Setup default args
995 + $defaults = array(
996 + 'limit' => -1,
997 + 'orderby' => 'u.user_id',
998 + 'order' => 'DESC',
999 + );
1000 +
1001 + /**
1002 + * Filters the earners args
1003 + *
1004 + * @since 1.6.7
1005 + *
1006 + * @param array $args Array of given arguments
1007 + * @param int $rank_id The given rank's post ID
1008 + *
1009 + * @return array
1010 + */
1011 + $args = apply_filters( 'gamipress_get_rank_earners_args', $args, $rank_id );
1012 +
1013 + $args = wp_parse_args( $args, $defaults );
1014 +
1015 + // Sanitization
1016 + $args['limit'] = absint( $args['limit'] );
1017 + $args['order'] = gamipress_validate_from_array( strtoupper( $args['order'] ), array( 'ASC', 'DESC' ), 'DESC' );
1018 +
1019 + // Setup FROM
1020 + if( ! empty( $args['from'] ) )
1021 + $from .= $args['from'];
1022 +
1023 + // Setup WHERE
1024 + if( ! empty( $args['where'] ) )
1025 + $where .= $args['where'];
1026 +
1027 + // Setup LIMIT
1028 + if( $args['limit'] > 0 )
1029 + $limit = '0, ' . $args['limit'];
1030 +
1031 + // Setup ORDER BY
1032 + if( ! empty( $args['orderby'] ) )
1033 + $order_by = $args['orderby'] . ' ' . $args['order'];
1034 +
1035 + $earners = $wpdb->get_col(
1036 + "SELECT u.user_id
1037 + FROM {$from}
1038 + WHERE {$where}
1039 + GROUP BY {$group_by} "
1040 + . ( ! empty( $order_by ) ? "ORDER BY {$order_by} " : '' )
1041 + . ( ! empty( $limit ) ? "LIMIT {$limit} " : '' )
1042 + );
1043 +
1044 + // Build an array of wp users based of IDs found
1045 + $earned_users = array();
1046 +
1047 + foreach( $earners as $earner_id ) {
1048 +
1049 + if( absint( $earner_id ) === 0 ) {
1050 + continue;
1051 + }
1052 +
1053 + $earned_users[] = new WP_User( $earner_id );
1054 + }
1055 +
1056 + return $earned_users;
1057 +
1058 +}
1059 +
1060 +/**
1061 + * Build an unordered list of users who have earned a given rank
1062 + *
1063 + * @since 1.3.1
1064 + * @updated 1.6.7 Added $args parameter
1065 + *
1066 + * @param int $rank_id The given rank's post ID
1067 + * @param array $args Array of arguments that modifies the earners list result
1068 + *
1069 + * @return string Concatenated markup
1070 + */
1071 +function gamipress_get_rank_earners_list( $rank_id = 0, $args = array() ) {
1072 +
1073 + /**
1074 + * Filters the earners list args
1075 + *
1076 + * @since 1.6.7
1077 + *
1078 + * @param array $args Array of given arguments
1079 + * @param int $rank_id The given rank's post ID
1080 + *
1081 + * @return array
1082 + */
1083 + $args = apply_filters( 'gamipress_get_rank_earners_list_args', $args, $rank_id );
1084 +
1085 + // Grab our users
1086 + $earners = gamipress_get_rank_earners( $rank_id, $args );
1087 + $output = '';
1088 +
1089 + // Only generate output if we have earners
1090 + if ( ! empty( $earners ) ) {
1091 +
1092 + /**
1093 + * Filters the rank earners heading text
1094 + *
1095 + * @since 1.8.6
1096 + *
1097 + * @param string $heading_text The heading text
1098 + * @param int $rank_id The given rank's post ID
1099 + * @param array $args Array of given arguments
1100 + *
1101 + * @return string
1102 + */
1103 + $heading_text = apply_filters( 'gamipress_rank_earners_heading', __( 'People who have reached this:', 'gamipress' ), $rank_id, $args );
1104 +
1105 + // Loop through each user and build our output
1106 + $output .= '<h4>' . $heading_text . '</h4>';
1107 +
1108 + $output .= '<ul class="gamipress-rank-earners-list rank-' . $rank_id . '-earners-list">';
1109 +
1110 + foreach ( $earners as $user ) {
1111 +
1112 + $user_url = get_author_posts_url( $user->ID );
1113 +
1114 + /**
1115 + * Filters the rank earner url
1116 + *
1117 + * @since 1.8.6
1118 + *
1119 + * @param string $user_url The user URl, by default the get_author_posts_url()
1120 + * @param int $user_id The rendered user ID
1121 + * @param int $rank_id The given rank's post ID
1122 + * @param array $args Array of given arguments
1123 + *
1124 + * @return string
1125 + */
1126 + $user_url = apply_filters( 'gamipress_rank_earner_user_url', $user_url, $user->ID, $rank_id, $args );
1127 +
1128 + /**
1129 + * Filters the rank earner display
1130 + *
1131 + * @since 1.8.6
1132 + *
1133 + * @param string $user_display The user display, by default the user display name
1134 + * @param int $user_id The rendered user ID
1135 + * @param int $rank_id The given rank's post ID
1136 + * @param array $args Array of given arguments
1137 + *
1138 + * @return string
1139 + */
1140 + $user_display = apply_filters( 'gamipress_rank_earner_user_display', $user->display_name, $user->ID, $rank_id, $args );
1141 +
1142 + $user_content = '<li>'
1143 + . '<a href="' . $user_url . '">'
1144 + . get_avatar( $user->ID )
1145 + . '<span class="earner-display-name">' . $user_display . '</span>'
1146 + . '</a>'
1147 + . '</li>';
1148 +
1149 + /**
1150 + * Filters the earners list user output
1151 + *
1152 + * @since 1.0.0
1153 + * @updated 1.6.7 Added $rank_id and $args arguments
1154 + *
1155 + * @param string $user_content User output
1156 + * @param int $user_id The rendered user ID
1157 + * @param int $rank_id The given rank's post ID
1158 + * @param array $args Array of given arguments
1159 + *
1160 + * @return string
1161 + */
1162 + $output .= apply_filters( 'gamipress_get_rank_earners_list_user', $user_content, $user->ID, $rank_id, $args );
1163 + }
1164 +
1165 + $output .= '</ul>';
1166 +
1167 + }
1168 +
1169 + /**
1170 + * Filters the rank earners list output
1171 + *
1172 + * @since 1.0.0
1173 + *
1174 + * @param string $output Achievement earners list output
1175 + * @param int $rank_id The given rank's post ID
1176 + * @param array $args Array of given arguments
1177 + * @param array $earners Array of rank earners
1178 + *
1179 + * @return string
1180 + */
1181 + return apply_filters( 'gamipress_get_rank_earners_list', $output, $rank_id, $args, $earners );
1182 +}
1183 +
1184 +/**
1185 + * Return the given rank's priority
1186 + *
1187 + * @since 1.3.7
1188 + *
1189 + * @param integer|WP_Post $rank_id The given rank's post ID or rank's post object
1190 + *
1191 + * @return integer The given rank's priority
1192 + */
1193 +function gamipress_get_rank_priority( $rank_id = 0 ) {
1194 +
1195 + global $wpdb;
1196 +
1197 + if( gamipress_get_post_field( 'post_status', $rank_id ) === 'auto-draft' ) {
1198 +
1199 + $rank_type = gamipress_get_post_type( $rank_id );
1200 +
1201 + $posts = GamiPress()->db->posts;
1202 +
1203 + // Get higher menu order
1204 + $last = $wpdb->get_var( $wpdb->prepare(
1205 + "SELECT p.menu_order
1206 + FROM {$posts} AS p
1207 + WHERE p.post_type = %s
1208 + AND p.post_status = %s
1209 + ORDER BY menu_order DESC
1210 + LIMIT 1",
1211 + $rank_type,
1212 + 'publish'
1213 + ) );
1214 +
1215 + return absint( $last ) + 1;
1216 + }
1217 +
1218 + return absint( gamipress_get_post_field( 'menu_order', $rank_id ) );
1219 +
1220 +}
1221 +
1222 +/**
1223 + * Flush rewrite rules whenever an rank type is published.
1224 + *
1225 + * @since 1.3.1
1226 + *
1227 + * @param string $new_status New status.
1228 + * @param string $old_status Old status.
1229 + * @param object $post Post object.
1230 + */
1231 +function gamipress_flush_rewrite_on_published_rank( $new_status, $old_status, $post ) {
1232 + if ( 'rank-type' === $post->post_type && 'publish' === $new_status && 'publish' !== $old_status ) {
1233 + gamipress_flush_rewrite_rules();
1234 + }
1235 +}
1236 +add_action( 'transition_post_status', 'gamipress_flush_rewrite_on_published_rank', 10, 3 );
1237 +
1238 +/**
1239 + * Update all dependent data if rank type name has changed.
1240 + *
1241 + * @since 1.3.1
1242 + *
1243 + * @param array $data Post data.
1244 + * @param array $post_args Post args.
1245 + * @return array Updated post data.
1246 + */
1247 +function gamipress_maybe_update_rank_type( $data = array(), $post_args = array() ) {
1248 +
1249 + // Bail if not is main site, on network wide installs ranks are just available on main site
1250 + if( gamipress_is_network_wide_active() && ! is_main_site() ) {
1251 + return $data;
1252 + }
1253 +
1254 + // Bail if not is a points type
1255 + if( $post_args['post_type'] !== 'rank-type') {
1256 + return $data;
1257 + }
1258 +
1259 + // If user set an empty slug, then generate it
1260 + if( empty( $post_args['post_name'] ) ) {
1261 + $post_args['post_name'] = wp_unique_post_slug(
1262 + sanitize_title( $post_args['post_title'] ),
1263 + $post_args['ID'],
1264 + $post_args['post_status'],
1265 + $post_args['post_type'],
1266 + $post_args['post_parent']
1267 + );
1268 + }
1269 +
1270 + // Sanitize post_name
1271 + $post_args['post_name'] = gamipress_sanitize_slug( $post_args['post_name'] );
1272 +
1273 + if ( gamipress_rank_type_changed( $post_args ) ) {
1274 +
1275 + $original_type = gamipress_get_post( $post_args['ID'] )->post_name;
1276 + $new_type = $post_args['post_name'];
1277 +
1278 + $data['post_name'] = gamipress_update_rank_types( $original_type, $new_type );
1279 +
1280 + add_filter( 'redirect_post_location', 'gamipress_rank_type_rename_redirect', 99 );
1281 +
1282 + }
1283 +
1284 + return $data;
1285 +}
1286 +add_filter( 'wp_insert_post_data' , 'gamipress_maybe_update_rank_type' , 99, 2 );
1287 +
1288 +/**
1289 + * Check if an rank type name has changed.
1290 + *
1291 + * @since 1.3.1
1292 + *
1293 + * @param array $post_args Post args.
1294 + * @return bool True if name has changed, otherwise false.
1295 + */
1296 +function gamipress_rank_type_changed( $post_args = array() ) {
1297 +
1298 + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
1299 + return false;
1300 + }
1301 +
1302 + $original_post = ( !empty( $post_args['ID'] ) && isset( $post_args['ID'] ) ) ? get_post( $post_args['ID'] ) : null;
1303 + $status = false;
1304 +
1305 + if ( is_object( $original_post ) ) {
1306 + if (
1307 + 'rank-type' === $post_args['post_type']
1308 + && $original_post->post_status !== 'auto-draft'
1309 + && ! empty( $original_post->post_name )
1310 + && $original_post->post_name !== $post_args['post_name']
1311 + ) {
1312 + $status = true;
1313 + }
1314 + }
1315 +
1316 + return $status;
1317 +}
1318 +
1319 +/**
1320 + * Replace all instances of one rank type with another.
1321 + *
1322 + * @since 1.3.1
1323 + *
1324 + * @param string $original_type Original rank type.
1325 + * @param string $new_type New rank type.
1326 + * @return string New rank type.
1327 + */
1328 +function gamipress_update_rank_types( $original_type = '', $new_type = '' ) {
1329 +
1330 + // Sanity check to prevent alterating core posts
1331 + if ( empty( $original_type ) || in_array( $original_type, array( 'post', 'page', 'attachment', 'revision', 'nav_menu_item' ) ) ) {
1332 + return $new_type;
1333 + }
1334 +
1335 + gamipress_update_ranks_rank_types( $original_type, $new_type );
1336 + gamipress_update_earned_meta_rank_types( $original_type, $new_type );
1337 +
1338 + /**
1339 + * Action triggered when a rank type gets updated (called before flush rewrite rules)
1340 + *
1341 + * @since 1.5.1
1342 + *
1343 + * @param string $original_type The original type slug.
1344 + * @param string $new_type The new type slug.
1345 + */
1346 + do_action( 'gamipress_update_rank_type', $original_type, $new_type );
1347 +
1348 + gamipress_flush_rewrite_rules();
1349 +
1350 + return $new_type;
1351 +
1352 +}
1353 +
1354 +/**
1355 + * Change all ranks of one type to a new type.
1356 + *
1357 + * @since 1.3.1
1358 + *
1359 + * @param string $original_type Original rank type.
1360 + * @param string $new_type New rank type.
1361 + */
1362 +function gamipress_update_ranks_rank_types( $original_type = '', $new_type = '' ) {
1363 +
1364 + $items = get_posts( array(
1365 + 'posts_per_page' => -1,
1366 + 'post_status' => 'any',
1367 + 'post_type' => $original_type,
1368 + 'fields' => 'id',
1369 + 'suppress_filters' => false,
1370 + ) );
1371 +
1372 + foreach ( $items as $item ) {
1373 + set_post_type( $item->ID, $new_type );
1374 + }
1375 +
1376 +}
1377 +
1378 +/**
1379 + * Change all earned meta from one rank type to another.
1380 + *
1381 + * @since 1.3.1
1382 + *
1383 + * @param string $original_type Original rank type.
1384 + * @param string $new_type New rank type.
1385 + */
1386 +function gamipress_update_earned_meta_rank_types( $original_type = '', $new_type = '' ) {
1387 +
1388 + // Setup CT object
1389 + $ct_table = ct_setup_table( 'gamipress_user_earnings' );
1390 +
1391 + $ct_table->db->update(
1392 + array( 'post_type' => $new_type ),
1393 + array( 'post_type' => $original_type )
1394 + );
1395 +
1396 + ct_reset_setup_table();
1397 +
1398 + global $wpdb;
1399 +
1400 + $wpdb->get_results( $wpdb->prepare(
1401 + "UPDATE {$wpdb->usermeta}
1402 + SET meta_key = %s
1403 + WHERE meta_key = %s",
1404 + "_gamipress_{$new_type}_rank",
1405 + "_gamipress_{$original_type}_rank"
1406 + ) );
1407 +
1408 +}
1409 +
1410 +/**
1411 + * Redirect to include custom rename message.
1412 + *
1413 + * @since 1.3.1
1414 + *
1415 + * @param string $location Original URI.
1416 + * @return string Updated URI.
1417 + */
1418 +function gamipress_rank_type_rename_redirect( $location = '' ) {
1419 +
1420 + remove_filter( 'redirect_post_location', __FUNCTION__, 99 );
1421 +
1422 + return add_query_arg( 'message', 99, $location );
1423 +
1424 +}
1425 +
1426 +/**
1427 + * Filter the "post updated" messages to include support for rank types.
1428 + *
1429 + * @since 1.3.1
1430 + *
1431 + * @param array $messages Array of messages to display.
1432 + *
1433 + * @return array $messages Compiled list of messages.
1434 + */
1435 +function gamipress_rank_type_update_messages( $messages ) {
1436 +
1437 + $messages['rank-type'] = array_fill( 1, 10, __( 'Rank Type saved successfully.', 'gamipress' ) );
1438 + $messages['rank-type']['99'] = sprintf( __('Rank Type renamed successfully. <p>All ranks of this type, and all active and earned user ranks, have been updated <strong>automatically</strong>.</p> All shortcodes, %s, and URIs that reference the old rank type slug must be updated <strong>manually</strong>.', 'gamipress'), '<a href="' . esc_url( admin_url( 'widgets.php' ) ) . '">' . __( 'widgets', 'gamipress' ) . '</a>' );
1439 +
1440 + return $messages;
1441 +
1442 +}
1443 +add_filter( 'post_updated_messages', 'gamipress_rank_type_update_messages' );