PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 8.0.2
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v8.0.2
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 / admin / users.php

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

941 lines 39.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin Users
4 *
5 * @package GamiPress\Admin\Users
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 * Display achievements for a user on their profile screen
14 *
15 * @since 1.0.0
16 * @param object $user The current user's $user object
17 * @return void
18 */
19 function gamipress_user_profile_data( $user = null ) {
20 ?>
21
22 <?php // Verify user meets minimum role to manage earned achievements
23 if ( current_user_can( gamipress_get_manager_capability() ) ) : ?>
24
25 <h2><?php echo gamipress_dashicon( 'gamipress' ); ?> <?php _e( 'GamiPress', 'gamipress' ); ?></h2>
26
27 <?php endif; ?>
28
29 <?php // Output markup to user rank
30 gamipress_profile_user_rank( $user );
31
32 // Output markup to list user points
33 gamipress_profile_user_points( $user );
34
35 // Output markup to list user earnings
36 gamipress_profile_user_earnings( $user );
37
38 // Output markup for awarding achievement for user
39 gamipress_profile_award_achievement( $user );
40
41 // Output markup for awarding requirement for user
42 gamipress_profile_award_requirement( $user );
43
44 }
45 add_action( 'show_user_profile', 'gamipress_user_profile_data' );
46 add_action( 'edit_user_profile', 'gamipress_user_profile_data' );
47
48 /**
49 * Update user rank ajax handler
50 *
51 * @since 1.5.9
52 */
53 function gamipress_ajax_profile_update_user_rank() {
54 // Security check, forces to die if not security passed
55 check_ajax_referer( 'gamipress_admin', 'nonce' );
56
57 $rank_id = absint( $_POST['rank_id'] );
58 $user_id = absint( $_POST['user_id'] );
59
60 // Check if user has permissions
61 if ( ! current_user_can( 'edit_user', $user_id ) )
62 wp_send_json_error( __( 'You can perform this action.', 'gamipress' ) );
63
64 // Check if valid user ID
65 if( $user_id === 0 )
66 wp_send_json_error( __( 'Invalid user ID.', 'gamipress' ) );
67
68 $rank = gamipress_get_post( $rank_id );
69
70 // Check if is a valid rank
71 if ( ! $rank )
72 wp_send_json_error( __( 'Invalid post ID.', 'gamipress' ) );
73
74 if ( ! gamipress_is_rank( $rank ) )
75 wp_send_json_error( __( 'Invalid rank ID.', 'gamipress' ) );
76
77 // Update the user rank
78 gamipress_update_user_rank( $user_id, absint( $rank_id ), get_current_user_id() );
79
80 wp_send_json_success( array(
81 'message' => __( 'Rank updated successfully.', 'gamipress' ),
82 'rank' => array(
83 'ID' => $rank->ID,
84 'post_title' => $rank->post_title,
85 'thumbnail' => gamipress_get_rank_post_thumbnail( $rank->ID, array( 32, 32 ) ),
86 )
87 ) );
88
89 }
90 add_action( 'wp_ajax_gamipress_profile_update_user_rank', 'gamipress_ajax_profile_update_user_rank' );
91
92 /**
93 * Update user points ajax handler
94 *
95 * @since 1.5.9
96 * @updated 1.6.0 Now also return the current user ranks in order to see any rank change through the points earned
97 */
98 function gamipress_ajax_profile_update_user_points() {
99 // Security check, forces to die if not security passed
100 check_ajax_referer( 'gamipress_admin', 'nonce' );
101
102 $points = absint( $_POST['points'] );
103 $register_movement = ( bool ) $_POST['register_movement'];
104 $earnings_text = stripslashes( sanitize_text_field( $_POST['earnings_text'] ) );
105 $points_type = sanitize_text_field( $_POST['points_type'] );
106 $user_id = absint( $_POST['user_id'] );
107
108 // Check if user can edit other users
109 if ( ! current_user_can( 'edit_user', $user_id ) ) {
110 wp_send_json_error( __( 'You can perform this action.', 'gamipress' ) );
111 }
112
113 // Check if user can manage GamiPress
114 if( ! current_user_can( gamipress_get_manager_capability() ) ) {
115 wp_send_json_error( __( 'You can perform this action.', 'gamipress' ) );
116 }
117
118 // Check if valid user ID
119 if( $user_id === 0 ) {
120 wp_send_json_error( __( 'Invalid user ID.', 'gamipress' ) );
121 }
122
123 // Check if valid amount
124 if( ! is_numeric( $points ) ) {
125 wp_send_json_error( __( 'Invalid points amount.', 'gamipress' ) );
126 }
127
128 // Check if is valid points type
129 if( $points_type !== '' && ! in_array( $points_type, gamipress_get_points_types_slugs() ) ) {
130 wp_send_json_error( __( 'Invalid points type.', 'gamipress' ) );
131 }
132
133 // Grab the user's current points
134 $current_points = gamipress_get_user_points( $user_id, $points_type );
135
136 // Update the user points
137 gamipress_update_user_points( $user_id, $points, get_current_user_id(), null, $points_type );
138
139 if( $register_movement ) {
140
141 // Insert the custom user earning for the manual balance adjustment
142 gamipress_insert_user_earning( $user_id, array(
143 'title' => $earnings_text,
144 'user_id' => $user_id,
145 'post_id' => gamipress_get_points_type_id( $points_type ),
146 'post_type' => 'points-type',
147 'points' => $points - $current_points,
148 'points_type' => $points_type,
149 'date' => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
150 ) );
151
152 }
153
154 // After update the user points balance, is possible that user unlocks a rank
155 // For that, we need to return the current user ranks again and check for differences
156 $ranks = array();
157
158 foreach( gamipress_get_rank_types_slugs() as $rank_type ) {
159
160 // Get the rank object to build the same response as gamipress_ajax_profile_update_user_rank() function
161 $rank = gamipress_get_user_rank( $user_id, $rank_type );
162
163 $ranks[] = array(
164 'ID' => $rank->ID,
165 'post_title' => $rank->post_title,
166 'post_type' => $rank->post_type, // Included to meet the rank type
167 'thumbnail' => gamipress_get_rank_post_thumbnail( $rank->ID, array( 32, 32 ) ),
168 );
169 }
170
171 wp_send_json_success( array(
172 'message' => __( 'Points updated successfully.', 'gamipress' ),
173 'points' => gamipress_format_amount( $points, $points_type ),
174 'ranks' => $ranks
175 ) );
176
177 }
178 add_action( 'wp_ajax_gamipress_profile_update_user_points', 'gamipress_ajax_profile_update_user_points' );
179
180 /**
181 * Generate markup to show user rank
182 *
183 * @since 1.0.0
184 *
185 * @param object $user The current user's $user object
186 *
187 * @return string concatenated markup
188 */
189 function gamipress_profile_user_rank( $user = null ) {
190
191 $rank_types = gamipress_get_rank_types();
192
193 $can_manage = current_user_can( gamipress_get_manager_capability() );
194
195 // Return if not rank types and user is not a manager
196 if( empty( $rank_types ) && ! $can_manage ) {
197 return;
198 }
199 ?>
200
201 <table class="form-table">
202 <tr>
203 <th>
204 <label><?php echo $can_manage ? __( 'Ranks', 'gamipress' ) : __( 'Your Ranks', 'gamipress' ); ?></label>
205 </th>
206 <td>
207
208 <?php if( empty( $rank_types ) && $can_manage ) : ?>
209
210 <?php // No rank types configured yet ?>
211 <span class="description">
212 <?php echo sprintf( __( 'No rank types configured, visit %s to configure some rank types.', 'gamipress' ), '<a href="' . admin_url( 'edit.php?post_type=rank-type' ) . '">' . __( 'this page', 'gamipress' ) . '</a>' ); ?>
213 </span>
214
215 <?php else : ?>
216
217 <div class="profile-ranks gamipress-profile-cards">
218
219 <?php // Show the information of each user rank ?>
220 <?php foreach( $rank_types as $rank_type => $data ) : ?>
221
222 <div class="profile-rank-wrapper gamipress-profile-card-wrapper">
223 <div class="profile-rank profile-rank-<?php echo $rank_type; ?> gamipress-profile-card">
224
225 <span class="profile-rank-type-name"><?php echo $data['singular_name']; ?></span>
226
227 <?php // Get and display the current user rank
228 $user_rank = gamipress_get_user_rank( $user->ID, $rank_type );
229
230 if( $user_rank ) : ?>
231
232 <div class="profile-rank-thumbnail"><?php echo gamipress_get_rank_post_thumbnail( $user_rank->ID, array( 32, 32 ) ); ?></div>
233
234 <span class="profile-rank-title"><?php echo $user_rank->post_title; ?></span>
235
236 <?php endif; ?>
237
238
239 <?php if( $can_manage ) :
240 // Show an editable form of ranks
241
242 // Get all published ranks of this type
243 $ranks = gamipress_get_ranks( array(
244 'post_type' => $rank_type,
245 'posts_per_page' => -1
246 ) ); ?>
247
248 <?php if( empty( $ranks ) ) : ?>
249
250 <?php // No ranks of this type configured yet ?>
251 <span class="description">
252 <?php echo sprintf( __( 'No %1$s configured, visit %2$s to configure some %1$s.', 'gamipress' ),
253 strtolower( $data['plural_name'] ),
254 '<a href="' . admin_url( 'edit.php?post_type=' . $rank_type ) . '">' . __( 'this page', 'gamipress' ) . '</a>'
255 ); ?>
256 </span>
257
258 <?php else : ?>
259
260 <a href="#" class="profile-rank-toggle"><?php echo __( 'Edit', 'gamipress' ); ?></a>
261
262 <div class="profile-rank-form-wrapper">
263
264 <select name="user_<?php echo $rank_type; ?>_rank" id="user_<?php echo $rank_type; ?>_rank" style="min-width: 15em;">
265 <?php foreach( $ranks as $rank ) : ?>
266 <option value="<?php echo $rank->ID; ?>" <?php selected( $user_rank->ID, $rank->ID ); ?>><?php echo $rank->post_title; ?></option>
267 <?php endforeach; ?>
268 </select>
269
270 <span class="description"><?php echo sprintf( __( '%s listed are ordered by priority.', 'gamipress' ), $data['plural_name'] ); ?></span>
271
272 <div class="profile-rank-form-buttons">
273 <a href="#" class="button button-primary profile-rank-save"><?php echo __( 'Save', 'gamipress' ); ?></a>
274 <a href="#" class="button profile-rank-cancel"><?php echo __( 'Cancel', 'gamipress' ); ?></a>
275 <span class="spinner"></span>
276 </div>
277
278 </div>
279
280 <?php endif; ?>
281
282 <?php endif; ?>
283
284 </div>
285 </div>
286
287 <?php endforeach; ?>
288
289 </div>
290
291 <?php endif; ?>
292
293 </td>
294 </tr>
295 </table>
296
297 <?php
298 }
299
300 /**
301 * Generate markup to list user earned points
302 *
303 * @since 1.0.0
304 *
305 * @param object $user The current user's $user object
306 *
307 * @return string concatenated markup
308 */
309 function gamipress_profile_user_points( $user = null ) {
310
311 $points_types = gamipress_get_points_types();
312
313 $can_manage = current_user_can( gamipress_get_manager_capability() );
314
315 // Return if not points types and user is not a manager
316 if( empty( $points_types ) && ! $can_manage ) {
317 return;
318 }
319 ?>
320
321 <table class="form-table">
322 <tr>
323 <th>
324 <label><?php echo $can_manage ? __( 'Points Balances', 'gamipress' ) : __( 'Your Balances', 'gamipress' ); ?></label>
325 </th>
326 <td>
327
328 <?php if( empty( $points_types ) && $can_manage ) : ?>
329
330 <span class="description">
331 <?php echo sprintf( __( 'No points types configured, visit %s to configure some points types.', 'gamipress' ), '<a href="' . admin_url( 'edit.php?post_type=points-type' ) . '">' . __( 'this page', 'gamipress' ) . '</a>' ); ?>
332 </span>
333
334 <?php else : ?>
335
336 <div class="profile-points gamipress-profile-cards">
337
338 <?php // Filter available to re-enable the default points
339 if( apply_filters( 'gamipress_user_points_backward_compatibility', false ) ) :
340 $user_points = gamipress_get_user_points( $user->ID ); ?>
341
342 <div class="profile-points-wrapper gamipress-profile-card-wrapper">
343
344 <div class="profile-points profile-points-default gamipress-profile-card">
345
346 <span class="profile-points-type-name"><?php _e( 'Points', 'gamipress' ); ?></span>
347
348 <div class="profile-points-thumbnail"></div>
349
350 <span class="profile-points-amount"><?php echo $user_points; ?></span>
351
352 <?php if( $can_manage ) :
353 // Show an editable form of points ?>
354
355 <a href="#" class="profile-points-toggle"><?php echo __( 'Edit', 'gamipress' ); ?></a>
356
357 <div class="profile-points-form-wrapper">
358
359 <input type="number" name="user_points" id="user_points" value="<?php echo $user_points; ?>" class="regular-text" data-points-type="" />
360
361 <span class="description"><?php echo __( 'Enter a new total will automatically log the change and difference between totals.', 'gamipress' ); ?></span>
362
363 <div class="profile-points-form-buttons">
364 <a href="#" class="button button-primary profile-points-save"><?php echo __( 'Save', 'gamipress' ); ?></a>
365 <a href="#" class="button profile-points-cancel"><?php echo __( 'Cancel', 'gamipress' ); ?></a>
366 <span class="spinner"></span>
367 </div>
368
369 </div>
370
371 <?php endif; ?>
372
373 </div>
374
375 </div>
376
377 <?php endif; ?>
378
379 <?php foreach( $points_types as $points_type => $data ) :
380 $user_points = gamipress_get_user_points( $user->ID, $points_type ); ?>
381
382 <div class="profile-points-wrapper gamipress-profile-card-wrapper">
383
384 <div class="profile-points profile-points-<?php echo $points_type; ?> gamipress-profile-card">
385
386 <span class="profile-points-type-name"><?php echo $data['plural_name']; ?></span>
387
388 <div class="profile-points-thumbnail"><?php echo gamipress_get_points_type_thumbnail( $points_type, array( 32, 32 ) ); ?></div>
389
390 <span class="profile-points-amount"><?php echo gamipress_format_amount( $user_points, $points_type ); ?></span>
391
392 <?php if( $can_manage ) :
393 // Show an editable form of points ?>
394
395 <a href="#" class="profile-points-toggle"><?php echo __( 'Edit', 'gamipress' ); ?></a>
396
397 <div class="profile-points-form-wrapper">
398
399 <div class="profile-points-new-balance-input">
400 <label for="user_<?php echo $points_type; ?>_points"><?php echo __( 'New balance:', 'gamipress' ); ?></label>
401 <input type="number" name="user_<?php echo $points_type; ?>_points" id="user_<?php echo $points_type; ?>_points" value="<?php echo $user_points; ?>" class="regular-text" data-points-type="<?php echo $points_type; ?>" />
402 <span class="description"><?php echo __( 'Enter a new total will automatically log the change and difference between totals.', 'gamipress' ); ?></span>
403 </div>
404
405 <label for="user_<?php echo $points_type; ?>_register_points_movement" class="profile-points-register-movement-input-label"><?php echo __( 'Register on user earnings:', 'gamipress' ); ?></label>
406 <div class="gamipress-switch gamipress-switch-small profile-points-register-movement-input">
407 <input type="checkbox" name="user_<?php echo $points_type; ?>_register_points_movement" id="user_<?php echo $points_type; ?>_register_points_movement">
408 <label for="user_<?php echo $points_type; ?>_register_points_movement"><?php echo __( 'Check this option to register this balance movement on user earnings.', 'gamipress' ); ?></label>
409 </div>
410
411 <div class="profile-points-earning-text-input" style="display: none;">
412 <label for="user_<?php echo $points_type; ?>_points_earning_text"><?php echo __( 'Earning entry text:', 'gamipress' ); ?></label>
413 <input type="text" name="user_<?php echo $points_type; ?>_points_earning_text" id="user_<?php echo $points_type; ?>_points_earning_text" value="<?php echo __( 'Manual balance adjustment', 'gamipress' ); ?>" class="regular-text" />
414 <span class="description"><?php echo __( 'Enter the line text to be displayed on user earnings.', 'gamipress' ); ?></span>
415 </div>
416
417 <div class="profile-points-form-buttons">
418 <a href="#" class="button button-primary profile-points-save"><?php echo __( 'Save', 'gamipress' ); ?></a>
419 <a href="#" class="button profile-points-cancel"><?php echo __( 'Cancel', 'gamipress' ); ?></a>
420 <span class="spinner"></span>
421 </div>
422
423 </div>
424
425 <?php endif; ?>
426
427 </div>
428
429 </div>
430
431 <?php endforeach; ?>
432
433 </div>
434
435 <?php endif; ?>
436 </td>
437 </tr>
438 </table>
439
440 <?php
441 }
442
443 /**
444 * Generate markup to list user earnings
445 *
446 * @since 1.0.0
447 *
448 * @param object $user The current user's $user object
449 *
450 * @return string concatenated markup
451 */
452 function gamipress_profile_user_earnings( $user = null ) {
453
454 /**
455 * Filter to allow set the number of user earnings to show on user profile
456 *
457 * @since 1.8.3
458 *
459 * @param int $items_per_page
460 *
461 * @return int
462 */
463 $items_per_page = apply_filters( 'gamipress_user_profile_earnings_items_per_page', 10 );
464 ?>
465
466 <h2><?php echo current_user_can( gamipress_get_manager_capability() ) ? __( 'User Earnings', 'gamipress' ) : __( 'Your Achievements', 'gamipress' ); ?></h2>
467
468 <?php ct_render_ajax_list_table( 'gamipress_user_earnings',
469 array(
470 'user_id' => absint( $user->ID ),
471 'items_per_page' => $items_per_page,
472 ),
473 array(
474 'views' => false,
475 'search_box' => false
476 )
477 ); ?>
478
479 <?php
480 }
481
482 /**
483 * Generate markup for awarding an achievement to a user
484 *
485 * @since 1.0.0
486 *
487 * @param object $user The current user's $user object
488 *
489 * @return string concatenated markup
490 */
491 function gamipress_profile_award_achievement( $user = null ) {
492
493 // Return if user is not a manager
494 if( ! current_user_can( gamipress_get_manager_capability() ) ) {
495 return;
496 }
497
498 // Grab our types
499 $achievement_types = gamipress_get_achievement_types();
500 ?>
501
502 <h2><?php _e( 'Award Achievement', 'gamipress' ); ?></h2>
503
504 <table class="form-table">
505
506 <tr>
507 <th><label for="gamipress-award-achievement-type-select"><?php _e( 'Select an achievement type to award:', 'gamipress' ); ?></label></th>
508 <td>
509 <select id="gamipress-award-achievement-type-select">
510 <option value=""><?php _e( 'Choose an achievement type', 'gamipress' ); ?></option>
511 <?php foreach ( $achievement_types as $slug => $data ) :
512 echo '<option value="'. $slug .'">' . ucwords( $data['singular_name'] ) .'</option>';
513 endforeach; ?>
514 </select>
515 </td>
516 </tr>
517
518 </table>
519
520 <div id="gamipress-awards-options">
521 <?php foreach ( $achievement_types as $slug => $data ) : ?>
522 <div id="<?php echo esc_attr( $slug ); ?>" data-loaded="false" style="display: none;">
523 <span class="spinner is-active"></span>
524 </div>
525 <?php endforeach; ?>
526
527 </div><!-- #gamipress-awards-options -->
528
529 <?php
530 }
531
532 /**
533 * Ajax handler to load the award table of the given post type
534 *
535 * @since 1.8.7
536 */
537 function gamipress_ajax_profile_load_award_achievement_award() {
538
539 // Security check, forces to die if not security passed
540 check_ajax_referer( 'gamipress_admin', 'nonce' );
541
542 // Return if user is not a manager
543 if( ! current_user_can( gamipress_get_manager_capability() ) ) {
544 wp_send_json_error( __( 'You can perform this action.', 'gamipress' ) );
545 }
546
547 $post_type = sanitize_text_field( $_POST['post_type'] );
548 $user_id = absint( $_POST['user_id'] );
549
550 // Check if user has permissions
551 if ( ! current_user_can( 'edit_user', $user_id ) ) {
552 wp_send_json_error( __( 'You can perform this action.', 'gamipress' ) );
553 }
554
555 // Grab our types
556 $achievement_types = gamipress_get_achievement_types();
557
558 $achievements = gamipress_get_user_achievements( array(
559 'user_id' => absint( $user_id ),
560 'achievement_type' => $post_type
561 ) );
562
563 $achievement_ids = array_map( function( $achievement ) {
564 return $achievement->ID;
565 }, $achievements );
566
567 // On network wide active installs, we need to switch to main blog mostly for posts permalinks and thumbnails
568 $blog_id = gamipress_switch_to_main_site_if_network_wide_active();
569
570 ob_start(); ?>
571
572 <?php foreach ( $achievement_types as $slug => $data ) :
573
574 // Skip if not is the points type to render
575 if( $post_type !== $slug ) {
576 continue;
577 } ?>
578 <div id="<?php echo esc_attr( $slug ); ?>">
579 <table id="<?php echo esc_attr( $slug ); ?>-table" class="wp-list-table widefat fixed striped gamipress-table">
580
581 <thead>
582 <tr>
583 <th><?php echo ucwords( $data['singular_name'] ); ?></th>
584 <th><?php _e( 'Actions', 'gamipress' ); ?></th>
585 </tr>
586 </thead>
587
588 <tbody>
589 <?php
590 // Load achievement type entries
591 $the_query = new WP_Query( array(
592 'post_type' => $slug,
593 'posts_per_page' => -1,
594 'post_status' => 'publish',
595 'suppress_filters' => false
596 ) );
597
598 if ( $the_query->have_posts() ) : ?>
599
600 <?php while ( $the_query->have_posts() ) : $the_query->the_post();
601
602 // Setup our award URL
603 $award_url = add_query_arg( array(
604 'action' => 'award',
605 'achievement_id' => absint( get_the_ID() ),
606 'user_id' => absint( $user_id )
607 ) );
608 ?>
609 <tr>
610 <td>
611 <?php // Thumbnail ?>
612 <?php echo gamipress_get_achievement_post_thumbnail( get_the_ID(), array( 32, 32 ) ); ?>
613
614 <?php // Title ?>
615 <strong><?php echo '<a href="' . get_edit_post_link( get_the_ID() ) . '">' . gamipress_get_post_field( 'post_title', get_the_ID() ) . '</a>'; ?></strong>
616 </td>
617 <td>
618 <a class="gamipress-award-achievement" href="<?php echo esc_url( wp_nonce_url( $award_url, 'gamipress_award_achievement' ) ); ?>"><?php printf( __( 'Award %s', 'gamipress' ), ucwords( $data['singular_name'] ) ); ?></a>
619 <?php if ( in_array( get_the_ID(), (array) $achievement_ids ) ) :
620 // Setup our revoke URL
621 $revoke_url = add_query_arg( array(
622 'action' => 'revoke',
623 'user_id' => absint( $user_id ),
624 'achievement_id' => absint( get_the_ID() ),
625 ) );
626 ?>
627 | <span class="delete"><a class="error gamipress-revoke-achievement" href="<?php echo esc_url( wp_nonce_url( $revoke_url, 'gamipress_revoke_achievement' ) ); ?>"><?php _e( 'Revoke Award', 'gamipress' ); ?></a></span>
628 <?php endif; ?>
629
630 </td>
631 </tr>
632 <?php endwhile; ?>
633
634 <?php else : ?>
635 <tr>
636 <td colspan="3"><?php printf( __( 'No %s found.', 'gamipress' ), $data['plural_name'] ); ?></td>
637 </tr>
638 <?php endif; wp_reset_postdata(); ?>
639
640 </tbody>
641
642 </table><!-- #<?php echo esc_attr( $slug ); ?>-table -->
643 </div><!-- #<?php echo esc_attr( $slug ); ?> -->
644
645 <?php endforeach; ?>
646
647 <?php $content = ob_get_clean();
648
649 // If switched to blog, return back to que current blog
650 if( $blog_id !== get_current_blog_id() && is_multisite() ) {
651 restore_current_blog();
652 }
653
654 if( empty( $content ) ) {
655 wp_send_json_error( __( 'Couldn\'t load this content.', 'gamipress' ) );
656 }
657
658 // Return the table rendered
659 wp_send_json_success( $content );
660
661 }
662 add_action( 'wp_ajax_gamipress_profile_load_award_achievement_table', 'gamipress_ajax_profile_load_award_achievement_award' );
663
664 /**
665 * Generate markup for awarding an achievement to a user
666 *
667 * @since 1.6.8
668 *
669 * @param object $user The current user's $user object
670 *
671 * @return string concatenated markup
672 */
673 function gamipress_profile_award_requirement( $user = null ) {
674
675 // Return if user is not a manager
676 if( ! current_user_can( gamipress_get_manager_capability() ) ) {
677 return;
678 }
679
680 // Grab our types
681 $requirement_types = gamipress_get_requirement_types();
682
683 ?>
684
685 <h2><?php _e( 'Award Requirement', 'gamipress' ); ?></h2>
686
687 <table class="form-table">
688
689 <tr>
690 <th><label for="gamipress-award-requirement-type-select"><?php _e( 'Select a requirement type to award:', 'gamipress' ); ?></label></th>
691 <td>
692 <select id="gamipress-award-requirement-type-select">
693 <option value=""><?php _e( 'Choose a requirement type', 'gamipress' ); ?></option>
694 <?php foreach ( $requirement_types as $slug => $data ) :
695 echo '<option value="'. $slug .'">' . ucwords( $data['singular_name'] ) .'</option>';
696 endforeach; ?>
697 </select>
698 </td>
699 </tr>
700
701 </table>
702
703 <div id="gamipress-awards-options">
704 <?php foreach ( $requirement_types as $slug => $data ) : ?>
705 <div id="<?php echo esc_attr( $slug ); ?>" data-loaded="false" style="display: none;">
706 <span class="spinner is-active"></span>
707 </div>
708 <?php endforeach; ?>
709
710 </div><!-- #gamipress-awards-options -->
711
712 <?php
713 }
714
715 /**
716 * Ajax handler to load the requiremetn award table of the given post type
717 *
718 * @since 1.8.7
719 */
720 function gamipress_ajax_profile_load_award_requirement_table() {
721
722 // Security check, forces to die if not security passed
723 check_ajax_referer( 'gamipress_admin', 'nonce' );
724
725 // Return if user is not a manager
726 if( ! current_user_can( gamipress_get_manager_capability() ) ) {
727 wp_send_json_error( __( 'You can perform this action.', 'gamipress' ) );
728 }
729
730 $post_type = sanitize_text_field( $_POST['post_type'] );
731 $user_id = absint( $_POST['user_id'] );
732
733 // Check if user has permissions
734 if ( ! current_user_can( 'edit_user', $user_id ) ) {
735 wp_send_json_error( __( 'You can perform this action.', 'gamipress' ) );
736 }
737
738 // Grab our types
739 $achievement_types = gamipress_get_achievement_types();
740 $rank_types = gamipress_get_rank_types();
741 $requirement_types = gamipress_get_requirement_types();
742
743 $achievements = gamipress_get_user_achievements( array(
744 'user_id' => absint( $user_id ),
745 'achievement_type' => $post_type
746 ) );
747
748 $achievement_ids = array_map( function( $achievement ) {
749 return $achievement->ID;
750 }, $achievements );
751
752 // On network wide active installs, we need to switch to main blog mostly for posts permalinks and thumbnails
753 $blog_id = gamipress_switch_to_main_site_if_network_wide_active();
754
755 ob_start(); ?>
756
757 <?php foreach ( $requirement_types as $slug => $data ) :
758
759 // Skip if not is the points type to render
760 if( $post_type !== $slug ) {
761 continue;
762 } ?>
763 <div id="<?php echo esc_attr( $slug ); ?>">
764 <table id="<?php echo esc_attr( $slug ); ?>-table" class="wp-list-table widefat fixed striped gamipress-table">
765
766 <thead>
767 <tr>
768 <th><?php echo ucwords( $data['singular_name'] ); ?></th>
769 <th><?php _e( 'Actions', 'gamipress' ); ?></th>
770 </tr>
771 </thead>
772
773 <tbody>
774 <?php
775 // Load achievement type entries
776 $the_query = new WP_Query( array(
777 'post_type' => $slug,
778 'posts_per_page' => -1,
779 'post_status' => 'publish',
780 'suppress_filters' => false
781 ) );
782
783 if ( $the_query->have_posts() ) : ?>
784
785 <?php while ( $the_query->have_posts() ) : $the_query->the_post();
786
787 // If not parent object, skip
788 if( $slug === 'step' && ! $achievement = gamipress_get_step_achievement( get_the_ID() ) ) {
789 continue;
790 } else if( $slug === 'points-award' && ! $points_type = gamipress_get_points_award_points_type( get_the_ID() ) ) {
791 continue;
792 } else if( $slug === 'points-deduct' && ! $points_type = gamipress_get_points_deduct_points_type( get_the_ID() ) ) {
793 continue;
794 } else if( $slug === 'rank-requirement' && ! $rank = gamipress_get_rank_requirement_rank( get_the_ID() ) ) {
795 continue;
796 }
797
798 // Setup our award URL
799 $award_url = add_query_arg( array(
800 'action' => 'award',
801 'achievement_id' => absint( get_the_ID() ),
802 'user_id' => absint( $user_id )
803 ) );
804 ?>
805 <tr>
806 <td>
807 <?php // Output parent achievement
808 if( $slug === 'step' && $achievement ) : ?>
809
810 <?php // Achievement thumbnail ?>
811 <?php echo gamipress_get_achievement_post_thumbnail( $achievement->ID, array( 32, 32 ) ); ?>
812
813 <?php // Step title ?>
814 <strong><?php echo gamipress_get_post_field( 'post_title', get_the_ID() ); ?></strong>
815
816 <?php // Step relationship details ?>
817 <?php echo ( isset( $achievement_types[$achievement->post_type] ) ? '<br> ' . $achievement_types[$achievement->post_type]['singular_name'] . ': ' : '' ); ?>
818 <?php echo '<a href="' . get_edit_post_link( $achievement->ID ) . '">' . gamipress_get_post_field( 'post_title', $achievement->ID ) . '</a>'; ?>
819
820 <?php elseif( in_array( $slug, array( 'points-award', 'points-deduct' ) ) && $points_type ) : ?>
821
822 <?php // Points type thumbnail ?>
823 <?php echo gamipress_get_points_type_thumbnail( $points_type->ID, array( 32, 32 ) ); ?>
824
825 <?php // Points award/deduct title ?>
826 <strong><?php echo gamipress_get_post_field( 'post_title', get_the_ID() ); ?></strong>
827 <br>
828 <?php echo '<a href="' . get_edit_post_link( $points_type->ID ) . '">' . gamipress_get_post_field( 'post_title', $points_type->ID ) . '</a>'; ?>
829
830 <?php elseif( $slug === 'rank-requirement' && $rank ) : ?>
831
832 <?php // Rank thumbnail ?>
833 <?php echo gamipress_get_rank_post_thumbnail( $rank->ID, array( 32, 32 ) ); ?>
834
835 <?php // Rank requirement title ?>
836 <strong><?php echo gamipress_get_post_field( 'post_title', get_the_ID() ); ?></strong>
837
838 <?php // Rank requirement relationship details ?>
839 <?php echo ( isset( $rank_types[$rank->post_type] ) ? '<br> ' . $rank_types[$rank->post_type]['singular_name'] . ': ' : '' ); ?>
840 <?php echo '<a href="' . get_edit_post_link( $rank->ID ) . '">' . gamipress_get_post_field( 'post_title', $rank->ID ) . '</a>'; ?>
841
842 <?php endif; ?>
843 </td>
844 <td>
845 <a class="gamipress-award-achievement" href="<?php echo esc_url( wp_nonce_url( $award_url, 'gamipress_award_achievement' ) ); ?>"><?php printf( __( 'Award %s', 'gamipress' ), ucwords( $data['singular_name'] ) ); ?></a>
846 <?php if ( in_array( get_the_ID(), (array) $achievement_ids ) ) :
847 // Setup our revoke URL
848 $revoke_url = add_query_arg( array(
849 'action' => 'revoke',
850 'user_id' => absint( $user_id ),
851 'achievement_id' => absint( get_the_ID() ),
852 ) );
853 ?>
854 | <span class="delete"><a class="error gamipress-revoke-achievement" href="<?php echo esc_url( wp_nonce_url( $revoke_url, 'gamipress_revoke_achievement' ) ); ?>"><?php _e( 'Revoke Award', 'gamipress' ); ?></a></span>
855 <?php endif; ?>
856
857 </td>
858 </tr>
859 <?php endwhile; ?>
860
861 <?php else : ?>
862 <tr>
863 <td colspan="3"><?php printf( __( 'No %s found.', 'gamipress' ), $data['plural_name'] ); ?></td>
864 </tr>
865 <?php endif; wp_reset_postdata(); ?>
866
867 </tbody>
868
869 </table><!-- #<?php echo esc_attr( $slug ); ?> -->
870 </div><!-- #<?php echo esc_attr( $slug ); ?> -->
871
872 <?php endforeach; ?>
873
874 <?php $content = ob_get_clean();
875
876 // If switched to blog, return back to que current blog
877 if( $blog_id !== get_current_blog_id() && is_multisite() ) {
878 restore_current_blog();
879 }
880
881 if( empty( $content ) ) {
882 wp_send_json_error( __( 'Couldn\'t load this content.', 'gamipress' ) );
883 }
884
885 // Return the table rendered
886 wp_send_json_success( $content );
887
888 }
889 add_action( 'wp_ajax_gamipress_profile_load_award_requirement_table', 'gamipress_ajax_profile_load_award_requirement_table' );
890
891
892 /**
893 * Process the adding/revoking of achievements on the user profile page
894 *
895 * @since 1.0.0
896 */
897 function gamipress_process_user_data() {
898
899 // verify user meets minimum role to view earned achievements
900 if ( current_user_can( gamipress_get_manager_capability() ) ) {
901
902 // Process awarding achievement to user
903 if ( isset( $_GET['action'] ) && $_GET['action'] === 'award' && isset( $_GET['user_id'] ) && isset( $_GET['achievement_id'] ) ) {
904
905 // Verify our nonce
906 check_admin_referer( 'gamipress_award_achievement' );
907
908 // Award the achievement
909 gamipress_award_achievement_to_user( absint( $_GET['achievement_id'] ), absint( $_GET['user_id'] ), get_current_user_id() );
910
911 // Redirect back to the user editor
912 wp_redirect( add_query_arg( 'user_id', absint( $_GET['user_id'] ), admin_url( 'user-edit.php' ) ) );
913 exit();
914 }
915
916 // Process revoking achievement from a user
917 if ( isset( $_GET['action'] ) && $_GET['action'] === 'revoke' && isset( $_GET['user_id'] ) && isset( $_GET['achievement_id'] ) ) {
918
919 // Verify our nonce
920 check_admin_referer( 'gamipress_revoke_achievement' );
921
922 $earning_id = isset( $_GET['user_earning_id'] ) ? absint( $_GET['user_earning_id'] ) : 0 ;
923
924 // Revoke the achievement
925 gamipress_revoke_achievement_to_user( absint( $_GET['achievement_id'] ), absint( $_GET['user_id'] ), $earning_id );
926
927 // If revoking from user earnings screen return directly without redirect
928 if( isset( $_GET['page'] ) && $_GET['page'] === 'gamipress_user_earnings' ) {
929 exit();
930 }
931
932 // Redirect back to the user editor
933 wp_redirect( add_query_arg( 'user_id', absint( $_GET['user_id'] ), admin_url( 'user-edit.php' ) ) );
934 exit();
935
936 }
937
938 }
939
940 }
941 add_action( 'admin_init', 'gamipress_process_user_data' );