/**
  * Award an achievement to a user
  *
  * @alias add
  * @since Achievements (3.4)
  * @synopsis --user_id=<id> --achievement=<postname>
  */
 public function award($args, $assoc_args)
 {
     if (!$assoc_args['user_id'] || !get_userdata($assoc_args['user_id'])) {
         WP_CLI::error('Invalid User ID specified.');
     }
     // Get the achievement ID
     $achievement_id = $this->_get_achievement_id_by_post_name($assoc_args['achievement']);
     if (!$achievement_id) {
         WP_CLI::error(sprintf('Achievement ID not found for post_name: %1$s', $achievement_id));
     }
     // If the user has already unlocked this achievement, bail out.
     if (dpa_has_user_unlocked_achievement($assoc_args['user_id'], $achievement_id)) {
         WP_CLI::warning(sprintf('User ID %1$s has already unlocked achievement ID %2$s', $assoc_args['user_id'], $achievement_id));
         return;
     }
     $achievement_obj = dpa_get_achievements(array('no_found_rows' => true, 'nopaging' => true, 'numberposts' => 1, 'p' => $achievement_id));
     $achievement_obj = $achievement_obj[0];
     // Find any still-locked progress for this achievement for this user, as dpa_maybe_unlock_achievement() needs it.
     $progress_obj = dpa_get_progress(array('author' => $assoc_args['user_id'], 'no_found_rows' => true, 'nopaging' => true, 'numberposts' => 1, 'post_status' => dpa_get_locked_status_id()));
     if (empty($progress_obj)) {
         $progress_obj = array();
     }
     // Award the achievement
     dpa_maybe_unlock_achievement($assoc_args['user_id'], 'skip_validation', $progress_obj, $achievement_obj);
     WP_CLI::success(sprintf('Achievement ID %1$s has been awarded to User ID %2$s', $achievement_id, $assoc_args['user_id']));
 }
Exemplo n.º 2
0
/**
 * Handles the redeem achievement form submission.
 * 
 * Finds any achievements with the specific redemption code, and if the user hasn't already unlocked
 * that achievement, it's awarded to the user.
 *
 * @param string $action Optional. If 'dpa-redeem-achievement', handle the form submission.
 * @since Achievements (3.1)
 */
function dpa_form_redeem_achievement($action = '')
{
    if ('dpa-redeem-achievement' !== $action || !dpa_is_user_active()) {
        return;
    }
    // Check required form values are present
    $redemption_code = isset($_POST['dpa_code']) ? sanitize_text_field(stripslashes($_POST['dpa_code'])) : '';
    $redemption_code = apply_filters('dpa_form_redeem_achievement_code', $redemption_code);
    if (empty($redemption_code) || !dpa_verify_nonce_request('dpa-redeem-achievement')) {
        return;
    }
    // If multisite and running network-wide, switch_to_blog to the data store site
    if (is_multisite() && dpa_is_running_networkwide()) {
        switch_to_blog(DPA_DATA_STORE);
    }
    // Find achievements that match the same redemption code
    $achievements = dpa_get_achievements(array('meta_key' => '_dpa_redemption_code', 'meta_value' => $redemption_code));
    // Bail out early if no achievements found
    if (empty($achievements)) {
        dpa_add_error('dpa_redeem_achievement_nonce', __('That code was invalid. Try again!', 'achievements'));
        // If multisite and running network-wide, undo the switch_to_blog
        if (is_multisite() && dpa_is_running_networkwide()) {
            restore_current_blog();
        }
        return;
    }
    $existing_progress = dpa_get_progress(array('author' => get_current_user_id()));
    foreach ($achievements as $achievement_obj) {
        $progress_obj = array();
        // If we have existing progress, pass that to dpa_maybe_unlock_achievement().
        foreach ($existing_progress as $progress) {
            if ($achievement_obj->ID === $progress->post_parent) {
                // If the user has already unlocked this achievement, don't give it to them again.
                if (dpa_get_unlocked_status_id() === $progress->post_status) {
                    $progress_obj = false;
                } else {
                    $progress_obj = $progress;
                }
                break;
            }
        }
        if (false !== $progress_obj) {
            dpa_maybe_unlock_achievement(get_current_user_id(), 'skip_validation', $progress_obj, $achievement_obj);
        }
    }
    // If multisite and running network-wide, undo the switch_to_blog
    if (is_multisite() && dpa_is_running_networkwide()) {
        restore_current_blog();
    }
}
Exemplo n.º 3
0
/**
 * Use this to unlock an Achievement for the specified user, ignoring the Achievement's criteria.
 *
 * @global DPA_Achievement_Template $achievements_template Achievements template tag object
 * @global object $bp BuddyPress global settings
 * @param int $user_id Optional
 * @param string $achievement_slug Optional; defaults to the Achievement currently being viewed
 * @since 2.0
 * @uses DPA_Achievement
 */
