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
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 8.0.5, at includes/admin/meta-boxes/requirements-ui.php

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