Example #1
0
/**
 * Maps 'achievements' post type caps to built-in WordPress caps
 *
 * @param array $caps Capabilities for meta capability
 * @param string $cap Capability name
 * @param int $user_id User id
 * @param mixed $args Arguments
 * @return array Actual capabilities for meta capability
 * @since Achievements (3.0)
 */
function dpa_map_meta_caps($caps, $cap, $user_id, $args)
{
    switch ($cap) {
        // Reading
        case 'read_achievement':
        case 'read_achievement_progress':
            $post = get_post($args[0]);
            if (!empty($post)) {
                $caps = array();
                $post_type = get_post_type_object($post->post_type);
                // Public post
                if ('publish' === $post->post_status) {
                    $caps[] = 'read';
                } elseif ((int) $user_id === (int) $post->post_author) {
                    $caps[] = 'read';
                } else {
                    $caps[] = $post_type->cap->read_private_posts;
                }
            }
            break;
        case 'read_achievements':
            // Add do_not_allow cap if user is spam or deleted
            if (!dpa_is_user_active($user_id)) {
                $caps = array('do_not_allow');
            }
            break;
            // Publishing
        // Publishing
        case 'publish_achievements':
        case 'publish_achievement_progresses':
            // Add do_not_allow cap if user is spam or deleted
            if (!dpa_is_user_active($user_id)) {
                $caps = array('do_not_allow');
            }
            break;
            // Editing
        // Editing
        case 'edit_achievements':
        case 'edit_achievement_progresses':
            // Add do_not_allow cap if user is spam or deleted
            if (!dpa_is_user_active($user_id)) {
                $caps = array('do_not_allow');
            }
            break;
        case 'edit_achievement':
        case 'edit_achievement_progress':
            $_post = get_post($args[0]);
            if (!empty($_post)) {
                // Get caps for post type object
                $post_type = get_post_type_object($_post->post_type);
                $caps = array();
                // Add 'do_not_allow' cap if user is spam or deleted
                if (!dpa_is_user_active($user_id)) {
                    $caps[] = 'do_not_allow';
                    // User is author so allow edit
                } elseif ((int) $user_id === (int) $_post->post_author) {
                    $caps[] = $post_type->cap->edit_posts;
                    // Unknown, so map to edit_others_posts
                } else {
                    $caps[] = $post_type->cap->edit_others_posts;
                }
            }
            break;
            // Deleting
        // Deleting
        case 'delete_achievement':
        case 'delete_achievement_progress':
            $_post = get_post($args[0]);
            if (!empty($_post)) {
                // Get caps for post type object
                $post_type = get_post_type_object($_post->post_type);
                $caps = array();
                // Add 'do_not_allow' cap if user is spam or deleted
                if (!dpa_is_user_active($user_id)) {
                    $caps[] = 'do_not_allow';
                    // User is author so allow to delete
                } elseif ((int) $user_id === (int) $_post->post_author) {
                    $caps[] = $post_type->cap->delete_posts;
                    // Unknown so map to delete_others_posts
                } else {
                    $caps[] = $post_type->cap->delete_others_posts;
                }
            }
            break;
    }
    return apply_filters('dpa_map_meta_caps', $caps, $cap, $user_id, $args);
}
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);
}
Example #3
0
/**
 * Return a fancy description of the achievements on the site, including the
 * number of public and hidden achievements, and the username and avatar of
 * the most recent person who unlocked the achievement.
 *
 * @param mixed $args This function supports these arguments:
 *  - before: Before the text
 *  - after: After the text
 *  - size: Size of the avatar
 * @return string Fancy description
 * @since Achievements (3.0)
 */
function dpa_get_achievements_index_description($args = '')
{
    $defaults = array('after' => '</p></div>', 'before' => '<div class="dpa-template-notice info"><p class="dpa-achievements-description">', 'size' => 14);
    $r = dpa_parse_args($args, $defaults, 'get_achievements_index_description');
    extract($r);
    // Get count of total achievements
    $achievement_count = dpa_get_total_achievement_count();
    $achievement_text = sprintf(_n('%s achievement', '%s achievements', $achievement_count, 'achievements'), number_format_i18n($achievement_count));
    // Get data on the most recent unlocked achievement
    $recent_achievement_id = dpa_stats_get_last_achievement_id();
    $recent_user_id = dpa_stats_get_last_achievement_user_id();
    if (!empty($recent_user_id) && !empty($recent_achievement_id)) {
        // Check user ID is still valid
        $user = get_userdata($recent_user_id);
        if (!empty($user) && dpa_is_user_active($user)) {
            // Check achievement ID is valid
            $achievement = get_post($recent_achievement_id);
            if (!empty($achievement) && 'publish' === $achievement->post_status) {
                // Combine all the things to build the output text
                $retstr = sprintf(__('This site has %1$s, and the last unlocked was <a href="%2$s">%3$s</a> by %4$s.', 'achievements'), $achievement_text, esc_url(get_permalink($achievement->ID)), esc_html(apply_filters('dpa_get_achievement_title', $achievement->post_title, $achievement->ID)), dpa_get_user_avatar_link(array('size' => $size, 'user_id' => $user->ID)));
            }
        }
    }
    // If we haven't set a more specific description, fall back to the default.
    if (!isset($retstr)) {
        $retstr = sprintf(__('This site has %1$s.', 'achievements'), $achievement_text);
    }
    $retstr = $before . $retstr . $after;
    return apply_filters('dpa_get_achievements_index_description', $retstr, $args);
}
 /**
  * Record an activity stream entry when a user unlocks an achievement
  *
  * @param WP_Post $achievement Achievement post object
  * @param int $user_id
  * @param int $progress_id
  * @since Achievements (3.2)
  */
 public function achievement_unlocked(WP_Post $achievement, $user_id, $progress_id)
 {
     // Bail if user is not active
     if (!dpa_is_user_active($user_id)) {
         return;
     }
     // Achievement details
     $achievement_permalink = dpa_get_achievement_permalink($achievement->ID);
     $achievement_title = get_post_field('post_title', $achievement->ID, 'raw');
     $achievement_link = sprintf('<a href="%1$s">%2$s</a>', esc_url($achievement_permalink), esc_html($achievement_title));
     // Activity action & text
     $activity_text = sprintf(__('%1$s unlocked the achievement: %2$s', 'achievements'), bp_core_get_userlink($user_id), $achievement_link);
     $activity_action = apply_filters('dpa_activity_achievement_unlocked', $activity_text, $achievement->ID, $user_id, $progress_id);
     // Record the activity
     $activity = array('action' => $activity_action, 'content' => '', 'item_id' => $achievement->ID, 'hide_sitewide' => false, 'primary_link' => $achievement_permalink, 'type' => $this->achievement_unlocked, 'user_id' => $user_id);
     $this->record_activity($activity);
 }