function dpa_force_unlock_achievement($user_id = 0, $achievement_slug = '')
{
    global $achievements_template, $bp;
    if (!$user_id) {
        $user_id = $bp->loggedin_user->id;
    }
    if (!$achievement_slug) {
        $achievement_slug = apply_filters('dpa_get_achievement_slug', $bp->current_item);
    }
    if (!empty($achievements_template->achievement)) {
        $original_achievement = $achievements_template->achievement;
    }
    if (!empty($achievements_template->achievements)) {
        $original_achievements = $achievements_template->achievements;
    }
    // Can't use $bp->achievements_current_achievement as that achievement's populate_extras meta is for the logged-in user (or doesn't exist).
    $achievements_template->achievement = new DPA_Achievement(array('type' => 'single', 'slug' => $achievement_slug, 'user_id' => $user_id));
    $achievements_template->achievements = array($achievements_template->achievement);
    dpa_maybe_unlock_achievement($user_id, 'force');
    if (isset($original_achievements)) {
        $achievements_template->achievements = $original_achievements;
    }
    if (isset($original_achievement)) {
        $achievements_template->achievement = $original_achievement;
    }
}
Exemplo n.º 4
0
/**
 * Implements the Achievement actions and unlocks if criteria met.
 *
 * @see dpa_register_events()
 * @since Achievements (3.0)
 */
