Example #1
0
/**
 * Delete a user's progress for an achievement. Essentially, un-reward the achievement for this user.
 *
 * @param int $achievement_id Achievement ID
 * @param int $user_id User ID
 * @since Achievements (3.0)
 */
function dpa_delete_achievement_progress($achievement_id, $user_id)
{
    $achievement_id = dpa_get_achievement_id($achievement_id);
    if (empty($achievement_id) || !dpa_is_achievement($achievement_id)) {
        return;
    }
    $progress_id = dpa_get_progress(array('author' => $user_id, 'fields' => 'ids', 'no_found_rows' => true, 'nopaging' => true, 'numberposts' => 1, 'post_parent' => $achievement_id));
    if (empty($progress_id)) {
        return;
    }
    $progress_id = apply_filters('dpa_delete_achievement_progress', array_pop($progress_id), $achievement_id, $user_id);
    do_action('dpa_before_delete_achievement_progress', $progress_id, $achievement_id, $user_id);
    wp_delete_post($progress_id, true);
    // Check that the delete achievement isn't in the user's pending notifications
    $notifications = dpa_get_user_notifications($user_id);
    if (isset($notifications[$achievement_id])) {
        unset($notifications[$achievement_id]);
    }
    // Update the user's notifications in case we cleared any above
    dpa_update_user_notifications($notifications, $user_id);
    // Decrease user unlocked count
    dpa_update_user_unlocked_count($user_id, dpa_get_user_unlocked_count($user_id) - 1);
    /**
     * If the progress was linked to an achievement that is the same achievement that is stored in
     * this user's "last unlocked" meta, then clear the "last unlocked" meta, too.
     */
    if ((int) dpa_get_user_last_unlocked($user_id) === $achievement_id) {
        dpa_update_user_last_unlocked($user_id, 0);
    }
    do_action('dpa_after_delete_achievement_progress', $progress_id, $achievement_id, $user_id);
}
Example #2
0
/**
 * Has a specific user unlocked a specific achievement?
 *
 * @param int $user_id
 * @param int $achievement_id
 * @return bool True if user has unlocked the achievement
 * @since Achievements (3.4) 
 */
function dpa_has_user_unlocked_achievement($user_id, $achievement_id)
{
    if (!dpa_is_user_active($user_id)) {
        return false;
    }
    $achievement_id = dpa_get_achievement_id($achievement_id);
    if (empty($achievement_id) || !dpa_is_achievement($achievement_id)) {
        return false;
    }
    // Try to fetched an unlocked progress item for this user pair/achievement pair
    $progress = dpa_get_progress(array('author' => $user_id, 'fields' => 'ids', 'no_found_rows' => true, 'nopaging' => true, 'numberposts' => 1, 'post_parent' => $achievement_id, 'post_status' => dpa_get_unlocked_status_id()));
    return apply_filters('dpa_has_user_unlocked_achievement', !empty($progress), $progress, $user_id, $achievement_id);
}
/**
 * How many times this Achievement has been unlocked?
 *
 * @since 2.0
 * @param int $achievement_id Achievement ID
 * @return int
 */
function dpa_get_achievement_unlocked_count($achievement_id = 0)
{
    if (!$achievement_id) {
        $achievement_id = dpa_get_achievement_id();
    }
    $achievement_meta = dpa_get_achievements_meta();
    if (isset($achievement_meta[$achievement_id]) && $achievement_meta[$achievement_id]['no_of_unlocks']) {
        return apply_filters('dpa_get_achievement_unlocked_count', (int) $achievement_meta[$achievement_id]['no_of_unlocks']);
    } else {
        return apply_filters('dpa_get_achievement_unlocked_count', 0);
    }
}
Example #4
0
/**
 * Displays achievement notices
 *
 * @since Achievements (3.0)
 */
function dpa_achievement_notices()
{
    // Bail if not viewing an achievement
    if (!dpa_is_single_achievement()) {
        return;
    }
    // Filter notice text and bail if empty
    $notice_text = apply_filters('dpa_achievement_notices', '', dpa_get_achievement_id());
    if (empty($notice_text)) {
        return;
    }
    dpa_add_error('achievement_notice', $notice_text, 'message');
}
Example #5
0
/**
 * Has the current achievement in the progress loop been unlocked by the current user?
 * 
 * The "current" user refers to the user in the dpa_has_achievements() loop, which is not necessarily
 * the currently-logged in user.
 *
 * @param int $achievement_id Optional. Achievement ID to check.
 * @return bool True if achievement has been unlocked
 * @since Achievements (3.0)
 */
function dpa_is_achievement_unlocked($achievement_id = 0)
{
    $achievement_id = dpa_get_achievement_id($achievement_id);
    // Look in the progress posts and match the achievement against a post_parent
    $progress = wp_filter_object_list(achievements()->progress_query->posts, array('post_parent' => $achievement_id));
    $progress = array_shift($progress);
    $retval = !empty($progress) && dpa_get_unlocked_status_id() === $progress->post_status;
    return apply_filters('dpa_is_achievement_unlocked', $retval, $achievement_id, $progress);
}
Example #6
0
/**
 * Checks if an Achievement's criteria has been met, and if it has, unlock the Achievement.
 * Achievements with an action count of 0 are, effectively, unlocked each time but only
 * the points are added to user's total.
 *
 * @global object $bp BuddyPress global settings
 * @param int $user_id
 * @param string $skip_validation Set to 'force' to skip Achievement validation, e.g. the Achievement is unlocked regardless of its criteria.
 * @since 2.0
 */