Example #5
0
/**
 * 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 notification JS templates.
  * 
  * These will be used with underscore.js' _.template() method. It compiles these JS templates into functions
  * that can be evaluated for rendering. Useful for rendering complicated bits of HTML from JSON data sources,
  * which is exactly what we're going to do.
  *
  * @since Achievements (3.5)
  */
 public static function print_notification_templates()
 {
     // If user's not active or is inside the WordPress Admin, bail out.
     if (!dpa_is_user_active() || is_admin() || is_404()) {
         return;
     }
     echo achievements()->shortcodes->display_notifications_template();
 }
 /**
  * Last unlocked achievement column
  *
  * @param WP_User $user A singular item (one full row)
  * @see WP_List_Table::single_row_columns()
  * @since Achievements (3.0)
  */
 public function column_dpa_last_id(WP_User $user)
 {
     $output = true;
     // Get this user's most recent unlocked achievement
     $achievement_id = dpa_get_user_last_unlocked($user->ID);
     if (empty($achievement_id)) {
         $output = false;
     }
     // Check user ID is valid
     if ($output && !dpa_is_user_active($user->ID)) {
         $output = false;
     }
     // Check achievement is still valid
     if ($output) {
         $achievement = get_post($achievement_id);
     }
     if ($output && (empty($achievement) || 'publish' !== $achievement->post_status)) {
         $output = false;
     }
     if ($output) {
         printf('<a href="%1$s">%2$s</a>', esc_url(get_permalink($achievement->ID)), esc_html(apply_filters('dpa_get_achievement_title', $achievement->post_title, $achievement->ID)));
     } else {
         echo '&#8212;';
     }
 }
Example #8
0
 /**
  * Register custom menu items
  *
  * @global WP_Admin_Bar $wp_admin_bar
  * @since Achievements (3.0)
  */
 public function admin_bar_menu()
 {
     global $wp_admin_bar;
     if (!dpa_is_user_active()) {
         return;
     }
     $wp_admin_bar->add_node(array('href' => dpa_get_user_avatar_link('type=url'), 'id' => 'dpa_my_achievements', 'parent' => 'user-actions', 'title' => _x('My Achievements', 'Menu item in the toolbar', 'achievements')));
 }
Example #9
0
/**
 * Maps 'achievements' post type caps to built-in WordPress caps
 *
 * @param array $caps Capabilities for meta capability
 * @param string $cap Capability name
 * @param int $user_id User id
 * @param mixed $args Arguments
 * @return array Actual capabilities for meta capability
 * @since 3.0
 */
function dpa_map_meta_caps($caps, $cap, $user_id, $args)
{
    switch ($cap) {
        // Reading
        case 'read_achievement':
            if ($post = get_post($args[0])) {
                $caps = array();
                $post_type = get_post_type_object($post->post_type);
                if ('published' == $post->post_status) {
                    $caps[] = 'read';
                } else {
                    $caps[] = $post_type->cap->read_private_posts;
                }
            }
            break;
            // Editing
        // Editing
        case 'edit_achievements':
            // Add do_not_allow cap if user is spam or deleted
            if (!dpa_is_user_active($user_id)) {
                $caps = array('do_not_allow');
            }
            break;
        case 'edit_achievement':
            if ($post = get_post($args[0])) {
                $caps = array();
                $post_type = get_post_type_object($post->post_type);
                // Add 'do_not_allow' cap if user is spam or deleted
                if (!dpa_is_user_active($user_id)) {
                    $caps[] = 'do_not_allow';
                } elseif ((int) $user_id == (int) $post->post_author) {
                    $caps[] = $post_type->cap->edit_posts;
                } else {
                    $caps[] = $post_type->cap->edit_others_posts;
                }
            }
            break;
            // Deleting
        // Deleting
        case 'delete_achievement':
            if ($post = get_post($args[0])) {
                $caps = array();
                $post_type = get_post_type_object($post->post_type);
                // Add 'do_not_allow' cap if user is spam or deleted
                if (!dpa_is_user_active($user_id)) {
                    $caps[] = 'do_not_allow';
                } elseif ((int) $user_id == (int) $post->post_author) {
                    $caps[] = $post_type->cap->delete_posts;
                } else {
                    $caps[] = $post_type->cap->delete_others_posts;
                }
            }
            break;
    }
    return apply_filters('dpa_map_meta_caps', $caps, $cap, $user_id, $args);
}