PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 8.0.5
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v8.0.5
8.0.5 8.0.4 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 All 47 releases
← All changes | includes/shortcodes/gamipress_achievements.php +650 -0 7.9.2 → 8.0.5 View file →
@@ -1,0 +1,650 @@
1 +<?php
2 +/**
3 + * GamiPress Achievements Shortcode
4 + *
5 + * @package GamiPress\Shortcodes\Shortcode\GamiPress_Achievements
6 + * @author GamiPress <[email protected]>, Ruben Garcia <[email protected]>
7 + * @since 1.0.0
8 + */
9 +// Exit if accessed directly
10 +if( !defined( 'ABSPATH' ) ) exit;
11 +
12 +/**
13 + * Register [gamipress_achievements] shortcode
14 + *
15 + * @since 1.0.0
16 + */
17 +function gamipress_register_achievements_shortcode() {
18 +
19 + $achievement_fields = GamiPress()->shortcodes['gamipress_achievement']->fields;
20 +
21 + unset( $achievement_fields['id'] );
22 +
23 + gamipress_register_shortcode( 'gamipress_achievements', array(
24 + 'name' => __( 'Achievement List', 'gamipress' ),
25 + 'description' => __( 'Display a list of achievements.', 'gamipress' ),
26 + 'icon' => 'awards',
27 + 'group' => 'gamipress',
28 + 'output_callback' => 'gamipress_achievements_shortcode',
29 + 'tabs' => array(
30 + 'general' => array(
31 + 'icon' => 'dashicons-admin-generic',
32 + 'title' => __( 'General', 'gamipress' ),
33 + 'fields' => array(
34 + 'type',
35 + 'columns',
36 + 'columns_small',
37 + 'filter',
38 + 'filter_value',
39 + 'search',
40 + 'search_value',
41 + 'load_more',
42 + ),
43 + ),
44 + 'achievement' => array(
45 + 'icon' => 'dashicons-awards',
46 + 'title' => __( 'Achievement', 'gamipress' ),
47 + 'fields' => array_keys( $achievement_fields ),
48 + ),
49 + 'query' => array(
50 + 'icon' => 'dashicons-search',
51 + 'title' => __( 'Query', 'gamipress' ),
52 + 'fields' => array(
53 + 'limit',
54 + 'orderby',
55 + 'order',
56 + 'current_user',
57 + 'user_id',
58 + 'include',
59 + 'exclude',
60 + 'wpms',
61 + ),
62 + ),
63 + ),
64 + 'fields' => array_merge( array(
65 + 'type' => array(
66 + 'name' => __( 'Achievement Type(s)', 'gamipress' ),
67 + 'tooltip' => __( 'Achievement type(s) to display.', 'gamipress' ),
68 + 'label_cb' => 'cmb_tooltip_label_cb',
69 + 'shortcode_desc' => __( 'Single or comma-separated list of achievement type(s) to display.', 'gamipress' ),
70 + 'type' => 'advanced_select',
71 + 'classes' => 'gamipress-selector',
72 + 'attributes' => array(
73 + 'data-placeholder' => __( 'Default: All', 'gamipress' ),
74 + ),
75 + 'multiple' => true,
76 + 'options_cb' => 'gamipress_options_cb_achievement_types',
77 + 'default' => 'all',
78 + ),
79 + 'columns' => array(
80 + 'name' => __( 'Columns', 'gamipress' ),
81 + 'tooltip' => __( 'Columns to divide achievements.', 'gamipress' ),
82 + 'label_cb' => 'cmb_tooltip_label_cb',
83 + 'type' => 'select',
84 + 'options' => array(
85 + '1' => __( '1 Column', 'gamipress' ),
86 + '2' => __( '2 Columns', 'gamipress' ),
87 + '3' => __( '3 Columns', 'gamipress' ),
88 + '4' => __( '4 Columns', 'gamipress' ),
89 + '5' => __( '5 Columns', 'gamipress' ),
90 + '6' => __( '6 Columns', 'gamipress' ),
91 + ),
92 + 'default' => '1'
93 + ),
94 + 'columns_small' => array(
95 + 'name' => __( 'Columns in small screens', 'gamipress' ),
96 + 'tooltip' => __( 'Columns to divide achievements in small screens.', 'gamipress' ),
97 + 'label_cb' => 'cmb_tooltip_label_cb',
98 + 'type' => 'select',
99 + 'options' => array(
100 + '1' => __( '1 Column', 'gamipress' ),
101 + '2' => __( '2 Columns', 'gamipress' ),
102 + '3' => __( '3 Columns', 'gamipress' ),
103 + '4' => __( '4 Columns', 'gamipress' ),
104 + '5' => __( '5 Columns', 'gamipress' ),
105 + '6' => __( '6 Columns', 'gamipress' ),
106 + ),
107 + 'default' => '1'
108 + ),
109 + 'filter' => array(
110 + 'name' => __( 'Show Filter', 'gamipress' ),
111 + 'tooltip' => __( 'Display filter input.', 'gamipress' ),
112 + 'label_cb' => 'cmb_tooltip_label_cb',
113 + 'type' => 'checkbox',
114 + 'classes' => 'gamipress-switch',
115 + 'default' => 'yes'
116 + ),
117 + 'filter_value' => array(
118 + 'name' => __( 'Initial Filter Value', 'gamipress' ),
119 + 'tooltip' => __( 'Set filter initial value. If you hide the filter, user won\'t be able to change this value.', 'gamipress' ),
120 + 'label_cb' => 'cmb_tooltip_label_cb',
121 + 'type' => 'select',
122 + 'options' => array(
123 + 'all' => __( 'All Achievements', 'gamipress' ),
124 + 'completed' => __( 'Completed Achievements', 'gamipress' ),
125 + 'not-completed' => __( 'Not Completed Achievements', 'gamipress' ),
126 + ),
127 + 'default' => 'all'
128 + ),
129 + 'search' => array(
130 + 'name' => __( 'Show Search', 'gamipress' ),
131 + 'tooltip' => __( 'Display a search input.', 'gamipress' ),
132 + 'label_cb' => 'cmb_tooltip_label_cb',
133 + 'type' => 'checkbox',
134 + 'classes' => 'gamipress-switch',
135 + 'default' => 'yes'
136 + ),
137 + 'search_value' => array(
138 + 'name' => __( 'Initial Search Value', 'gamipress' ),
139 + 'tooltip' => __( 'Set search initial value. If you hide the search, user won\'t be able to change this value.', 'gamipress' ),
140 + 'label_cb' => 'cmb_tooltip_label_cb',
141 + 'type' => 'text',
142 + 'default' => ''
143 + ),
144 + 'load_more' => array(
145 + 'name' => __( 'Show the "Load More" button', 'gamipress' ),
146 + 'tooltip' => __( 'Display a load more button.', 'gamipress' ),
147 + 'label_cb' => 'cmb_tooltip_label_cb',
148 + 'type' => 'checkbox',
149 + 'classes' => 'gamipress-switch',
150 + 'default' => 'yes'
151 + ),
152 + 'limit' => array(
153 + 'name' => __( 'Limit', 'gamipress' ),
154 + 'tooltip' => __( 'Number of achievements to display.', 'gamipress' ),
155 + 'label_cb' => 'cmb_tooltip_label_cb',
156 + 'type' => 'text',
157 + 'default' => 10,
158 + ),
159 + 'orderby' => array(
160 + 'name' => __( 'Order By', 'gamipress' ),
161 + 'tooltip' => __( 'Parameter to use for sorting.', 'gamipress' ),
162 + 'label_cb' => 'cmb_tooltip_label_cb',
163 + 'type' => 'select',
164 + 'options' => array(
165 + 'menu_order' => __( 'Menu order', 'gamipress' ),
166 + 'ID' => __( 'Achievement', 'gamipress' ),
167 + 'title' => __( 'Title', 'gamipress' ),
168 + 'date' => __( 'Published date', 'gamipress' ),
169 + 'modified' => __( 'Last modified date', 'gamipress' ),
170 + 'author' => __( 'Author', 'gamipress' ),
171 + 'rand' => __( 'Random', 'gamipress' ),
172 + 'points_awarded' => __( 'Points awarded', 'gamipress' ),
173 + 'points_to_unlock' => __( 'Points to unlock', 'gamipress' ),
174 + ),
175 + 'default' => 'menu_order',
176 + ),
177 + 'order' => array(
178 + 'name' => __( 'Order', 'gamipress' ),
179 + 'tooltip' => __( 'Sort order.', 'gamipress' ),
180 + 'label_cb' => 'cmb_tooltip_label_cb',
181 + 'type' => 'select',
182 + 'options' => array( 'ASC' => __( 'Ascending', 'gamipress' ), 'DESC' => __( 'Descending', 'gamipress' ) ),
183 + 'default' => 'ASC',
184 + ),
185 + 'current_user' => array(
186 + 'name' => __( 'Current User', 'gamipress' ),
187 + 'tooltip' => __( 'Show achievements earned by the current logged in user.', 'gamipress' ),
188 + 'label_cb' => 'cmb_tooltip_label_cb',
189 + 'type' => 'checkbox',
190 + 'classes' => 'gamipress-switch',
191 + ),
192 + 'user_id' => array(
193 + 'name' => __( 'User', 'gamipress' ),
194 + 'tooltip' => __( 'Show achievements earned by a specific user.', 'gamipress' ),
195 + 'label_cb' => 'cmb_tooltip_label_cb',
196 + 'type' => 'select',
197 + 'default' => '',
198 + 'options_cb' => 'gamipress_options_cb_users'
199 + ),
200 + 'include' => array(
201 + 'name' => __( 'Include', 'gamipress' ),
202 + 'tooltip' => __( 'Achievements to include.', 'gamipress' ),
203 + 'label_cb' => 'cmb_tooltip_label_cb',
204 + 'shortcode_desc' => __( 'Comma-separated list of specific achievement IDs to include.', 'gamipress' ),
205 + 'type' => 'advanced_select',
206 + 'multiple' => true,
207 + 'classes' => 'gamipress-post-selector',
208 + 'attributes' => array(
209 + 'data-post-type' => implode( ',', gamipress_get_achievement_types_slugs() ),
210 + 'data-placeholder' => __( 'Select achievements', 'gamipress' ),
211 + ),
212 + 'default' => '',
213 + 'options_cb' => 'gamipress_options_cb_posts'
214 + ),
215 + 'exclude' => array(
216 + 'name' => __( 'Exclude', 'gamipress' ),
217 + 'tooltip' => __( 'Achievements to exclude.', 'gamipress' ),
218 + 'label_cb' => 'cmb_tooltip_label_cb',
219 + 'shortcode_desc' => __( 'Comma-separated list of specific achievement IDs to exclude.', 'gamipress' ),
220 + 'type' => 'advanced_select',
221 + 'multiple' => true,
222 + 'classes' => 'gamipress-post-selector',
223 + 'attributes' => array(
224 + 'data-post-type' => implode( ',', gamipress_get_achievement_types_slugs() ),
225 + 'data-placeholder' => __( 'Select achievements', 'gamipress' ),
226 + ),
227 + 'default' => '',
228 + 'options_cb' => 'gamipress_options_cb_posts'
229 + ),
230 + 'wpms' => array(
231 + 'name' => __( 'Include Multisite Achievements', 'gamipress' ),
232 + 'tooltip' => __( 'Show achievements from all network sites.', 'gamipress' ),
233 + 'label_cb' => 'cmb_tooltip_label_cb',
234 + 'type' => 'checkbox',
235 + 'classes' => 'gamipress-switch',
236 + ),
237 + ), $achievement_fields ),
238 + ) );
239 +
240 +}
241 +add_action( 'init', 'gamipress_register_achievements_shortcode' );
242 +
243 +/**
244 + * Achievement List Shortcode
245 + *
246 + * @since 1.0.0
247 + *
248 + * @param array $atts Shortcode attributes
249 + * @param string $content Shortcode content
250 + *
251 + * @return string HTML markup
252 + */
253 +function gamipress_achievements_shortcode( $atts = array(), $content = '' ) {
254 +
255 + global $gamipress_template_args;
256 +
257 + // Initialize GamiPress template args global
258 + $gamipress_template_args = array();
259 +
260 + $shortcode = 'gamipress_achievements';
261 +
262 + $atts = shortcode_atts( array_merge( array(
263 + // Achievements atts
264 + 'type' => 'all',
265 + 'columns' => '1',
266 + 'columns_small' => '1',
267 + 'filter' => 'yes',
268 + 'filter_value' => 'all',
269 + 'search' => 'yes',
270 + 'search_value' => '',
271 + 'load_more' => 'yes',
272 + 'current_user' => 'no',
273 + 'user_id' => '0',
274 + 'limit' => '10',
275 + 'orderby' => 'menu_order',
276 + 'order' => 'ASC',
277 + 'include' => '',
278 + 'exclude' => '',
279 + 'wpms' => 'no',
280 + ), gamipress_achievement_shortcode_defaults() ), $atts, $shortcode );
281 +
282 + // Single type check to use dynamic template
283 + $is_single_type = false;
284 + $types = explode( ',', $atts['type'] );
285 +
286 + if ( $atts['type'] !== 'all' && count( $types ) === 1 ) {
287 + $is_single_type = true;
288 + }
289 +
290 + // ---------------------------
291 + // Shortcode Errors
292 + // ---------------------------
293 +
294 + if( $is_single_type ) {
295 +
296 + // Check if achievement type is valid
297 + if ( ! in_array( $atts['type'], gamipress_get_achievement_types_slugs() ) )
298 + return gamipress_shortcode_error( __( 'The type provided isn\'t a valid registered achievement type.', 'gamipress' ), $shortcode );
299 +
300 + } else if( $atts['type'] !== 'all' ) {
301 +
302 + // Let's check if all types provided are wrong
303 + $all_types_wrong = true;
304 +
305 + foreach( $types as $type ) {
306 + if ( in_array( $type, gamipress_get_achievement_types_slugs() ) )
307 + $all_types_wrong = false;
308 + }
309 +
310 + // just notify error if all types are wrong
311 + if( $all_types_wrong )
312 + return gamipress_shortcode_error( __( 'All types provided aren\'t valid registered achievement types.', 'gamipress' ), $shortcode );
313 +
314 + }
315 +
316 + // ---------------------------
317 + // Shortcode Processing
318 + // ---------------------------
319 +
320 + // Enqueue assets
321 + gamipress_enqueue_scripts();
322 +
323 + // Force to set current user as user ID
324 + if( $atts['current_user'] === 'yes' ) {
325 + $atts['user_id'] = get_current_user_id();
326 + } else if( absint( $atts['user_id'] ) === 0 ) {
327 + $atts['user_id'] = get_current_user_id();
328 + }
329 +
330 + // Setup a query args to get the first page of achievements
331 + $query_args = $atts;
332 +
333 + // Initializes filter and search values
334 + $query_args['filter'] = $atts['filter_value'];
335 + $query_args['search'] = isset( $atts['search_value'] ) ? $atts['search_value'] : '';
336 +
337 + $query = gamipress_achievements_shortcode_query( $query_args );
338 +
339 + // GamiPress template args global
340 + // Important! This var need to be set before render the achievements list to prevent get overwritten
341 + // by gamipress_render_achievement() used on gamipress_achievements_shortcode_query()
342 + $gamipress_template_args = $atts;
343 + $gamipress_template_args['query'] = $query;
344 + $gamipress_template_args['types'] = $types;
345 +
346 + // If we're dealing with multiple achievement types
347 + if ( 'all' === $gamipress_template_args['type'] ) {
348 + $gamipress_template_args['plural_label'] = __( 'achievements', 'gamipress' );
349 + } else {
350 + $gamipress_template_args['plural_label'] = ( 1 == count( $types ) && ! empty( $types[0] ) ) ? get_post_type_object( $types[0] )->labels->name : __( 'achievements', 'gamipress' );
351 + }
352 +
353 + ob_start();
354 + if( $is_single_type ) {
355 + gamipress_get_template_part( 'achievements', $atts['type'] );
356 + } else {
357 + gamipress_get_template_part( 'achievements' );
358 + }
359 + $output = ob_get_clean();
360 +
361 + /**
362 + * Filter to override shortcode output
363 + *
364 + * @since 1.6.5
365 + *
366 + * @param string $output Final output
367 + * @param array $atts Shortcode attributes
368 + * @param string $content Shortcode content
369 + */
370 + return apply_filters( 'gamipress_achievements_shortcode_output', $output, $atts, $content );
371 +
372 +}
373 +
374 +/**
375 + * Achievement List Shortcode Query
376 + *
377 + * @since 1.4.5
378 + *
379 + * @param array $args
380 + *
381 + * @return array
382 + */
383 +function gamipress_achievements_shortcode_query( $args = array() ) {
384 +
385 + // Setup our AJAX query vars
386 + $type = isset( $args['type'] ) ? $args['type'] : false;
387 + $limit = isset( $args['limit'] ) ? $args['limit'] : false;
388 + $offset = isset( $args['offset'] ) ? $args['offset'] : false;
389 + $filter = isset( $args['filter'] ) ? $args['filter'] : false;
390 + $search = isset( $args['search'] ) ? $args['search'] : false;
391 + $current_user = isset( $args['current_user'] ) ? $args['current_user'] : false;
392 + $user_id = isset( $args['user_id'] ) ? $args['user_id'] : false;
393 + $orderby = isset( $args['orderby'] ) ? $args['orderby'] : false;
394 + $order = isset( $args['order'] ) ? $args['order'] : false;
395 + $wpms = isset( $args['wpms'] ) ? $args['wpms'] : false;
396 + $include = isset( $args['include'] ) ? $args['include'] : array();
397 + $exclude = isset( $args['exclude'] ) ? $args['exclude'] : array();
398 + $showed_ids = isset( $args['showed_ids'] ) ? $args['showed_ids'] : array();
399 +
400 + // On network wide active installs, we need to switch to main blog mostly for posts permalinks and thumbnails
401 + $blog_id = gamipress_switch_to_main_site_if_network_wide_active();
402 +
403 + // Sanitization
404 + $limit = absint( $limit );
405 + $offset = absint( $offset );
406 + $order = gamipress_validate_from_array( strtoupper( $order ), array( 'ASC', 'DESC' ), 'DESC' );
407 +
408 + // Turn no attributes to false
409 + if( $current_user === 'no' )
410 + $current_user = false;
411 +
412 + if( $wpms === 'no' )
413 + $wpms = false;
414 +
415 + // Force to set current user as user ID
416 + if( $current_user ) $user_id = get_current_user_id();
417 +
418 + // Get the current user if one wasn't specified
419 + if( ! $user_id ) $user_id = get_current_user_id();
420 +
421 + // Ensure user ID as int
422 + $user_id = absint( $user_id );
423 +
424 + // Setup template vars
425 + $template_args = array(
426 + 'user_id' => $user_id, // User ID on achievement is used to meet to which user apply earned checks
427 + );
428 +
429 + $achievement_fields = GamiPress()->shortcodes['gamipress_achievement']->fields;
430 +
431 + unset( $achievement_fields['id'] );
432 +
433 + // Loop achievement shortcode fields to pass them to the achievement template
434 + foreach( $achievement_fields as $field_id => $field_args ) {
435 + if( isset( $args[$field_id] ) )
436 + $template_args[$field_id] = $args[$field_id];
437 + }
438 +
439 + // Convert $type to properly support multiple achievement types
440 + if ( $type === 'all') {
441 + $type = gamipress_get_achievement_types_slugs();
442 + } else {
443 + $type = explode( ',', $type );
444 + }
445 +
446 + // Prevent empty strings to be turned an array by explode()
447 + if ( ! is_array( $include ) && empty( $include ) ) {
448 + $include = array();
449 + }
450 +
451 + // Build $exclude array
452 + if ( ! is_array( $exclude ) && empty( $exclude ) ) {
453 + $exclude = array();
454 + }
455 +
456 + // Build $include array
457 + if ( ! is_array( $include ) ) {
458 + $include = explode( ',', $include );
459 + }
460 +
461 + // Build $exclude array
462 + if ( ! is_array( $exclude ) ) {
463 + $exclude = explode( ',', $exclude );
464 + }
465 +
466 + // Initialize our output and counters
467 + $achievements = '';
468 + $achievement_count = 0;
469 + $query_count = 0;
470 +
471 + // Grab our hidden achievements (used to filter the query)
472 + $hidden = gamipress_get_hidden_achievement_ids( $type );
473 +
474 + if( $wpms && $wpms !== 'no' ) {
475 + // If we're polling all sites, grab an array of site IDs
476 + $sites = gamipress_get_network_site_ids();
477 + } else {
478 + // Otherwise, use only the current site
479 + $sites = array( get_current_blog_id() );
480 + }
481 +
482 + // On network wide active installs, force to just loop main site
483 + if( gamipress_is_network_wide_active() )
484 + $sites = array( get_main_site_id() );
485 +
486 + // Loop through each site (default is current site only)
487 + foreach( $sites as $site_blog_id ) {
488 +
489 + // If we're not polling the current site, switch to the site we're polling
490 + $current_site_blog_id = get_current_blog_id();
491 +
492 + if ( $current_site_blog_id != $site_blog_id )
493 + switch_to_blog( $site_blog_id );
494 +
495 + // Grab user earned achievements (used to filter the query)
496 + $earned_ids = gamipress_get_user_earned_achievement_ids( $user_id, $type );
497 +
498 + // If filter is set to load earned achievements and user hasn't earned anything, don't need to continue
499 + if( ! ( $filter === 'completed' && empty( $earned_ids ) ) ) {
500 +
501 + // Query Achievements
502 + $query_args = array(
503 + 'post_type' => $type,
504 + 'orderby' => $orderby,
505 + 'order' => $order,
506 + 'posts_per_page' => $limit,
507 + 'offset' => $offset,
508 + 'post_status' => 'publish',
509 + 'post__in' => array(),
510 + 'post__not_in' => array_diff( $hidden, $earned_ids )
511 + );
512 +
513 + // Filter - query completed or non completed achievements
514 + if( $filter === 'completed' && ! empty( $earned_ids ) ) {
515 + // Include earned achievements
516 + $query_args[ 'post__in' ] = $earned_ids;
517 + } else if( $filter === 'not-completed' && ! empty( $earned_ids ) ) {
518 + // Exclude earned achievements
519 + $query_args[ 'post__not_in' ] = array_merge( $hidden, $earned_ids );
520 + }
521 +
522 + // Include certain achievements
523 + if( ! empty( $include ) ) {
524 + $query_args[ 'post__not_in' ] = array_diff( $query_args[ 'post__not_in' ], $include );
525 + $query_args[ 'post__in' ] = array_merge( $query_args[ 'post__in' ], $include );
526 + }
527 +
528 + // Exclude certain achievements
529 + if( ! empty( $exclude ) ) {
530 + $query_args[ 'post__not_in' ] = array_merge( $query_args[ 'post__not_in' ], $exclude );
531 + }
532 +
533 + // Search
534 + if( $search ) {
535 + $query_args[ 's' ] = $search;
536 + }
537 +
538 + // Order By
539 + if( in_array( $orderby, array( 'points_awarded', 'points_to_unlock' ) ) ) {
540 + $query_args['meta_key'] = ( $orderby === 'points_awarded' ? '_gamipress_points' : '_gamipress_points_to_unlock' );
541 + $query_args['orderby'] = 'meta_value_num';
542 + }
543 +
544 + // Process already displayed achievements
545 + if( ! empty( $showed_ids ) ) {
546 + // Exclude already displayed achievements
547 + $query_args[ 'post__in' ] = array_diff( $query_args[ 'post__in' ], $showed_ids );
548 + $query_args[ 'post__not_in' ] = array_merge( $query_args[ 'post__not_in' ], $showed_ids );
549 + // Offset not needed since displayed post are getting already excluded
550 + unset( $query_args['offset'] );
551 + }
552 +
553 + // Prevent to display posts excluded
554 + if( ! empty( $query_args[ 'post__in' ] ) && ! empty( $query_args[ 'post__not_in' ] ) ) {
555 + $query_args[ 'post__in' ] = array_diff( $query_args[ 'post__in' ], $query_args[ 'post__not_in' ] );
556 + }
557 +
558 + /**
559 + * Filters achievements list query args
560 + *
561 + * @since 1.5.9
562 + *
563 + * @param array $query_args Query args to be passed to WP_Query
564 + * @param array $args Function received args (Note: to pass your own args on achievements list request, check JS event 'gamipress_achievements_list_request_data')
565 + *
566 + * @return array
567 + */
568 + $query_args = apply_filters( 'gamipress_achievements_shortcode_query_args', $query_args, $args );
569 +
570 + // Query achievements
571 + $achievement_posts = new WP_Query( $query_args );
572 + $query_count = absint( $achievement_posts->found_posts );
573 +
574 + // Add displayed post to the count since they have been excluded on the query
575 + if( ! empty( $showed_ids ) )
576 + $query_count += count( $showed_ids );
577 +
578 + // Loop achievements found
579 + while( $achievement_posts->have_posts() ) : $achievement_posts->the_post();
580 + // Render the achievement passing the template args
581 + $achievements .= gamipress_render_achievement( get_the_ID(), $template_args );
582 + $achievement_count++;
583 + endwhile;
584 +
585 + }
586 +
587 + // Display a message for no results
588 + if( empty( $achievements ) && $offset === 0 ) {
589 +
590 + $current = current( $type );
591 +
592 + // If we have exactly one achievement type, get its plural name, otherwise use "achievements"
593 + $post_type_plural = ( count( $type ) == 1 && ! empty( $current ) ) ? gamipress_get_achievement_type_plural( $current ) : __( 'achievements' , 'gamipress' );
594 +
595 + // Setup our completion message
596 + $achievements .= '<div class="gamipress-no-results">';
597 +
598 + if ( 'completed' === $filter )
599 + $no_results_text = sprintf( __( 'No completed %s to display.', 'gamipress' ), strtolower( $post_type_plural ) );
600 + else if ( 'not-completed' === $filter )
601 + $no_results_text = sprintf( __( 'You completed all %s.', 'gamipress' ), strtolower( $post_type_plural ) );
602 + else
603 + $no_results_text = sprintf( __( 'No %s to display.', 'gamipress' ), strtolower( $post_type_plural ) );
604 +
605 + /**
606 + * Filter achievements no results text
607 + *
608 + * @since 1.0.0
609 + *
610 + * @param string $no_results_text
611 + *
612 + * @return string
613 + */
614 + $no_results_text = apply_filters( 'gamipress_achievements_no_results_text', $no_results_text );
615 +
616 + $achievements .= '<p>' . $no_results_text . '</p>';
617 +
618 + $achievements .= '</div><!-- .gamipress-no-results -->';
619 + }
620 +
621 + // Come back to current blog
622 + if( $current_site_blog_id != $site_blog_id && is_multisite() )
623 + restore_current_blog();
624 +
625 + }
626 +
627 + // If switched to blog, return back to que current blog
628 + if( $blog_id !== get_current_blog_id() && is_multisite() )
629 + restore_current_blog();
630 +
631 + $query = array(
632 + 'achievements' => $achievements,
633 + 'offset' => $offset + $limit,
634 + 'query_count' => $query_count,
635 + 'achievement_count' => $achievement_count,
636 + );
637 +
638 + /**
639 + * Filter the achievements query
640 + *
641 + * @since 1.6.5
642 + *
643 + * @param array $response
644 + * @param array $args
645 + *
646 + * @return array
647 + */
648 + return apply_filters( 'gamipress_achievements_shortcode_query', $query, $args );
649 +
650 +}