function dpa_maybe_unlock_achievement($user_id, $skip_validation = '')
{
    global $bp;
    $action_count = dpa_get_achievement_action_count();
    if (dpa_is_achievement_unlocked() && $action_count > 0) {
        return;
    }
    $counters = get_user_meta($user_id, 'achievements_counters', true);
    $achievement_id = dpa_get_achievement_id();
    $skip_validation = 'force' == $skip_validation;
    // No point saving a count of 1 if the action_count is 1.
    $unlocked = false;
    if (0 === $action_count || 1 == $action_count) {
        $unlocked = true;
    } elseif (!$skip_validation) {
        if (!$counters && !is_array($counters)) {
            $counters = array();
        }
        $counters[$achievement_id] += apply_filters('dpa_achievement_counter_increment_by', 1);
        update_user_meta($user_id, 'achievements_counters', $counters);
        do_action('dpa_achievement_counter_incremented');
    }
    if (!$unlocked && ($skip_validation || $counters[$achievement_id] >= $action_count)) {
        if (isset($counters[$achievement_id])) {
            unset($counters[$achievement_id]);
            update_user_meta($user_id, 'achievements_counters', $counters);
        }
        $unlocked = true;
    }
    // Update points, insert unlocked record into DB and send notifications.
    if ($unlocked) {
        dpa_points_increment(dpa_get_achievement_points(), $user_id);
        // Let Achievements with action_count == 0, which have already been unlocked, only increment points.
        if (dpa_is_achievement_unlocked() && 0 === $action_count) {
            return;
        }
        dpa_unlock_achievement($user_id);
        if (apply_filters('dpa_achievement_unlocked_tell_user', true, $achievement_id, $user_id)) {
            bp_core_add_notification($achievement_id, $user_id, $bp->achievements->id, 'new_achievement', $user_id);
            dpa_record_activity($user_id, dpa_format_activity($user_id, $achievement_id), $achievement_id);
        }
        do_action('dpa_achievement_unlocked', $achievement_id, $user_id);
    }
}
/**
 * Reset main query vars and filter 'the_content' to output an Achievements template part as needed.
 *
 * @param string $template Optional
 * @since Achievements (3.0)
 */
function dpa_template_include_theme_compat($template = '')
{
    // Bail if a root template was already found. This prevents unintended recursive filtering of 'the_content'.
    if (dpa_is_template_included()) {
        return $template;
    }
    // Bail if shortcodes are unset somehow
    if (!is_a(achievements()->shortcodes, 'DPA_Shortcodes')) {
        return $template;
    }
    // Achievements archive
    if (dpa_is_achievement_archive()) {
        // Page exists where this archive should be
        $page = dpa_get_page_by_path(dpa_get_root_slug());
        // Should we replace the content...
        if (empty($page->post_content)) {
            $new_content = achievements()->shortcodes->display_achievements_index();
            // ...or use the existing page content?
        } else {
            $new_content = apply_filters('the_content', $page->post_content);
        }
        // Should we replace the title...
        if (empty($page->post_title)) {
            $new_title = dpa_get_achievement_archive_title();
            // ...or use the existing page title?
        } else {
            $new_title = apply_filters('the_title', $page->post_title);
        }
        dpa_theme_compat_reset_post(array('comment_status' => 'closed', 'ID' => !empty($page->ID) ? $page->ID : 0, 'is_archive' => true, 'post_author' => 0, 'post_content' => $new_content, 'post_date' => 0, 'post_status' => 'publish', 'post_title' => $new_title, 'post_type' => dpa_get_achievement_post_type()));
        // Single Achievement
    } elseif (dpa_is_single_achievement()) {
        dpa_theme_compat_reset_post(array('comment_status' => 'closed', 'ID' => dpa_get_achievement_id(), 'is_single' => true, 'post_author' => dpa_get_achievement_author_id(), 'post_content' => achievements()->shortcodes->display_achievement(array('id' => dpa_get_achievement_id())), 'post_date' => 0, 'post_status' => 'publish', 'post_title' => dpa_get_achievement_title(), 'post_type' => dpa_get_achievement_post_type()));
        // Single user's achievements template
    } elseif (dpa_is_single_user_achievements()) {
        dpa_theme_compat_reset_post(array('comment_status' => 'closed', 'ID' => 0, 'is_archive' => true, 'post_author' => 0, 'post_content' => achievements()->shortcodes->display_user_achievements(), 'post_date' => 0, 'post_status' => 'publish', 'post_title' => sprintf(_x("%s's achievements", 'possesive noun', 'achievements'), get_the_author_meta('display_name', dpa_get_displayed_user_id())), 'post_type' => dpa_get_achievement_post_type()));
    }
    /**
     * Bail if the template already matches an Achievements template. This includes
     * archive-* and single-* WordPress post_type matches (allowing themes to use the
     * expected format) as well as all other Achievements-specific template files.
     */
    if (dpa_is_template_included()) {
        return $template;
        /**
         * If we are relying on Achievements' built-in theme compatibility to load
         * the proper content, we need to intercept the_content, replace the
         * output, and display ours instead.
         *
         * To do this, we first remove all filters from 'the_content' and hook
         * our own function into it, which runs a series of checks to determine
         * the context, and then uses the built in shortcodes to output the
         * correct results from inside an output buffer.
         *
         * Uses dpa_get_theme_compat_templates() to provide fall-backs that
         * should be coded without superfluous mark-up and logic (prev/next
         * navigation, comments, date/time, etc...)
         * 
         * Hook into the 'dpa_get_achievements_template' to override the array of
         * possible templates, or 'dpa_achievements_template' to override the result.
         */
    } elseif (dpa_is_theme_compat_active()) {
        dpa_remove_all_filters('the_content');
        $template = dpa_get_theme_compat_templates();
    }
    return apply_filters('dpa_template_include_theme_compat', $template);
}