function dpa_handle_event()
{
    // Look at the current_filter to find out what action has occured
    $event_name = current_filter();
    $func_args = func_get_args();
    // Let other plugins do things before anything happens
    do_action('dpa_before_handle_event', $event_name, $func_args);
    // Allow other plugins to change the name of the event being processed, or to bail out early
    $event_name = apply_filters('dpa_handle_event_name', $event_name, $func_args);
    if (false === $event_name) {
        return;
    }
    /**
     * Extensions using the DPA_CPT_Extension base class may not capture their generic CPT
     * actions if that same action was used with by another extension with a different post
     * type. As no achievement will ever be associated with a generic action, if we're about
     * to query for a generic action, bail out.
     */
    foreach (achievements()->extensions as $extension) {
        if (!is_a($extension, 'DPA_CPT_Extension')) {
            continue;
        }
        // Is $event_name a generic CPT action?
        if (in_array($event_name, $extension->get_generic_cpt_actions(array()))) {
            return;
        }
    }
    // This filter allows the user ID to be updated (e.g. for draft posts which are then published by someone else)
    $user_id = absint(apply_filters('dpa_handle_event_user_id', get_current_user_id(), $event_name, $func_args));
    if (!$user_id) {
        return;
    }
    // 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;
    }
    // Find achievements that are associated with the $event_name taxonomy
    $args = array('ach_event' => $event_name, 'ach_populate_progress' => $user_id, 'no_found_rows' => true, 'nopaging' => true, 'post_status' => 'any', 'posts_per_page' => -1, 's' => '');
    // If multisite and running network-wide, switch_to_blog to the data store site
    if (is_multisite() && dpa_is_running_networkwide()) {
        switch_to_blog(DPA_DATA_STORE);
    }
    // Loop through achievements found
    if (dpa_has_achievements($args)) {
        while (dpa_achievements()) {
            dpa_the_achievement();
            // Check that the post status is published or privately published
            // We need to check this here to work around WP_Query not
            // constructing the query correctly with private
            if (!in_array($GLOBALS['post']->post_status, array('publish', 'private'))) {
                continue;
            }
            // Let other plugins do things before we maybe_unlock_achievement
            do_action('dpa_handle_event', $event_name, $func_args, $user_id, $args);
            // Allow plugins to stop any more processing for this achievement
            if (false === apply_filters('dpa_handle_event_maybe_unlock_achievement', true, $event_name, $func_args, $user_id, $args)) {
                continue;
            }
            // Look in the progress posts and match against a post_parent which is the same as the current achievement.
            $progress = wp_filter_object_list(achievements()->progress_query->posts, array('post_parent' => dpa_get_the_achievement_ID()));
            $progress = array_shift($progress);
            // If the achievement hasn't already been unlocked, maybe_unlock_achievement.
            if (empty($progress) || dpa_get_unlocked_status_id() !== $progress->post_status) {
                dpa_maybe_unlock_achievement($user_id, false, $progress);
            }
        }
    }
    // If multisite and running network-wide, undo the switch_to_blog
    if (is_multisite() && dpa_is_running_networkwide()) {
        restore_current_blog();
    }
    achievements()->achievement_query = new WP_Query();
    achievements()->leaderboard_query = new ArrayObject();
    achievements()->progress_query = new WP_Query();
    // Everything's done. Let other plugins do things.
    do_action('dpa_after_handle_event', $event_name, $func_args, $user_id, $args);
}
Exemplo n.º 5
0
 /**
  * Update the user's "User Points" meta information when the Edit User page has been saved,
  * and modify the user's current achievements as appropriate.
  *
  * The action that this function is hooked to is only executed on a succesful update,
  * which is behind a nonce and capability check (see wp-admin/user-edit.php).
  *
  * @param int $user_id
  * @since Achievements (3.0)
  */
 public function save_profile_fields($user_id)
 {
     if (!isset($_POST['dpa_achievements']) || !is_super_admin()) {
         return;
     }
     if (!isset($_POST['dpa_user_achievements'])) {
         $_POST['dpa_user_achievements'] = array();
     }
     // If multisite and running network-wide, switch_to_blog to the data store site
     if (is_multisite() && dpa_is_running_networkwide()) {
         switch_to_blog(DPA_DATA_STORE);
     }
     // Update user's points
     dpa_update_user_points((int) $_POST['dpa_achievements'], $user_id);
     // Get unlocked achievements
     $unlocked_achievements = dpa_get_progress(array('author' => $user_id, 'post_status' => dpa_get_unlocked_status_id()));
     $old_unlocked_achievements = wp_list_pluck($unlocked_achievements, 'post_parent');
     $new_unlocked_achievements = array_filter(wp_parse_id_list($_POST['dpa_user_achievements']));
     // Figure out which achievements to add or remove
     $achievements_to_add = array_diff($new_unlocked_achievements, $old_unlocked_achievements);
     $achievements_to_remove = array_diff($old_unlocked_achievements, $new_unlocked_achievements);
     // Remove achievements :(
     if (!empty($achievements_to_remove)) {
         foreach ($achievements_to_remove as $achievement_id) {
             dpa_delete_achievement_progress($achievement_id, $user_id);
         }
     }
     // Award achievements! :D
     if (!empty($achievements_to_add)) {
         // Get achievements to add
         $new_achievements = dpa_get_achievements(array('post__in' => $achievements_to_add, 'posts_per_page' => count($achievements_to_add)));
         // Get any still-locked progress for this user
         $existing_progress = dpa_get_progress(array('author' => $user_id, 'post_status' => dpa_get_locked_status_id()));
         foreach ($new_achievements as $achievement_obj) {
             $progress_obj = array();
             // If we have existing progress, pass that to dpa_maybe_unlock_achievement().
             foreach ($existing_progress as $progress) {
                 if ($achievement_obj->ID === $progress->post_parent) {
                     $progress_obj = $progress;
                     break;
                 }
             }
             dpa_maybe_unlock_achievement($user_id, 'skip_validation', $progress_obj, $achievement_obj);
         }
     }
     // If multisite and running network-wide, undo the switch_to_blog
     if (is_multisite() && dpa_is_running_networkwide()) {
         restore_current_blog();
     }
 }