PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 7.9.5
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v7.9.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
gamipress / includes / admin / meta-boxes / requirements-ui.php

requirements-ui.php in GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI 7.9.5, at includes/admin/meta-boxes/requirements-ui.php

1,409 lines 63.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Requirements UI
4 *
5 * @package GamiPress\Admin\Requirements_UI
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 * Add requirements meta boxes
14 *
15 * @since 1.0.5
16 *
17 * @return void
18 */
19 function gamipress_add_requirements_ui_meta_box() {
20
21 // Points Awards
22 add_meta_box( 'gamipress-requirements-ui-points-award', __( 'Automatic Points Awards', 'gamipress' ), 'gamipress_requirements_ui_meta_box', 'points-type', 'advanced', 'default', array( 'requirement_type' => 'points-award' ) );
23
24 // Points Deductions
25 add_meta_box( 'gamipress-requirements-ui-points-deduct', __( 'Automatic Points Deductions', 'gamipress' ), 'gamipress_requirements_ui_meta_box', 'points-type', 'advanced', 'default', array( 'requirement_type' => 'points-deduct' ) );
26
27 // Steps
28 foreach ( gamipress_get_achievement_types_slugs() as $achievement_type ) {
29 add_meta_box( 'gamipress-requirements-ui', __( 'Required Steps', 'gamipress' ), 'gamipress_requirements_ui_meta_box', $achievement_type, 'advanced', 'default', array( 'requirement_type' => 'step' ) );
30 }
31
32 // Rank Requirements
33 foreach ( gamipress_get_rank_types_slugs() as $rank_type ) {
34 add_meta_box( 'gamipress-requirements-ui', __( 'Rank Requirements', 'gamipress' ), 'gamipress_requirements_ui_meta_box', $rank_type, 'advanced', 'default', array( 'requirement_type' => 'rank-requirement' ) );
35 }
36
37 }
38 add_action( 'add_meta_boxes', 'gamipress_add_requirements_ui_meta_box' );
39
40 /**
41 * Renders the HTML for meta box, refreshes whenever a new requirement is added
42 *
43 * @since 1.0.5
44 * @updated 1.3.7 Added $metabox
45 *
46 * @param WP_Post $post The current post object.
47 * @param array $metabox With metabox id, title, callback, and args elements.
48 *
49 * @return void
50 */
51 function gamipress_requirements_ui_meta_box( $post = null, $metabox = array() ) {
52
53 // Define the requirement type to use
54 $requirement_type = gamipress_requirements_ui_get_requirement_type( $post, $metabox );
55
56 // If is lowest priority rank then show a notice and prevent to show requirements UI
57 if( $requirement_type === 'rank-requirement' ) {
58
59 if( ( $post->post_status === 'auto-draft' && gamipress_get_rank_priority( $post->ID ) === 1 )
60 || ( $post->post_status !== 'auto-draft' && gamipress_is_lowest_priority_rank( $post->ID ) ) ) {
61
62 echo '<p>' .
63 __( 'The rank with the lowest priority is set as default rank for all users so this rank should be created without requirements.', 'gamipress' )
64 . '<br>'
65 . __( 'You will be able to set requirements on next ranks. After save this rank, if it is not configured as the lowest priority you will be able to edit the requirements again.', 'gamipress' )
66 . '</p>';
67 return;
68
69 }
70 }
71
72 // Setup the requirement object based on the requirement type
73 $requirement_types = gamipress_get_requirement_types();
74 $requirement_type_object = $requirement_types[$requirement_type];
75
76 // Get assigned requirements
77 $assigned_requirements = gamipress_get_assigned_requirements( $post->ID, $requirement_type, 'any' );
78
79 if( ! $assigned_requirements ) {
80 $assigned_requirements = array();
81 }
82
83 // Sort the requirements by their order
84 uasort( $assigned_requirements, 'gamipress_compare_requirements_order' );
85
86 switch( $requirement_type ) {
87 case 'points-award':
88 echo '<p>' .
89 __( 'Define the automatic ways a user could retrieve an amount of this points type. Use the "Label" field to optionally customize the titles of each one.', 'gamipress' )
90 . '</p>';
91 break;
92 case 'points-deduct':
93 echo '<p>' .
94 __( 'Define the automatic ways a user could lose an amount of this points type. Use the "Label" field to optionally customize the titles of each one.', 'gamipress' )
95 . '</p>';
96 break;
97 case 'step':
98 echo '<p>' .
99 __( 'Define the required "steps" for this achievement to be considered complete. Use the "Label" field to optionally customize the titles of each step.', 'gamipress' )
100 . '</p>';
101 break;
102 case 'rank-requirement':
103 echo '<p>' .
104 __( 'Define the required requirements for this rank to be considered that user is ranked on it. Use the "Label" field to optionally customize the titles of each requirement.', 'gamipress' )
105 . '<br>'
106 . __( '<strong>Important!</strong> User will not earn this requirements until be ranked on the previous rank.', 'gamipress' )
107 . '</p>';
108 break;
109 }
110
111 // Sequential input
112 if( in_array( $requirement_type, array( 'step', 'rank-requirement' ) ) ) : ?>
113
114 <?php wp_nonce_field( '_gamipress_sequential_' . $post->ID, '_gamipress_sequential_nonce' ); ?>
115
116 <label for="_gamipress_sequential">
117 <strong><?php echo ( $requirement_type === 'step'
118 ? __( 'Sequential Steps', 'gamipress' )
119 : __( 'Sequential Requirements', 'gamipress' )
120 ); ?></strong>
121 </label>
122
123 <div class="gamipress-switch gamipress-switch-small gamipress-requirements-sequential">
124 <input type="checkbox" id="_gamipress_sequential" name="_gamipress_sequential" <?php checked( true, (bool) gamipress_get_post_meta( $post->ID, '_gamipress_sequential' ) ); ?> value="on">
125 <label for="_gamipress_sequential"><?php echo ( $requirement_type === 'step'
126 ? __( 'Check this option to force users to complete steps in order.', 'gamipress' )
127 : __( 'Check this option to force users to complete requirements in order.', 'gamipress' )
128 ); ?></label>
129 </div>
130
131 <?php endif;
132
133 do_action( 'gamipress_before_requirements_list', $requirement_type, $requirement_type_object, $assigned_requirements );
134
135 // Concatenate our requirements output
136 echo '<ul id="requirements-list" class="requirements-list">';
137 foreach ( $assigned_requirements as $requirement ) {
138 gamipress_requirement_ui_html( $requirement->ID, $post->ID );
139 }
140 echo '</ul>';
141
142 // Render the add and save buttons ?>
143 <div class="button gamipress-button-success gamipress-add-requirement" data-post-id="<?php echo $post->ID; ?>" data-requirement-type="<?php echo $requirement_type; ?>">
144 <span class="dashicons dashicons-plus"></span><?php printf( __( 'Add New %s', 'gamipress' ), $requirement_type_object['singular_name'] ); ?>
145 </div>
146 <div class="button-primary gamipress-save-requirements">
147 <span class="dashicons dashicons-saved"></span><?php printf( __( 'Save All %s', 'gamipress' ), $requirement_type_object['plural_name'] ); ?>
148 </div>
149 <span class="spinner requirements-spinner"></span>
150 <?php
151 }
152
153 /**
154 * Return post assigned requirements
155 *
156 * @since 1.0.0
157 * @updated 1.5.1 Added $post_status parameter
158 *
159 * @param int $post_id
160 * @param string $requirement_type
161 * @param string $post_status
162 *
163 * @return array|bool
164 */
165 function gamipress_get_assigned_requirements( $post_id = null, $requirement_type = '', $post_status = 'publish' ) {
166
167 // If not properly upgrade to required version fallback to compatibility function
168 if( ! is_gamipress_upgraded_to( '1.5.1' ) ) {
169 return gamipress_get_assigned_requirements_old( $post_id, $requirement_type, $post_status );
170 }
171
172 global $post;
173
174 if( $post_id === null ) {
175 $post_id = $post->ID;
176 }
177
178 // Grab post's requirements
179 return get_posts( array(
180 'post_type' => $requirement_type,
181 'post_parent' => $post_id,
182 'post_status' => $post_status,
183 'orderby' => 'menu_order',
184 'order' => 'ASC',
185 'posts_per_page' => -1,
186 'suppress_filters' => false,
187 ) );
188
189 }
190
191 /**
192 * Helper function for generating the HTML output for configuring a given requirement
193 *
194 * @since 1.0.5
195 *
196 * @param integer $requirement_id The given requirement's ID
197 * @param integer $post_id The given requirement's parent $post ID
198 *
199 * @return string The concatenated HTML input for the requirement
200 */
201 function gamipress_requirement_ui_html( $requirement_id = 0, $post_id = 0 ) {
202
203 // Grab our requirement's requirements and measurement
204 $requirements = gamipress_get_requirement_object( $requirement_id );
205 $requirement_type = gamipress_get_post_type( $requirement_id );
206 $status = gamipress_get_post_status( $requirement_id );
207 $count = ! empty( $requirements['count'] ) ? $requirements['count'] : 1;
208 $limit = ! empty( $requirements['limit'] ) ? $requirements['limit'] : 1;
209 $limit_type = ! empty( $requirements['limit_type'] ) ? $requirements['limit_type'] : 'unlimited';
210
211 // Setup the requirement object based on the requirement type
212 $requirement_types = gamipress_get_requirement_types();
213 $requirement_type_object = $requirement_types[$requirement_type];
214 ?>
215
216 <li class="requirement-row requirement-<?php echo $requirement_id; ?> <?php echo ( $status === 'publish' ? 'requirement-published' : '' ); ?>" data-requirement-id="<?php echo $requirement_id; ?>">
217
218 <?php
219 /**
220 * Available action to add custom HTML at top of the requirement HTML
221 *
222 * @since 1.0.0
223 *
224 * @param int $requirement_id The requirement ID
225 * @param int $post_id The post ID where requirements are displayed
226 */
227 do_action( 'gamipress_requirement_ui_html_requirement_top', $requirement_id, $post_id ); ?>
228
229 <input type="hidden" name="requirement_id" value="<?php echo $requirement_id; ?>" />
230 <input type="hidden" name="requirement_type" value="<?php echo $requirement_type; ?>" />
231 <input type="hidden" name="post_id" value="<?php echo $post_id; ?>" />
232 <input type="hidden" name="order" value="<?php echo absint( gamipress_get_requirement_menu_order( $requirement_id ) ); ?>" />
233
234 <div class="requirement-header">
235
236 <div class="requirement-header-title">
237 <strong><?php echo get_the_title( $requirement_id ); ?></strong>
238 </div>
239
240 <div class="requirement-actions">
241
242 <?php $change_status_title = ( $status === 'publish' ? __( 'Disable %s', 'gamipress' ) : __( 'Enable %s', 'gamipress' ) ) ?>
243
244 <div class="requirement-action requirement-action-change-status"
245 title="<?php echo sprintf( $change_status_title, $requirement_type_object['singular_name'] ); ?>"
246 data-enabled-title="<?php echo sprintf( __( 'Disable %s', 'gamipress' ), $requirement_type_object['singular_name'] ); ?>"
247 data-disabled-title="<?php echo sprintf( __( 'Enable %s', 'gamipress' ), $requirement_type_object['singular_name'] ); ?>"
248 >
249 <div class="gamipress-switch gamipress-switch-small">
250 <input type="checkbox" id="requirement-action-change-status-input-<?php echo $requirement_id; ?>" <?php checked( 'publish', $status ) ?> />
251 <label for="requirement-action-change-status-input-<?php echo $requirement_id; ?>"></label>
252 </div>
253 </div>
254
255 <?php
256
257 // Setup the default requirement actions
258 $requirement_actions = array(
259 'duplicate' => array(
260 'label' => __( 'Duplicate', 'gamipress' ),
261 'icon' => 'dashicons-admin-page',
262 ),
263 'delete' => array(
264 'label' => __( 'Delete', 'gamipress' ),
265 'icon' => 'dashicons-trash',
266 )
267 );
268
269 /**
270 * Available filter to add custom requirement actions
271 *
272 * @since 1.4.6
273 *
274 * @param array $requirement_actions
275 */
276 $requirement_actions = apply_filters( 'gamipress_requirement_ui_requirement_actions', $requirement_actions );
277
278 foreach( $requirement_actions as $requirement_action => $requirement_action_args ) : ?>
279
280 <div class="requirement-action requirement-action-<?php echo $requirement_action; ?>" title="<?php echo $requirement_action_args['label']; ?>">
281 <span class="dashicons <?php echo $requirement_action_args['icon']; ?>"></span>
282 </div>
283
284 <?php endforeach; ?>
285
286 </div>
287
288 </div>
289
290 <?php
291 /**
292 * Available action to add custom HTML after the requirement header
293 *
294 * @since 1.0.0
295 *
296 * @param int $requirement_id The requirement ID
297 * @param int $post_id The post ID where requirements are displayed
298 */
299 do_action( 'gamipress_requirement_ui_html_after_requirement_header', $requirement_id, $post_id ); ?>
300
301 <label for="select-trigger-type-<?php echo $requirement_id; ?>"><?php _e( 'When', 'gamipress' ); ?>:</label>
302
303 <?php
304 /**
305 * Available action to add custom HTML after requirement text
306 *
307 * @since 1.0.0
308 *
309 * @param int $requirement_id The requirement ID
310 * @param int $post_id The post ID where requirements are displayed
311 */
312 do_action( 'gamipress_requirement_ui_html_after_require_text', $requirement_id, $post_id ); ?>
313
314 <select id="select-trigger-type-<?php echo $requirement_id; ?>" class="select-trigger-type" data-requirement-id="<?php echo $requirement_id; ?>">
315 <?php
316 $activity_triggers = gamipress_get_activity_triggers();
317 ksort( $activity_triggers );
318
319 // Grouped activity triggers
320 foreach ( $activity_triggers as $group => $group_triggers ) : ?>
321 <optgroup label="<?php echo esc_attr( $group ); ?>">
322 <?php foreach( $group_triggers as $trigger => $label ) : ?>
323 <option value="<?php echo esc_attr( $trigger ); ?>" <?php selected( $requirements['trigger_type'], $trigger, true ); ?>><?php echo $label; ?></option>
324 <?php endforeach; ?>
325 </optgroup>
326 <?php endforeach; ?>
327 </select>
328
329 <?php
330 /**
331 * Available action to add custom HTML after trigger type
332 *
333 * @since 1.0.0
334 *
335 * @param int $requirement_id The requirement ID
336 * @param int $post_id The post ID where requirements are displayed
337 */
338 do_action( 'gamipress_requirement_ui_html_after_trigger_type', $requirement_id, $post_id ); ?>
339
340 <?php
341 $points_conditions = gamipress_number_condition_options(); ?>
342
343 <select class="select-points-condition select-points-condition-<?php echo $requirement_id; ?>">
344 <?php foreach ( $points_conditions as $value => $label ) :
345 echo '<option value="' . $value . '" ' . selected( $requirements['points_condition'], $value, false ) . '>' . $label . '</option>';
346 endforeach; ?>
347 </select>
348
349 <?php
350 /**
351 * Available action to add custom HTML after points condition
352 *
353 * @since 1.0.0
354 *
355 * @param int $requirement_id The requirement ID
356 * @param int $post_id The post ID where requirements are displayed
357 */
358 do_action( 'gamipress_requirement_ui_html_after_points_condition', $requirement_id, $post_id ); ?>
359
360 <input type="number" name="requirement-points-required" id="requirement-<?php echo $requirement_id; ?>-points-required" class="points-required" value="<?php echo ( $requirements['points_required'] === 0 ? 1 : $requirements['points_required'] ); ?>" />
361
362 <?php
363 /**
364 * Available action to add custom HTML after points required
365 *
366 * @since 1.0.0
367 *
368 * @param int $requirement_id The requirement ID
369 * @param int $post_id The post ID where requirements are displayed
370 */
371 do_action( 'gamipress_requirement_ui_html_after_points_required', $requirement_id, $post_id ); ?>
372
373 <input type="text" name="requirement-meta-key-required" id="requirement-<?php echo $requirement_id; ?>-meta-key-required" class="meta-key-required" value="<?php echo esc_attr( $requirements['meta_key_required'] ); ?>" placeholder="<?php echo esc_attr( __( 'Meta key', 'gamipress' ) ); ?>" />
374 <input type="text" name="requirement-meta-value-required" id="requirement-<?php echo $requirement_id; ?>-meta-value-required" class="meta-value-required" value="<?php echo esc_attr( $requirements['meta_value_required'] ); ?>" placeholder="<?php echo esc_attr( __( 'Meta value', 'gamipress' ) ); ?>" />
375
376 <?php
377 /**
378 * Available action to add custom HTML after meta required
379 *
380 * @since 1.0.0
381 *
382 * @param int $requirement_id The requirement ID
383 * @param int $post_id The post ID where requirements are displayed
384 */
385 do_action( 'gamipress_requirement_ui_html_after_meta_required', $requirement_id, $post_id ); ?>
386
387 <select class="select-points-type-required select-points-type-required-<?php echo $requirement_id; ?>">
388 <option value=""><?php _e( 'Choose a points type', 'gamipress'); ?></option>
389 <?php foreach ( gamipress_get_points_types() as $slug => $data ) :
390
391 echo '<option value="' . $slug . '" ' . selected( $requirements['points_type_required'], $slug, false ) . '>' . $data['plural_name'] . '</option>';
392
393 endforeach; ?>
394 </select>
395
396 <?php
397 /**
398 * Available action to add custom HTML after points type required
399 *
400 * @since 1.0.0
401 *
402 * @param int $requirement_id The requirement ID
403 * @param int $post_id The post ID where requirements are displayed
404 */
405 do_action( 'gamipress_requirement_ui_html_after_points_type_required', $requirement_id, $post_id ); ?>
406
407 <select class="select-rank-type-required select-rank-type-required-<?php echo $requirement_id; ?>">
408 <?php foreach ( gamipress_get_rank_types() as $slug => $data ) :
409
410 echo '<option value="' . $slug . '" ' . selected( $requirements['rank_type_required'], $slug, false ) . '>' . $data['singular_name'] . '</option>';
411
412 endforeach; ?>
413 </select>
414
415 <?php
416 /**
417 * Available action to add custom HTML after rank type required
418 *
419 * @since 1.2.0
420 *
421 * @param int $requirement_id The requirement ID
422 * @param int $post_id The post ID where requirements are displayed
423 */
424 do_action( 'gamipress_requirement_ui_html_after_rank_type_required', $requirement_id, $post_id ); ?>
425
426 <select class="select-rank-required select-rank-required-<?php echo $requirement_id; ?>">
427 <option value=""><?php _e( 'Choose a rank', 'gamipress'); ?></option>
428 </select>
429
430 <?php
431 /**
432 * Available action to add custom HTML after rank required
433 *
434 * @since 1.2.0
435 *
436 * @param int $requirement_id The requirement ID
437 * @param int $post_id The post ID where requirements are displayed
438 */
439 do_action( 'gamipress_requirement_ui_html_after_rank_required', $requirement_id, $post_id ); ?>
440
441 <?php $post_types = get_post_types( array( 'public' => true ), 'objects' ); ?>
442
443 <select class="select-post-type-required select-post-type-required-<?php echo $requirement_id; ?>">
444 <option value=""><?php _e( 'Choose a post type', 'gamipress'); ?></option>
445 <?php foreach( $post_types as $post_type => $post_type_args ) : ?>
446 <option value="<?php echo esc_attr( $post_type ); ?>" <?php selected( $requirements['post_type_required'], $post_type ); ?>><?php echo $post_type_args->labels->singular_name ; ?></option>
447 <?php endforeach; ?>
448 </select>
449
450 <?php
451 /**
452 * Available action to add custom HTML after post type field
453 *
454 * @since 1.0.0
455 *
456 * @param int $requirement_id The requirement ID
457 * @param int $post_id The post ID where requirements are displayed
458 */
459 do_action( 'gamipress_requirement_ui_html_after_post_type_required', $requirement_id, $post_id ); ?>
460
461 <select class="select-user-role-required select-user-role-required-<?php echo $requirement_id; ?>">
462 <?php foreach ( gamipress_get_editable_roles() as $role => $details ) :
463
464 echo '<option value="' . $role . '" ' . selected( $requirements['user_role_required'], $role, false ) . '>' . translate_user_role( $details['name'] ) . '</option>';
465
466 endforeach; ?>
467 </select>
468
469 <?php
470 /**
471 * Available action to add custom HTML after user role required
472 *
473 * @since 1.8.8
474 *
475 * @param int $requirement_id The requirement ID
476 * @param int $post_id The post ID where requirements are displayed
477 */
478 do_action( 'gamipress_requirement_ui_html_after_user_role_required', $requirement_id, $post_id ); ?>
479
480 <select class="select-achievement-type select-achievement-type-<?php echo $requirement_id; ?>">
481 <option value=""><?php _e( 'Choose an achievement type', 'gamipress'); ?></option>
482 <?php foreach ( gamipress_get_achievement_types() as $slug => $data ) :
483
484 echo '<option value="' . $slug . '" ' . selected( $requirements['achievement_type'], $slug, false ) . '>' . $data['plural_name'] . '</option>';
485
486 endforeach; ?>
487 </select>
488
489 <?php
490 /**
491 * Available action to add custom HTML after achievement type
492 *
493 * @since 1.0.0
494 *
495 * @param int $requirement_id The requirement ID
496 * @param int $post_id The post ID where requirements are displayed
497 */
498 do_action( 'gamipress_requirement_ui_html_after_achievement_type', $requirement_id, $post_id ); ?>
499
500 <select class="select-achievement-post select-achievement-post-<?php echo $requirement_id; ?>">
501 <option value=""><?php _e( 'Choose an achievement', 'gamipress'); ?></option>
502 </select>
503
504 <?php // For multisite installs, we need to store site ID of attached post ?>
505 <input type="hidden" class="select-post-site-id" value="<?php echo $requirements['achievement_post_site_id']; ?>" />
506
507 <select class="select-post select-post-<?php echo $requirement_id; ?>">
508 <?php if( ! empty( $requirements['achievement_post'] ) ) :
509 $achievement_post_title = gamipress_get_specific_activity_trigger_post_title( $requirements['achievement_post'], $requirements['trigger_type'], $requirements['achievement_post_site_id'] ); ?>
510 <option value="<?php esc_attr_e( $requirements['achievement_post'] ); ?>" selected="selected"><?php echo $achievement_post_title; ?> (#<?php echo $requirements['achievement_post']; ?>)</option>
511 <?php endif; ?>
512 </select>
513
514 <?php
515 /**
516 * Available action to add custom HTML after achievement post field
517 *
518 * @since 1.0.0
519 *
520 * @param int $requirement_id The requirement ID
521 * @param int $post_id The post ID where requirements are displayed
522 */
523 do_action( 'gamipress_requirement_ui_html_after_achievement_post', $requirement_id, $post_id ); ?>
524
525 <input class="count" type="number" min="1" value="<?php echo $count; ?>" placeholder="1">
526 <span class="count-text"><?php _e( 'time(s)', 'gamipress' ); ?></span>
527
528 <?php do_action( 'gamipress_requirement_ui_html_after_count', $requirement_id, $post_id ); ?>
529
530 <span class="limit-text"><?php _e( 'limited to', 'gamipress' ); ?></span>
531 <input class="limit" type="number" min="1" value="<?php echo $limit; ?>" placeholder="1">
532 <?php
533 $limit_intervals = array(
534 'unlimited' => __( 'Unlimited', 'gamipress' ),
535 'minutely' => __( 'Per minute', 'gamipress' ),
536 'hourly' => __( 'Per hour', 'gamipress' ),
537 'daily' => __( 'Per day', 'gamipress' ),
538 'weekly' => __( 'Per week', 'gamipress' ),
539 'monthly' => __( 'Per month', 'gamipress' ),
540 'yearly' => __( 'Per year', 'gamipress' ),
541 );
542
543 /**
544 * Filter available to override limit intervals available
545 *
546 * @since 1.9.0
547 *
548 * @param array $limit_intervals Default limit intervals (unlimited, hourly, daily, weekly, monthly and yearly)
549 * @param int $requirement_id The requirement ID
550 * @param int $post_id The post ID where requirements are displayed
551 *
552 * @return array
553 */
554 $limit_intervals = apply_filters( 'gamipress_requirement_limit_intervals', $limit_intervals, $requirement_id, $post_id );
555 ?>
556 <select class="limit-type">
557 <?php foreach( $limit_intervals as $limit_interval => $limit_interval_label ) : ?>
558 <option value="<?php echo $limit_interval; ?>" <?php selected( $limit_type, $limit_interval ); ?>><?php echo $limit_interval_label; ?></option>
559 <?php endforeach; ?>
560 </select>
561
562 <?php
563 /**
564 * Available action to add custom HTML after requirement limit
565 *
566 * @since 1.0.0
567 *
568 * @param int $requirement_id The requirement ID
569 * @param int $post_id The post ID where requirements are displayed
570 */
571 do_action( 'gamipress_requirement_ui_html_after_limit', $requirement_id, $post_id ); ?>
572
573 <?php // Required points fields
574 if( in_array( $requirement_type, array( 'points-award', 'points-deduct' ) ) ) :
575 $points = ! empty( $requirements['points'] ) ? $requirements['points'] : 1;
576 $points_singular_name = get_post_field( 'post_title', $post_id );
577 $post_name = get_post_field( 'post_name', $post_id );
578 $points_type = $requirements['points_type'];
579 $maximum_earnings = absint( $requirements['maximum_earnings'] );
580
581 // Ensure points type is properly set, if not force update it
582 if( $points_type !== $post_name ) {
583 update_post_meta( $requirement_id, '_gamipress_points_type', $post_name );
584 $points_type = $post_name;
585 }
586
587 if( ! $points_singular_name ) {
588 $points_singular_name = __( 'point(s)', 'gamipress' );
589 } else {
590 $points_singular_name = strtolower( $points_singular_name . '(s)' );
591 }
592 ?>
593 <div class="requirement-awards">
594 <label for="requirement-<?php echo $requirement_id; ?>-points"><?php echo ( $requirement_type === 'points-award' ? __( 'Earn', 'gamipress' ) : __( 'Deduct', 'gamipress' ) ); ?>:</label>
595 <input type="number" name="requirement-points" id="requirement-<?php echo $requirement_id; ?>-points" class="points" value="<?php echo $points; ?>" />
596 <span class="points-text"><?php echo $points_singular_name; ?></span>
597 <input type="hidden" name="points_type" value="<?php echo $points_type; ?>">
598
599
600 <span class="maximum-earnings-text"><?php echo ( $requirement_type === 'points-award' ? __( 'with a maximum number of times to earn it of', 'gamipress' ) : __( 'with a maximum number of times to deduct it of', 'gamipress' ) ); ?></span>
601 <input type="number" min="0" name="requirement-maximum-earnings" id="requirement-<?php echo $requirement_id; ?>-maximum-earnings" class="maximum-earnings" value="<?php echo $maximum_earnings; ?>" />
602 <span class="maximum-earnings-notice"><?php _e( '(0 for no maximum)', 'gamipress' ); ?></span>
603 </div>
604
605 <?php
606 /**
607 * Available action to add custom HTML after requirement points ( just available for points awards and deducts )
608 *
609 * @since 1.0.0
610 *
611 * @param int $requirement_id The requirement ID
612 * @param int $post_id The post ID where requirements are displayed
613 */
614 do_action( 'gamipress_requirement_ui_html_after_points', $requirement_id, $post_id ); ?>
615 <?php endif; ?>
616
617 <?php // Optional field
618 if( in_array( $requirement_type, array( 'step', 'rank-requirement' ) ) ) :
619 $optional = (bool) $requirements['optional'];
620 ?>
621 <div class="requirement-clear"></div>
622 <div class="requirement-optional">
623 <label for="requirement-<?php echo $requirement_id; ?>-optional"><?php _e( 'Optional', 'gamipress' ); ?>:</label>
624 <select class="select-optional select-optional-<?php echo $requirement_id; ?>">
625 <option value="0" <?php selected( false, $optional ); ?>><?php _e( 'Required', 'gamipress'); ?></option>
626 <option value="1" <?php selected( true, $optional ); ?>><?php _e( 'Optional', 'gamipress'); ?></option>
627 </select>
628 </div>
629
630 <?php
631 /**
632 * Available action to add custom HTML after requirement optional ( just available for steps and rank requirements )
633 *
634 * @since 1.0.0
635 *
636 * @param int $requirement_id The requirement ID
637 * @param int $post_id The post ID where requirements are displayed
638 */
639 do_action( 'gamipress_requirement_ui_html_after_optional', $requirement_id, $post_id ); ?>
640 <?php endif; ?>
641
642 <div class="requirement-title">
643 <label for="requirement-<?php echo $requirement_id; ?>-title"><?php _e( 'Label', 'gamipress' ); ?>:</label>
644 <input type="text" name="requirement-title" id="requirement-<?php echo $requirement_id; ?>-title" class="title" value="<?php echo esc_attr( get_the_title( $requirement_id ) ); ?>" placeholder="<?php echo esc_attr( __( 'Enter the label here or leave it empty to be autogenerated...', 'gamipress' ) ); ?>" />
645 </div>
646
647 <div class="requirement-url">
648 <label for="requirement-<?php echo $requirement_id; ?>-url"><?php _e( 'URL', 'gamipress' ); ?>:</label>
649 <input type="text" id="requirement-<?php echo $requirement_id; ?>-url" class="url" value="<?php echo esc_attr( $requirements['url'] ); ?>" placeholder="https://..." />
650 </div>
651
652 <?php
653 /**
654 * Available action to add custom HTML after requirement URL
655 *
656 * @since 1.0.0
657 *
658 * @param int $requirement_id The requirement ID
659 * @param int $post_id The post ID where requirements are displayed
660 */
661 do_action( 'gamipress_requirement_ui_html_after_requirement_url', $requirement_id, $post_id ); ?>
662
663 <?php // TODO: Keep here for backward compatibility
664 /**
665 * Available action to add custom HTML after requirement title
666 *
667 * @since 1.0.0
668 *
669 * @param int $requirement_id The requirement ID
670 * @param int $post_id The post ID where requirements are displayed
671 */
672 do_action( 'gamipress_requirement_ui_html_after_requirement_title', $requirement_id, $post_id ); ?>
673
674 <?php
675 /**
676 * Available action to add custom HTML at bottom of the requirement HTML
677 *
678 * @since 1.0.0
679 *
680 * @param int $requirement_id The requirement ID
681 * @param int $post_id The post ID where requirements are displayed
682 */
683 do_action( 'gamipress_requirement_ui_html_requirement_bottom', $requirement_id, $post_id ); ?>
684
685 </li>
686 <?php
687 }
688
689 /**
690 * Define the requirement type to use
691 *
692 * @since 1.3.1
693 *
694 * @param WP_Post $post
695 * @param array $metabox
696 *
697 * @return string
698 */
699 function gamipress_requirements_ui_get_requirement_type( $post, $metabox ) {
700
701 $requirement_type = '';
702
703 if( $post->post_type === 'points-type' ) {
704 // Requirement type passed through the add_meta_box()
705 $requirement_type = $metabox['args']['requirement_type'];
706 } else if( gamipress_is_achievement( $post ) ) {
707 $requirement_type = 'step';
708 } else if( gamipress_is_rank( $post ) ) {
709 $requirement_type = 'rank-requirement';
710 } else if( isset( $metabox['args'] ) && isset( $metabox['args']['requirement_type'] ) ) {
711 $requirement_type = $metabox['args']['requirement_type'];
712 }
713
714 return apply_filters( 'gamipress_requirements_ui_get_requirement_type', $requirement_type, $post );
715 }
716
717 /**
718 * Get all the requirements of a given points award
719 *
720 * @since 1.0.0
721 *
722 * @param integer $point_award_id The given requirement's post ID
723 *
724 * @return array|bool An array of all the requirement requirements if it has any, false if not
725 */
726 function gamipress_get_points_award_requirements( $point_award_id = 0 ) {
727
728 $requirements = gamipress_get_requirement_object( $point_award_id );
729
730 return apply_filters( 'gamipress_get_points_award_requirements', $requirements, $point_award_id );
731 }
732
733 /**
734 * Get all the requirements of a given points deduct
735 *
736 * @since 1.3.7
737 *
738 * @param integer $point_deduct_id The given requirement's post ID
739 *
740 * @return array|bool An array of all the requirement requirements if it has any, false if not
741 */
742 function gamipress_get_points_deduct_requirements( $point_deduct_id = 0 ) {
743
744 $requirements = gamipress_get_requirement_object( $point_deduct_id );
745
746 return apply_filters( 'gamipress_get_points_deduct_requirements', $requirements, $point_deduct_id );
747 }
748
749 /**
750 * Get all the requirements of a given step
751 *
752 * @since 1.0.0
753 *
754 * @param integer $step_id The given requirement's post ID
755 *
756 * @return array|bool An array of all the requirement requirements if it has any, false if not
757 */
758 function gamipress_get_step_requirements( $step_id = 0 ) {
759
760 $requirements = gamipress_get_requirement_object( $step_id );
761
762 return apply_filters( 'gamipress_get_step_requirements', $requirements, $step_id );
763 }
764
765 /**
766 * Get all the requirements of a given rank requirement
767 *
768 * @since 1.3.1
769 *
770 * @param integer $rank_requirement_id The given requirement's post ID
771 *
772 * @return array|bool An array of all the requirement requirements if it has any, false if not
773 */
774 function gamipress_get_rank_requirement_requirements( $rank_requirement_id = 0 ) {
775
776 $requirements = gamipress_get_requirement_object( $rank_requirement_id );
777
778 return apply_filters( 'gamipress_get_rank_requirement_requirements', $requirements, $rank_requirement_id );
779 }
780
781 /**
782 * AJAX Handler for adding a new requirement
783 *
784 * @since 1.0.0
785 */
786 function gamipress_add_requirement_ajax_handler() {
787 // Security check, forces to die if not security passed
788 check_ajax_referer( 'gamipress_admin', 'nonce' );
789
790 // Check user capabilities
791 if( ! current_user_can( gamipress_get_manager_capability() ) )
792 wp_send_json_error( __( 'You are not allowed to perform this action.', 'gamipress' ) );
793
794 $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
795
796 $post = get_post( $post_id );
797
798 if( ! $post )
799 wp_send_json_error( __( 'Invalid post.', 'gamipress' ) );
800
801 $requirement_type = gamipress_requirements_ui_get_requirement_type( $post, array(
802 'args' => array(
803 'requirement_type' => ( isset( $_POST['requirement_type'] ) ? sanitize_text_field( $_POST['requirement_type'] ) : '' )
804 )
805 ) );
806
807 // Create a new requirement post and grab it's ID
808 $requirement_id = wp_insert_post( array(
809 'post_type' => $requirement_type,
810 'post_status' => 'publish',
811 'post_parent' => $post->ID,
812 'menu_order' => 0,
813 ) );
814
815 // Output the edit requirement html to insert into the requirements meta box
816 gamipress_requirement_ui_html( $requirement_id, $post->ID );
817 die;
818 }
819 add_action( 'wp_ajax_gamipress_add_requirement', 'gamipress_add_requirement_ajax_handler' );
820
821 /**
822 * AJAX Handler for duplicate a requirement
823 *
824 * @since 1.0.0
825 */
826 function gamipress_duplicate_requirement_ajax_handler() {
827 // Security check, forces to die if not security passed
828 check_ajax_referer( 'gamipress_admin', 'nonce' );
829
830 // Check user capabilities
831 if( ! current_user_can( gamipress_get_manager_capability() ) )
832 wp_send_json_error( __( 'You are not allowed to perform this action.', 'gamipress' ) );
833
834 $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
835 $requirement_id = isset( $_POST['requirement_id'] ) ? absint( $_POST['requirement_id'] ) : 0;
836
837 $post = get_post( $post_id );
838
839 if( ! $post )
840 wp_send_json_error( __( 'Invalid post.', 'gamipress' ) );
841
842 $requirement = gamipress_get_requirement_object( $requirement_id );
843
844 // Create a new requirement post and grab it's ID
845 $clone_requirement_id = wp_insert_post( array(
846 'post_title' => gamipress_get_post_field( 'post_title', $requirement['ID'] ),
847 'post_type' => gamipress_get_post_field( 'post_type', $requirement['ID'] ),
848 'post_status' => 'publish',
849 'post_parent' => $post->ID,
850 'menu_order' => absint( $post->menu_order ) + 1,
851 ) );
852
853 // Set the cloned ID to let gamipress_update_requirement() clone the data
854 $requirement['ID'] = $clone_requirement_id;
855
856 gamipress_update_requirement( $requirement );
857
858 // Reset the trigger cache
859 gamipress_delete_trigger_cache( $requirement['trigger_type'] );
860
861 // Output the edit requirement html to insert into the requirements meta box
862 gamipress_requirement_ui_html( $clone_requirement_id, $post->ID );
863 die;
864 }
865 add_action( 'wp_ajax_gamipress_duplicate_requirement', 'gamipress_duplicate_requirement_ajax_handler' );
866
867 /**
868 * AJAX Handler for deleting a requirement
869 *
870 * @since 1.0.0
871 */
872 function gamipress_delete_requirement_ajax_handler() {
873 // Security check, forces to die if not security passed
874 check_ajax_referer( 'gamipress_admin', 'nonce' );
875
876 // Check user capabilities
877 if( ! current_user_can( gamipress_get_manager_capability() ) )
878 wp_send_json_error( __( 'You are not allowed to perform this action.', 'gamipress' ) );
879
880 $requirement_id = isset( $_POST['requirement_id'] ) ? absint( $_POST['requirement_id'] ) : 0;
881
882 // Reset the trigger cache
883 $trigger = gamipress_get_post_meta( $requirement_id, '_gamipress_trigger_type' );
884
885 gamipress_delete_trigger_cache( $trigger );
886
887 /**
888 * Action to delete custom requirement
889 *
890 * @since 1.0.0
891 *
892 * @param int $requirement_id
893 */
894 do_action( 'gamipress_delete_requirement', $requirement_id );
895
896 // Delete the requirement post
897 wp_delete_post( $requirement_id );
898 die;
899 }
900 add_action( 'wp_ajax_gamipress_delete_requirement', 'gamipress_delete_requirement_ajax_handler' );
901
902 /**
903 * AJAX Handler for saving all requirements
904 *
905 * @since 1.0.5
906 */
907 function gamipress_update_requirements_ajax_handler() {
908 // Security check, forces to die if not security passed
909 check_ajax_referer( 'gamipress_admin', 'nonce' );
910
911 // Check user capabilities
912 if( ! current_user_can( gamipress_get_manager_capability() ) ) {
913 wp_send_json_error( __( 'You are not allowed to perform this action.', 'gamipress' ) );
914 }
915
916 $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
917 $requirements_limit = 20;
918 $order = absint( $_POST['loop'] ) * $requirements_limit;
919
920 // Save sequential steps (now placed on requirements UI)
921 if( isset( $_POST['_gamipress_sequential'] ) && ! empty( $_POST['_gamipress_sequential'] ) ) {
922 gamipress_update_post_meta( $post_id, '_gamipress_sequential', 'on' );
923 } else {
924 gamipress_delete_post_meta( $post_id, '_gamipress_sequential', 'on' );
925 }
926
927 // Only continue if we have any requirements
928 if ( isset( $_POST['requirements'] ) && is_array( $_POST['requirements'] ) ) {
929
930 // Setup an array for storing all our requirement titles
931 // This let's us dynamically update the Label field when requirements are saved
932 $new_titles = array();
933 $triggers = array();
934
935 // Loop through each of the created requirements
936 foreach ( $_POST['requirements'] as $requirement ) {
937
938 $requirement_updated = gamipress_update_requirement( $requirement, $order );
939
940 // Grab the requirement ID
941 $requirement_id = $requirement['requirement_id'];
942
943 // Add the title to our AJAX return
944 $new_titles[$requirement_id] = stripslashes( $requirement_updated['title'] );
945
946 // Add the trigger to the triggers array if not added yet
947 if( ! in_array( $requirement['trigger_type'], $triggers ) ) {
948 $triggers[] = $requirement['trigger_type'];
949 }
950
951 // Update order
952 $order++;
953
954 }
955
956 // Loop all saved triggers to reset their caches
957 foreach( $triggers as $trigger ) {
958 // Reset the trigger cache
959 gamipress_delete_trigger_cache( $trigger );
960 }
961
962 // Send back all our requirement titles
963 echo json_encode( $new_titles );
964
965 }
966
967 // We're done here.
968 die;
969 }
970 add_action( 'wp_ajax_gamipress_update_requirements', 'gamipress_update_requirements_ajax_handler' );
971
972 /**
973 * Save a requirement
974 *
975 * @since 1.4.6
976 *
977 * @param array $requirement
978 * @param int $order
979 *
980 * @return array The updated requirement object
981 */
982 function gamipress_update_requirement( $requirement, $order = 0 ) {
983
984 // Check user capabilities
985 if( ! current_user_can( gamipress_get_manager_capability() ) ) {
986
987 if( defined( 'DOING_AJAX' ) ) {
988 wp_send_json_error( __('You are not allowed to perform this action.', 'gamipress') );
989 } else {
990 return $requirement;
991 }
992
993 }
994
995 // Grab all of the relevant values of that requirement
996 $requirement_id = isset( $requirement['ID'] ) ? absint( $requirement['ID'] ) : absint( $requirement['requirement_id'] );
997 $requirement_type = gamipress_get_post_type( $requirement_id );
998 $count = ( ! empty( $requirement['count'] ) ) ? absint( $requirement['count'] ) : 1;
999 $points_condition = ( ! empty( $requirement['points_condition'] ) ) ? sanitize_text_field( $requirement['points_condition'] ) : 'greater_or_equal';
1000 $points_required = ( ! empty( $requirement['points_required'] ) ) ? absint( $requirement['points_required'] ) : 1;
1001 $points_type_required = ( ! empty( $requirement['points_type_required'] ) ) ? sanitize_text_field( $requirement['points_type_required'] ) : '';
1002 $rank_type_required = ( ! empty( $requirement['rank_type_required'] ) ) ? sanitize_text_field( $requirement['rank_type_required'] ) : '';
1003 $rank_required = ( ! empty( $requirement['rank_required'] ) ) ? absint( $requirement['rank_required'] ) : 0;
1004 $post_type_required = ( ! empty( $requirement['post_type_required'] ) ) ? sanitize_text_field( $requirement['post_type_required'] ) : '';
1005 $user_role_required = ( ! empty( $requirement['user_role_required'] ) ) ? sanitize_text_field( $requirement['user_role_required'] ) : '';
1006 $meta_key_required = ( ! empty( $requirement['meta_key_required'] ) ) ? sanitize_text_field( $requirement['meta_key_required'] ) : '';
1007 $meta_value_required = ( ! empty( $requirement['meta_value_required'] ) ) ? sanitize_text_field( $requirement['meta_value_required'] ) : '';
1008 $limit = ( ! empty( $requirement['limit'] ) ) ? absint( $requirement['limit'] ) : 1;
1009 $limit_type = ( ! empty( $requirement['limit_type'] ) ) ? sanitize_text_field( $requirement['limit_type'] ) : 'unlimited';
1010 $optional = ( isset( $requirement['optional'] ) ) ? (bool) $requirement['optional'] : false;
1011 $url = ( ! empty( $requirement['url'] ) ) ? sanitize_url( $requirement['url'] ) : '';
1012 $trigger_type = sanitize_text_field( $requirement['trigger_type'] );
1013 $achievement_type = sanitize_text_field( $requirement['achievement_type'] );
1014
1015 // Connect the achievement with the requirement
1016 if( in_array( $trigger_type, array( 'specific-achievement', 'revoke-specific-achievement' ) ) ) {
1017
1018 $achievement_post_id = absint( $requirement['achievement_post'] );
1019
1020 // Update achievement post to check it on rules engine
1021 update_post_meta( $requirement_id, '_gamipress_achievement_post', $achievement_post_id );
1022 }
1023
1024 // Specific activity trigger type
1025 if( in_array( $trigger_type, array_keys( gamipress_get_specific_activity_triggers() ) ) ) {
1026
1027 $achievement_post_id = absint( $requirement['achievement_post'] );
1028 $achievement_post_site_id = ( empty( $requirement['achievement_post_site_id'] ) ? get_current_blog_id() : absint( $requirement['achievement_post_site_id'] ) );
1029
1030 // Update achievement post to check it on rules engine
1031 update_post_meta( $requirement_id, '_gamipress_achievement_post', $achievement_post_id );
1032 update_post_meta( $requirement_id, '_gamipress_achievement_post_site_id', $achievement_post_site_id );
1033 }
1034
1035 // Update our relevant meta
1036 update_post_meta( $requirement_id, '_gamipress_points_condition', $points_condition );
1037 update_post_meta( $requirement_id, '_gamipress_points_required', $points_required );
1038 update_post_meta( $requirement_id, '_gamipress_points_type_required', $points_type_required );
1039 update_post_meta( $requirement_id, '_gamipress_rank_type_required', $rank_type_required );
1040 update_post_meta( $requirement_id, '_gamipress_rank_required', $rank_required );
1041 update_post_meta( $requirement_id, '_gamipress_post_type_required', $post_type_required );
1042 update_post_meta( $requirement_id, '_gamipress_user_role_required', $user_role_required );
1043 update_post_meta( $requirement_id, '_gamipress_meta_key_required', $meta_key_required );
1044 update_post_meta( $requirement_id, '_gamipress_meta_value_required', $meta_value_required );
1045 update_post_meta( $requirement_id, '_gamipress_count', $count );
1046 update_post_meta( $requirement_id, '_gamipress_limit', $limit );
1047 update_post_meta( $requirement_id, '_gamipress_limit_type', $limit_type );
1048 update_post_meta( $requirement_id, '_gamipress_trigger_type', $trigger_type );
1049 update_post_meta( $requirement_id, '_gamipress_achievement_type', $achievement_type );
1050 update_post_meta( $requirement_id, '_gamipress_optional', ( $optional ? '1' : '0' ) );
1051 update_post_meta( $requirement_id, '_gamipress_url', $url );
1052
1053 // Specific points award data
1054 if( $requirement_type === 'points-award' || $requirement_type === 'points-deduct' ) {
1055 $points = ( ! empty( $requirement['points'] ) ) ? absint( $requirement['points'] ) : 1;
1056 $points_type = ( ! empty( $requirement['points_type'] ) ) ? sanitize_text_field( $requirement['points_type'] ) : '';
1057 $maximum_earnings = ( ! $requirement['maximum_earnings'] !== "" ) ? absint( $requirement['maximum_earnings'] ) : 1;
1058
1059 update_post_meta( $requirement_id, '_gamipress_points', $points );
1060 update_post_meta( $requirement_id, '_gamipress_points_type', $points_type );
1061 update_post_meta( $requirement_id, '_gamipress_maximum_earnings', $maximum_earnings );
1062 }
1063
1064 // If a new meta key is in use, delete cache and rebuild it
1065 if( $meta_key_required !== '' ) {
1066 gamipress_delete_cache( 'gamipress_meta_keys_in_use' );
1067 gamipress_get_meta_keys_in_use();
1068 }
1069
1070 /**
1071 * Action to store custom requirement data when saved
1072 *
1073 * @since 1.0.0
1074 *
1075 * @param int $requirement_id
1076 * @param array $requirement
1077 */
1078 do_action( 'gamipress_update_requirement', $requirement_id, $requirement );
1079
1080 if( defined( 'DOING_AJAX' ) ) {
1081 /**
1082 * Action to store custom requirement data when saved through ajax
1083 *
1084 * @since 1.0.0
1085 *
1086 * @param int $requirement_id
1087 * @param array $requirement
1088 */
1089 do_action( 'gamipress_ajax_update_requirement', $requirement_id, $requirement );
1090 }
1091
1092 // Setup a new title if no set
1093 $post_title = ! empty( $requirement['title'] ) ? sanitize_text_field( $requirement['title'] ) : gamipress_build_requirement_title( $requirement_id, $requirement );
1094
1095 /**
1096 * Post title filter
1097 *
1098 * @since 1.0.0
1099 *
1100 * @param int $post_title The post title
1101 * @param int $requirement_id The requirement ID
1102 * @param array $requirement The requirement
1103 */
1104 $post_title = apply_filters( 'gamipress_requirement_post_title', $post_title, $requirement_id, $requirement );
1105
1106 // Update our original post with the new title
1107 wp_update_post( array(
1108 'ID' => $requirement_id,
1109 'post_title' => $post_title,
1110 'post_status' => isset( $requirement['status'] ) ? sanitize_text_field( $requirement['status'] ) : gamipress_get_post_status( $requirement_id ),
1111 'menu_order' => absint( $order )
1112 ) );
1113
1114 return gamipress_get_requirement_object( $requirement_id );
1115
1116 }
1117
1118 /**
1119 * Save custom fields
1120 *
1121 * @since 1.4.6
1122 *
1123 * @param int $post_id
1124 */
1125 function gamipress_on_save_requirements_post_parent( $post_id ) {
1126
1127 $post_type = gamipress_get_post_type( $post_id );
1128 $allowed_post_types = array_merge( gamipress_get_achievement_types_slugs(), gamipress_get_rank_types_slugs() );
1129
1130 // Bail if not is an allowed type
1131 if( ! in_array( $post_type, $allowed_post_types ) ) {
1132 return;
1133 }
1134
1135 if ( ! isset( $_POST['_gamipress_sequential_nonce'] )
1136 || ! wp_verify_nonce( $_POST['_gamipress_sequential_nonce'], '_gamipress_sequential_' . $post_id ) ) {
1137 return;
1138 }
1139
1140 // Save sequential steps (now placed on requirements UI)
1141 if( isset( $_REQUEST['_gamipress_sequential'] ) ) {
1142 gamipress_update_post_meta( $post_id, '_gamipress_sequential', 'on' );
1143 } else {
1144 gamipress_delete_post_meta( $post_id, '_gamipress_sequential', 'on' );
1145 }
1146
1147 }
1148 add_action( 'save_post', 'gamipress_on_save_requirements_post_parent' );
1149
1150 /**
1151 * Generate a requirement title based on his configuration
1152 *
1153 * @since 1.0.5
1154 *
1155 * @param $requirement_id integer The requirement ID
1156 * @param $requirement array The requirement array object (Optional)
1157 *
1158 * @return string
1159 */
1160 function gamipress_build_requirement_title( $requirement_id, $requirement = array() ) {
1161
1162 if( empty( $requirement ) ) {
1163 $requirement = gamipress_get_requirement_object( $requirement_id );
1164 }
1165
1166 $requirement_type = gamipress_get_post_type( $requirement_id );
1167 $points_condition = ( ! empty( $requirement['points_condition'] ) ) ? $requirement['points_condition'] : 'greater_or_equal';
1168 $points_required = ( ! empty( $requirement['points_required'] ) ) ? absint( $requirement['points_required'] ) : 1;
1169 $points_type_required = ( ! empty( $requirement['points_type_required'] ) ) ? $requirement['points_type_required'] : '';
1170 $rank_type_required = ( ! empty( $requirement['rank_type_required'] ) ) ? $requirement['rank_type_required'] : '';
1171 $rank_required = ( ! empty( $requirement['rank_required'] ) ) ? absint( $requirement['rank_required'] ) : 0;
1172 $post_type_required = ( ! empty( $requirement['post_type_required'] ) ) ? $requirement['post_type_required'] : '';
1173 $post_types = get_post_types( array(), 'objects' );
1174 $post_type_label = ( isset( $post_types[$post_type_required] ) ? strtolower( $post_types[$post_type_required]->labels->singular_name ) : __( 'post', 'gamipress' ) );
1175 $user_role_required = ( ! empty( $requirement['user_role_required'] ) ) ? $requirement['user_role_required'] : '';
1176 $roles = gamipress_get_editable_roles();
1177 $count = ( ! empty( $requirement['count'] ) ) ? absint( $requirement['count'] ) : 1;
1178 $limit = ( ! empty( $requirement['limit'] ) ) ? absint( $requirement['limit'] ) : 1;
1179 $limit_type = ( ! empty( $requirement['limit_type'] ) ) ? $requirement['limit_type'] : 'unlimited';
1180 $trigger_type = $requirement['trigger_type'];
1181 $achievement_type = $requirement['achievement_type'];
1182 $meta_key_required = ( isset( $requirement['meta_key_required'] ) ) ? $requirement['meta_key_required'] : '';
1183 $meta_value_required = ( isset( $requirement['meta_value_required'] ) ) ? $requirement['meta_value_required'] : '';
1184
1185 // Flip between our requirement types and make an appropriate connection
1186 switch ( $trigger_type ) {
1187 // Points triggers
1188 case 'earn-points':
1189 $title = sprintf( __( 'Earn %s', 'gamipress' ), gamipress_format_points( $points_required, $points_type_required, false ) );
1190 break;
1191 case 'points-balance':
1192 $points_conditions = gamipress_number_condition_options();
1193
1194 $title = sprintf( __( 'Reach a balance %s %s', 'gamipress' ), $points_conditions[$points_condition], gamipress_format_points( $points_required, $points_type_required, false ) );
1195 break;
1196 case 'gamipress_expend_points':
1197 $title = sprintf( __( 'Expend %s', 'gamipress' ), gamipress_format_points( $points_required, $points_type_required, false ) );
1198 break;
1199 // Rank triggers
1200 case 'earn-rank':
1201 $rank = gamipress_get_post( $rank_required );
1202
1203 $title = sprintf( __( 'Reach %s %s', 'gamipress' ), ( $rank ? gamipress_get_rank_type_singular( $rank->post_type, true ) : '' ), ( $rank ? $rank->post_title : '' ) );
1204 break;
1205 case 'revoke-rank':
1206 $rank = gamipress_get_post( $rank_required );
1207
1208 $title = sprintf( __( 'Get %s %s revoked', 'gamipress' ), ( $rank ? gamipress_get_rank_type_singular( $rank->post_type, true ) : '' ), ( $rank ? $rank->post_title : '' ) );
1209 break;
1210 // Achievement triggers
1211 case 'specific-achievement':
1212 $title = sprintf( __( 'Unlock "%s"', 'gamipress' ), gamipress_get_specific_activity_trigger_post_title( $requirement['achievement_post'], $trigger_type, $requirement['achievement_post_site_id'] ) );
1213 break;
1214 case 'any-achievement':
1215 $title = sprintf( __( 'Unlock any %s', 'gamipress' ), $achievement_type );
1216 break;
1217 case 'all-achievements':
1218 $title = sprintf( __( 'Unlock all %s', 'gamipress' ), $achievement_type );
1219 break;
1220 case 'revoke-specific-achievement':
1221 $title = sprintf( __( 'Get "%s" revoked', 'gamipress' ), gamipress_get_specific_activity_trigger_post_title( $requirement['achievement_post'], $trigger_type, $requirement['achievement_post_site_id'] ) );
1222 break;
1223 case 'revoke-any-achievement':
1224 $title = sprintf( __( 'Get any %s revoked', 'gamipress' ), $achievement_type );
1225 break;
1226 // Post type triggers
1227 case 'gamipress_new_comment_post_type':
1228 $title = sprintf( __( 'Comment on a %s', 'gamipress' ), $post_type_label );
1229 break;
1230 case 'gamipress_user_post_comment_post_type':
1231 $title = sprintf( __( 'Get a comment on a %s', 'gamipress' ), $post_type_label );
1232 break;
1233 case 'gamipress_spam_comment_post_type':
1234 $title = sprintf( __( 'Get a comment on a %s marked as spam', 'gamipress' ), $post_type_label );
1235 break;
1236 case 'gamipress_publish_post_type':
1237 $title = sprintf( __( 'Publish a new %s', 'gamipress' ), $post_type_label );
1238 break;
1239 case 'gamipress_delete_post_type':
1240 $title = sprintf( __( 'Delete a %s', 'gamipress' ), $post_type_label );
1241 break;
1242 case 'gamipress_post_type_visit':
1243 $title = sprintf( __( 'Daily visit a %s', 'gamipress' ), $post_type_label );
1244 break;
1245 case 'gamipress_user_post_type_visit':
1246 $title = sprintf( __( 'Get visits on a %s', 'gamipress' ), $post_type_label );
1247 break;
1248 // Role triggers
1249 case 'gamipress_add_specific_role':
1250 $title = sprintf( __( 'Get added to %s role', 'gamipress' ), translate_user_role( $roles[$user_role_required]['name'] ) );
1251 break;
1252 case 'gamipress_set_specific_role':
1253 $title = sprintf( __( 'Get assigned to %s role', 'gamipress' ), translate_user_role( $roles[$user_role_required]['name'] ) );
1254 break;
1255 case 'gamipress_remove_specific_role':
1256 $title = sprintf( __( 'Get removed from %s role', 'gamipress' ), translate_user_role( $roles[$user_role_required]['name'] ) );
1257 break;
1258 // Metas
1259 case 'gamipress_update_post_meta_any_value':
1260 $title = sprintf( __( 'Update post meta %s', 'gamipress' ), $meta_key_required );
1261 break;
1262 case 'gamipress_update_user_meta_any_value':
1263 $title = sprintf( __( 'Update user meta %s', 'gamipress' ), $meta_key_required );
1264 break;
1265 case 'gamipress_update_post_meta_specific_value':
1266 $title = sprintf( __( 'Update post meta %s with %s', 'gamipress' ), $meta_key_required, $meta_value_required );
1267 break;
1268 case 'gamipress_update_user_meta_specific_value':
1269 $title = sprintf( __( 'Update user meta %s with %s', 'gamipress' ), $meta_key_required, $meta_value_required );
1270 break;
1271 // Default
1272 default:
1273 $title = gamipress_get_activity_trigger_label( $trigger_type );
1274 break;
1275
1276 }
1277
1278 // Specific activity trigger type
1279 if( in_array( $trigger_type, array_keys( gamipress_get_specific_activity_triggers() ) ) ) {
1280 $achievement_post_id = absint( $requirement['achievement_post'] );
1281 $achievement_post_site_id = absint( $requirement['achievement_post_site_id'] );
1282
1283 if( $achievement_post_id ) {
1284 // Filtered title
1285 $title = sprintf(
1286 gamipress_get_specific_activity_trigger_label( $trigger_type ),
1287 gamipress_get_specific_activity_trigger_post_title( $achievement_post_id, $trigger_type, $achievement_post_site_id )
1288 );
1289 }
1290 }
1291
1292 // Filter to completely override activity trigger label
1293 $title = apply_filters( 'gamipress_activity_trigger_label', $title, $requirement_id, $requirement );
1294
1295 // Prepend "%d %s for" with the points to title
1296 if( $requirement_type === 'points-award' || $requirement_type === 'points-deduct' ) {
1297
1298 $points = ( ! empty( $requirement['points'] ) ) ? absint( $requirement['points'] ) : 1;
1299 $points_type = ( ! empty( $requirement['points_type'] ) ) ? $requirement['points_type'] : '';
1300 // This var is correctly set but not used to generate the title
1301 //$maximum_earnings = ( ! empty( $requirement['maximum_earnings'] ) ) ? absint( $requirement['maximum_earnings'] ) : 1;
1302
1303 if ( $points > 0 ) {
1304
1305 $points_title = '';
1306
1307 if( $requirement_type === 'points-award' ) {
1308 $points_title = sprintf( __( '%s for', 'gamipress' ), gamipress_format_points( $points, $points_type, false ) ); // 1 Points for
1309 } else if( $requirement_type === 'points-deduct' ) {
1310 $points_title = sprintf( __( '-%s for', 'gamipress' ), gamipress_format_points( $points, $points_type, false ) ); // -1 Points for
1311 }
1312
1313 // Prepend the points title to the title
1314 $title = sprintf( __( '%1$s %2$s', 'gamipress' ), $points_title, lcfirst( $title ) );
1315
1316 }
1317
1318 }
1319
1320 // Check if trigger is excluded from activity limits
1321 if( ! in_array( $trigger_type, gamipress_get_activity_triggers_excluded_from_activity_limit() ) ) {
1322 // Add "%d time(s)" to title
1323 $title = sprintf( __( '%1$s %2$s', 'gamipress' ), $title, sprintf( _n( '%d time', '%d times', $count, 'gamipress' ), $count ) );
1324 }
1325
1326 // Add "(limited to %d per %s)" to title if is limited
1327 if( $limit_type !== 'unlimited' ) {
1328
1329 $limit_type_label = '';
1330
1331 switch( $limit_type ) {
1332 case 'minutely':
1333 $limit_type_label = __( 'minute', 'gamipress' );
1334 break;
1335 case 'hourly':
1336 $limit_type_label = __( 'hour', 'gamipress' );
1337 break;
1338 case 'daily':
1339 $limit_type_label = __( 'day', 'gamipress' );
1340 break;
1341 case 'weekly':
1342 $limit_type_label = __( 'week', 'gamipress' );
1343 break;
1344 case 'monthly':
1345 $limit_type_label = __( 'month', 'gamipress' );
1346 break;
1347 case 'yearly':
1348 $limit_type_label = __( 'year', 'gamipress' );
1349 break;
1350 }
1351
1352 $title = sprintf( __( '%1$s %2$s', 'gamipress' ), $title, sprintf( __( '(limited to %d per %s)', 'gamipress' ), $limit, $limit_type_label ) );
1353 }
1354
1355 $optional = ( isset( $requirement['optional'] ) ) ? (bool) $requirement['optional'] : false;
1356
1357 if( $optional ) {
1358 $title = sprintf( __( '%1$s %2$s', 'gamipress' ), $title, __( '(Optional)', 'gamipress' ) );
1359 }
1360
1361 // Available hook for custom Activity Triggers
1362 return apply_filters( 'gamipress_requirement_title', $title, $requirement_id, $requirement );
1363
1364 }
1365
1366 /**
1367 * Get the sort order for a given requirement
1368 *
1369 * @since 1.0.5
1370 * @updated 1.5.1
1371 *
1372 * @param int $requirement_id The given requirement's post ID
1373 *
1374 * @return int The requirement's sort order
1375 */
1376 function gamipress_get_requirement_menu_order( $requirement_id = 0 ) {
1377
1378 // If not properly upgrade to required version fallback to compatibility function
1379 if( ! is_gamipress_upgraded_to( '1.5.1' ) )
1380 return gamipress_get_requirement_menu_order_old( $requirement_id );
1381
1382 return gamipress_get_post_field( 'menu_order', $requirement_id );
1383
1384 }
1385
1386 /**
1387 * Helper function for comparing our requirement sort order (used in uasort() in gamipress_create_points_awards_meta_box())
1388 *
1389 * @since 1.0.5
1390 * @updated 1.5.1
1391 *
1392 * @param WP_Post $requirement_x The given requirement
1393 * @param WP_Post $requirement_y The requirement we're comparing against
1394 *
1395 * @return int 0 if the order matches, -1 if it's lower, 1 if it's higher
1396 */
1397 function gamipress_compare_requirements_order( $requirement_x, $requirement_y ) {
1398
1399 // If not properly upgrade to required version fallback to compatibility function
1400 if( ! is_gamipress_upgraded_to( '1.5.1' ) && property_exists( $requirement_x, 'order' ) )
1401 return gamipress_compare_requirements_order_old( $requirement_x, $requirement_y );
1402
1403 if ( $requirement_x->menu_order == $requirement_y->menu_order )
1404 return 0;
1405
1406 return ( $requirement_x->menu_order < $requirement_y->menu_order ) ? -1 : 1;
1407
1408 }
1409