/** * If the specified achievement's criteria has been met, we unlock the * achievement. Otherwise we record progress for the achievement for next time. * * $skip_validation is the second parameter for backpat with Achievements 2.x * * @param int $user_id * @param string $skip_validation Optional. Set to "skip_validation" to skip Achievement validation (unlock achievement regardless of criteria). * @param object $progress_obj Optional. The Progress post object. Defaults to Progress object in the Progress loop. * @param object $achievement_obj Optional. The Achievement post object to maybe_unlock. Defaults to current object in Achievement loop. * @since Achievements (2.0) */ function dpa_maybe_unlock_achievement($user_id, $skip_validation = '', $progress_obj = null, $achievement_obj = null) { // Only proceed if the specified user is active (logged in and not a spammer) if (!dpa_is_user_active($user_id)) { return; } // Only proceed if the specified user can create progress posts if (!user_can($user_id, 'publish_achievement_progresses')) { return; } // Default to current object in the achievement loop if (empty($achievement_obj)) { $achievement_obj = achievements()->achievement_query->post; } // Default to progress object in the progress loop if (empty($progress_obj) && !empty(achievements()->progress_query->posts)) { $progress_obj = wp_filter_object_list(achievements()->progress_query->posts, array('post_parent' => $achievement_obj->ID)); $progress_obj = array_shift($progress_obj); } // Has the user already unlocked the achievement? if (!empty($progress_obj) && dpa_get_unlocked_status_id() === $progress_obj->post_status) { return; } // Prepare default values to create/update a progress post $progress_args = array('comment_status' => 'closed', 'ping_status' => 'closed', 'post_author' => $user_id, 'post_parent' => $achievement_obj->ID, 'post_title' => $achievement_obj->post_title, 'post_type' => dpa_get_progress_post_type()); // If achievement already has some progress, grab the ID so we update the post later if (!empty($progress_obj->ID)) { $progress_args['ID'] = $progress_obj->ID; } // If the achievement does not have a target set, this is an award achievement. $achievement_target = dpa_get_achievement_target($achievement_obj->ID); if ($achievement_target) { // Increment progress count $progress_args['post_content'] = apply_filters('dpa_maybe_unlock_achievement_progress_increment', 1); if (!empty($progress_obj)) { $progress_args['post_content'] = (int) $progress_args['post_content'] + (int) $progress_obj->post_content; } } // Does the progress count now meet the achievement target? if ('skip_validation' === $skip_validation || $achievement_target && (int) $progress_args['post_content'] >= $achievement_target) { // Yes. Unlock achievement. $progress_args['post_status'] = dpa_get_unlocked_status_id(); // No, user needs to make more progress. Make sure the locked status is set correctly. } else { $progress_args['post_status'] = dpa_get_locked_status_id(); } // Create or update the progress post $progress_id = wp_insert_post($progress_args); // If the achievement was just unlocked, do stuff. if (dpa_get_unlocked_status_id() === $progress_args['post_status']) { // Achievement was unlocked. Notifications and points updates are hooked to this function. do_action('dpa_unlock_achievement', $achievement_obj, $user_id, $progress_id); } }
/** * Output the target value of the achievement. Only used for event-type achievements. * The target is the number of times that an achievement's events must occur before the achievement is unlocked. * * @param int $achievement_id Optional. Achievement ID * @since Achievements (3.0) */ function dpa_achievement_target($achievement_id = 0) { echo number_format_i18n(dpa_get_achievement_target($achievement_id)); }
/** * Achievements metabox * * Contains fields to set the karma points, pick between action/event, and the list of events. * * @param WP_Post $post The post being added or edited * @since Achievements (3.0) */ function dpa_achievement_metabox(WP_Post $post) { // Get all events grouped by the extension which provided them $events = dpa_get_all_events_details(); // Get existing values (if this is an edit) $existing_points = dpa_get_achievement_points($post->ID); $existing_target = dpa_get_achievement_target($post->ID); $existing_events = wp_get_post_terms($post->ID, dpa_get_event_tax_id(), array('fields' => 'ids')); $existing_type = empty($existing_events) && !empty($_GET['action']) && 'edit' === $_GET['action'] ? 'award' : 'event'; $existing_code = dpa_get_achievement_redemption_code($post->ID); // Ensure sane defaults if (empty($existing_points)) { $existing_points = 0; } if (empty($existing_target)) { $existing_target = 1; } ?> <div class="misc-pub-section dpa-karma"> <label for="dpa-points"><?php _e('Karma points:', 'achievements'); ?> </label> <input type="number" name="dpa_points" id="dpa-points" value="<?php echo esc_attr($existing_points); ?> " /> </div> <div class="misc-pub-section dpa-type"> <label for="dpa_type"><?php _ex('Type:', 'type of achievement', 'achievements'); ?> </label> <input type="radio" name="dpa_type" id="dpa-type-award" value="award" <?php checked($existing_type, 'award'); ?> ><?php _ex(' Award', 'type of achievement', 'achievements'); ?> </input> <input type="radio" name="dpa_type" id="dpa-type-event" value="event" <?php checked($existing_type, 'event'); ?> ><?php _ex(' Event', 'type of achievement', 'achievements'); ?> </input> <p class="hint"><?php _e("An <em>award</em> is given by a site admin, whereas an <em>event</em> is unlocked automatically when its criteria have been met.", 'achievements'); ?> </p> <select id="dpa-event" name="dpa_event[]" style="visibility: hidden" data-placeholder="<?php esc_attr_e('Press here to pick events', 'achievements'); ?> " class="chzn-select <?php if (is_rtl()) { echo 'chzn-rtl'; } ?> " multiple="multiple"> <option value=""></option> <?php foreach ($events as $extension => $extension_events) { ?> <optgroup label="<?php echo esc_attr($extension); ?> "> <?php foreach ($extension_events as $event) { ?> <option value="<?php echo esc_attr($event['id']); ?> " <?php selected(in_array($event['id'], $existing_events), true); ?> ><?php echo esc_html($event['description']); ?> </option> <?php } ?> </optgroup> <?php } ?> </select> </div> <div class="misc-pub-section dpa-target"> <label for="dpa_target"><?php _ex('Events repeat:', "Number of times an achievement’s events need to repeat before the achievement is awarded", 'achievements'); ?> </label> <input type="number" name="dpa_target" id="dpa-target" min="1" value="<?php echo esc_attr($existing_target); ?> " /> <p class="hint"><?php _e("Number of times the events need to repeat before the achievement is awarded.", 'achievements'); ?> </p> </div> <div class="misc-pub-section dpa-redemption-code"> <label for="dpa-code"><?php _e('Redemption code:', 'achievements'); ?> </label> <input id="dpa-code" value="<?php echo esc_attr($existing_code); ?> " name="dpa_code" type="text" /> <p class="hint"><?php _e("Users can enter this code into the Redemption widget to unlock the achievement.", 'achievements'); ?> </p> </div> <?php wp_nonce_field('dpa_achievement_metabox_save', 'dpa_achievement_metabox'); do_action('dpa_achievement_metabox'); }