• Resolved mikebronner

    (@mikebronner)


    I have compiled all the code to add categories to achievements without affecting the plugin. Paul, please feel free to adopt this code at your discretion into the plugin in a future update.

    What this code does:
    – adds achievement categories that are specific to achievements, so as not to interfere with anything else.
    – allows sorting by achievement category

    Step 1: In you child theme add the following code to your functions.php (if you don’t have one, simply create one):

    /* Re-Register Custom Post Type for Achievements for WordPress ****************/
    	function objectToArray($d)
    	{
    		if (is_object($d))
    		{
    			$d = get_object_vars($d);
    		}
    		if (is_array($d))
    		{
    			return array_map(__FUNCTION__, $d);
    		}
    		else
    		{
    			return $d;
    		}
    	}
    
    	function register_achievements_custom_taxonomy()
    	{
    		$labels = array(
    			'name'              => _x( 'Achievement Categories', 'taxonomy general name' ),
    			'singular_name'     => _x( 'Achievement Category', 'taxonomy singular name' ),
    			'search_items'      => __( 'Search Achievement Categories' ),
    			'all_items'         => __( 'All Achievement Categories' ),
    			'parent_item'       => __( 'Parent Achievement Category' ),
    			'parent_item_colon' => __( 'Parent Achievement Category:' ),
    			'edit_item'         => __( 'Edit Achievement Category' ),
    			'update_item'       => __( 'Update Achievement Category' ),
    			'add_new_item'      => __( 'Add New Achievement Category' ),
    			'new_item_name'     => __( 'New Achievement Category' ),
    			'menu_name'         => __( 'Categories' ),
    		);
    		$args = array(
    			'labels' => $labels,
    			'hierarchical' => true,
    			'show_admin_column'	=> true,
    			'show_ui' => true,
    		);
    		register_taxonomy( 'dpa_achievement_category', array(dpa_get_achievement_post_type(), dpa_get_progress_post_type()), $args );
    	}
    	add_action( 'init', 'register_achievements_custom_taxonomy', 0 );
    
    	function register_achievements_post_type_override()
    	{
    		global $wp_post_types;
    
    		$achievements = objectToArray(get_post_types(array('name'=>dpa_get_achievement_post_type()), 'objects'));
    		$progresses = objectToArray(get_post_types(array('name'=>dpa_get_progress_post_type()), 'objects'));
    
    		$achievements = $achievements[dpa_get_achievement_post_type()];
    		$progresses = $achievements[dpa_get_progress_post_type()];
    
    		$achievements["taxonomies"] = array('dpa_achievement_category');
    		$progresses["taxonomies"] = array('dpa_achievement_category');
    
    		unset($wp_post_types[dpa_get_achievement_post_type()]);
    		unset($wp_post_types[dpa_get_progress_post_type()]);
    
    		register_post_type( dpa_get_achievement_post_type(), $achievements );
    		register_post_type( dpa_get_progress_post_type(), $progresses );
    	}
    	add_action( 'dpa_register_post_types', 'register_achievements_post_type_override', 6 );
    
    	function achievement_with_category_edit_columns( $columns )
    	{
    		$columns = array(
    			'cb'				=> '<input type="checkbox" />',
    			'title'				=> __( 'Title', 'dpa' ),
    			'achievement_type'	=> _x( 'Type', 'Type of the achievement; award or badge', 'dpa' ),
    			'category'			=> _x('Category', 'Achievement category', 'dpa'),
    			'karma'				=> __( 'Karma Points', 'dpa' ),
    			'date'				=> __( 'Date', 'dpa' ),
    		);
    
    		return $columns;
    	}
    	add_filter("manage_edit-achievement_columns", "achievement_with_category_edit_columns");
    
    	function achievement_with_category_custom_columns( $column )
    	{
    		global $post;
    		switch( $column )
    		{
    			case "description":
    				the_excerpt();
    				break;
    			case "category":
    				echo get_the_term_list( $post->ID, 'dpa_achievement_category', '', ', ', '' );
    				break;
    		}
    	}
    	add_action("manage_posts_custom_column", "achievement_with_category_custom_columns");
    
    	function dpa_has_progress_custom( $args = 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 );
    
    		$defaults = array(
    			'max_num_pages' => false,                         // Maximum number of pages to show
    			'order'         => 'DESC',                        // 'ASC', 'DESC
    			'orderby'       => 'date',                        // 'meta_value', 'author', 'date', 'title', 'modified', 'parent', 'rand'
    			'paged'         => dpa_get_paged(),               // Page number
    			'post_status'   => dpa_get_unlocked_status_id(),  // Get posts in the unlocked status by default.
    			'post_type'     => dpa_get_progress_post_type(),  // Only retrieve progress posts
    			's'             => '',                            // No search
    
    			// Conditional defaults
    
    			// If on a user's achievements page, use that author's user ID.
    			'author'         => dpa_is_single_user_achievements() ? dpa_get_displayed_user_id() : null,
    
    			// If on single achievement page, use that post's ID.
    			'post_parent'    => dpa_is_single_achievement() ? dpa_get_achievement_id() : null,
    
    			// If on a single achievement page, don't paginate progresses.
    			//'posts_per_page' => dpa_is_single_achievement() ? -1 : dpa_get_progresses_per_page(),
    			// Above commented out for 3.1; see https://github.com/paulgibbs/achievements/issues/70 for details
    			'posts_per_page' => -1,
    
    			// If on a user's achievements page, fetch the achievements if we haven't got them already
    			'ach_populate_achievements' => dpa_is_single_user_achievements() && ! is_a( achievements()->achievement_query, 'WP_Query' ),
    		);
    
    		$args = dpa_parse_args( $args, $defaults, 'has_progress' );
    
    		// Run the query
    		achievements()->progress_query = new WP_Query( $args );
    
    		//var_dump(achievements()->progress_query);
    
    		// If no limit to posts per page, set it to the current post_count
    		if ( -1 == $args['posts_per_page'] )
    			$args['posts_per_page'] = achievements()->progress_query->post_count;
    
    		// Add pagination values to query object
    		achievements()->progress_query->posts_per_page = $args['posts_per_page'];
    		achievements()->progress_query->paged          = $args['paged'];
    
    		// Only add pagination if query returned results
    		if ( ( (int) achievements()->progress_query->post_count || (int) achievements()->progress_query->found_posts ) && (int) achievements()->progress_query->posts_per_page ) {
    
    			// Limit the number of achievements shown based on maximum allowed pages
    			if ( ( ! empty( $args['max_num_pages'] ) ) && achievements()->progress_query->found_posts > achievements()->progress_query->max_num_pages * achievements()->progress_query->post_count )
    				achievements()->progress_query->found_posts = achievements()->progress_query->max_num_pages * achievements()->progress_query->post_count;
    
    			// If pretty permalinks are enabled, make our pagination pretty
    			if ( $GLOBALS['wp_rewrite']->using_permalinks() ) {
    
    				// Page or single post
    				if ( is_page() || is_single() )
    					$base = get_permalink();
    
    				// User achievements page
    				elseif ( dpa_is_single_user_achievements() )
    					$base = dpa_get_user_avatar_link( array( 'type' => 'url', 'user_id' => dpa_get_displayed_user_id() ) );
    
    				// Default
    				else
    					$base = get_permalink( $args['post_parent'] );
    
    				// Use pagination base
    				$base = trailingslashit( $base ) . user_trailingslashit( $GLOBALS['wp_rewrite']->pagination_base . '/%#%/' );
    
    			// Unpretty pagination
    			} else {
    				$base = add_query_arg( 'paged', '%#%' );
    			}
    
    			// Pagination settings with filter
    			$progress_pagination = apply_filters( 'dpa_progress_pagination', array(
    				'base'      => $base,
    				'current'   => (int) achievements()->progress_query->paged,
    				'format'    => '',
    				'mid_size'  => 1,
    				'next_text' => '→',
    				'prev_text' => '←',
    				'total'     => ( $args['posts_per_page'] == achievements()->progress_query->found_posts ) ? 1 : ceil( (int) achievements()->progress_query->found_posts / (int) $args['posts_per_page'] ),
    			) );
    
    			// Add pagination to query object
    			achievements()->progress_query->pagination_links = paginate_links( $progress_pagination );
    
    			// Remove first page from pagination
    			achievements()->progress_query->pagination_links = str_replace( $GLOBALS['wp_rewrite']->pagination_base . "/1/'", "'", achievements()->progress_query->pagination_links );
    		}
    
    		// If on a user's achievements page, we need to fetch the achievements
    		if ( $args['ach_populate_achievements'] && achievements()->progress_query->have_posts() ) {
    			$achievement_ids = wp_list_pluck( (array) achievements()->progress_query->posts, 'post_parent' );
    
    			$achievement_args = array(
    				'post__in'       => $achievement_ids,  // Only get achievements that relate to the progressses we've got.
    				'posts_per_page' => -1,                // No pagination
    				'orderby' => $args['orderby'],
    				'order' => $args['order'],
    			);
    			$achievement_args = dpa_parse_args( $args_filters, $achievement_args, 'has_achievement' );
    
    			// Run the query
    			dpa_has_achievements_custom( $achievement_args );
    		}
    
    		// If multisite and running network-wide, undo the switch_to_blog
    		if ( is_multisite() && dpa_is_running_networkwide() )
    			restore_current_blog();
    
    		return apply_filters( 'dpa_has_progress', achievements()->progress_query->have_posts() );
    	}
    
    	function dpa_has_achievements_custom( $args = 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 );
    
    		$default_post_parent     = dpa_is_single_achievement()       ? dpa_get_achievement_id()              : 'any';
    		$default_progress_status = dpa_is_single_user_achievements() ? array( dpa_get_unlocked_status_id() ) : array( dpa_get_locked_status_id(), dpa_get_unlocked_status_id() );
    
    		$defaults = array(
    			// Standard WP_Query params
    			'order'                 => 'ASC',                                                // 'ASC', 'DESC
    			'orderby'               => 'title',                                              // 'meta_value', 'author', 'date', 'title', 'modified', 'parent', rand'
    			'max_num_pages'         => false,                                                // Maximum number of pages to show
    			'paged'                 => dpa_get_paged(),                                      // Page number
    			'perm'                  => 'readable',                                           // Query var value to provide statuses
    			'post_parent'           => $default_post_parent,                                 // Post parent
    			'post_type'             => dpa_get_achievement_post_type(),                      // Only retrieve achievement posts
    			'posts_per_page'        => dpa_get_achievements_per_page(),                      // Achievements per page
    			'ach_progress_status'   => $default_progress_status,                             // On single user achievement page, default to only showing unlocked achievements
    			's'                     => ! empty( $_REQUEST['dpa'] ) ? $_REQUEST['dpa'] : '',  // Achievements search @todo Is this implemented correctly?
    
    			// Achievements params
    	 		'ach_event'             => '',                                                   // Load achievements for a specific event
    			'ach_populate_progress' => false,                                                // Progress post type: populate user progress for the results.
    
    	      'tax_query'	=> array(
    	        array(
    	            'taxonomy'  => 'dpa_achievement_category',
    	            'field'     => 'id',
    	            'terms'     => get_terms( 'dpa_achievement_category', array( 'fields' => 'ids' ))
    	            )),
    
    			);
    
    		// Load achievements for a specific event
    		if ( ! empty( $args['ach_event'] ) ) {
    
    			$args['tax_query'] = array(
    				array(
    					'field'    => 'slug',
    					'taxonomy' => dpa_get_event_tax_id(),
    					'terms'    => $args['ach_event'],
    				)
    			);
    
    			unset( $args['ach_event'] );
    		}
    
    		$args = dpa_parse_args( $args, $defaults, 'has_achievements' );
    		extract( $args );
    
    		// Run the query
    		achievements()->achievement_query = new WP_Query( $args );
    	//var_dump(achievements()->achievement_query);
    
    		// User to popular progress for
    		$progress_user_ids = false;
    
    		if ( isset( $args['ach_populate_progress'] ) ) {
    			if ( true === $args['ach_populate_progress'] ) {
    				if ( dpa_is_single_user_achievements() ) {
    					$progress_user_ids = dpa_get_displayed_user_id();
    
    				} elseif ( is_user_logged_in() ) {
    					$progress_user_ids = achievements()->current_user->ID;
    				}
    
    			} else {
    				$progress_user_ids = (int) $args['ach_populate_progress'];
    			}
    		}
    
    		// If no limit to posts per page, set it to the current post_count
    		if ( -1 == $posts_per_page )
    			$posts_per_page = achievements()->achievement_query->post_count;
    
    		// Add pagination values to query object
    		achievements()->achievement_query->posts_per_page = $posts_per_page;
    		achievements()->achievement_query->paged          = $paged;
    
    		// Only add pagination if query returned results
    		if ( ( (int) achievements()->achievement_query->post_count || (int) achievements()->achievement_query->found_posts ) && (int) achievements()->achievement_query->posts_per_page ) {
    
    			// Limit the number of achievements shown based on maximum allowed pages
    			if ( ( ! empty( $max_num_pages ) ) && achievements()->achievement_query->found_posts > achievements()->achievement_query->max_num_pages * achievements()->achievement_query->post_count )
    				achievements()->achievement_query->found_posts = achievements()->achievement_query->max_num_pages * achievements()->achievement_query->post_count;
    
    			// If pretty permalinks are enabled, make our pagination pretty
    			if ( $GLOBALS['wp_rewrite']->using_permalinks() ) {
    
    				// Page or single post
    				if ( is_page() || is_single() )
    					$base = get_permalink();
    
    				// Achievements archive
    				elseif ( dpa_is_achievement_archive() )
    					$base = dpa_get_achievements_url();
    
    				// Default
    				else
    					$base = get_permalink( $post_parent );
    
    				// Use pagination base
    				$base = trailingslashit( $base ) . user_trailingslashit( $GLOBALS['wp_rewrite']->pagination_base . '/%#%/' );
    
    			// Unpretty pagination
    			} else {
    				$base = add_query_arg( 'paged', '%#%' );
    			}
    
    			// Pagination settings with filter
    			$achievement_pagination = apply_filters( 'dpa_achievement_pagination', array(
    				'base'      => $base,
    				'current'   => (int) achievements()->achievement_query->paged,
    				'format'    => '',
    				'mid_size'  => 1,
    				'next_text' => '→',
    				'prev_text' => '←',
    				'total'     => ( $posts_per_page == achievements()->achievement_query->found_posts ) ? 1 : ceil( (int) achievements()->achievement_query->found_posts / (int) $posts_per_page ),
    			) );
    
    			// Add pagination to query object
    			achievements()->achievement_query->pagination_links = paginate_links( $achievement_pagination );
    
    			// Remove first page from pagination
    			achievements()->achievement_query->pagination_links = str_replace( $GLOBALS['wp_rewrite']->pagination_base . "/1/'", "'", achievements()->achievement_query->pagination_links );
    		}
    
    		// Populate extra progress information for the achievements
    		if ( ! empty( $progress_user_ids ) && achievements()->achievement_query->have_posts() ) {
    			$progress_post_ids = wp_list_pluck( (array) achievements()->achievement_query->posts, 'ID' );
    
    			// Args for progress query
    			$progress_args = array(
    				'author'         => $progress_user_ids,            // Posts belonging to these author(s)
    				'no_found_rows'  => true,                          // Disable SQL_CALC_FOUND_ROWS (used for pagination queries)
    				'post_parent'    => $progress_post_ids,            // Fetch progress posts with parent_id matching these
    				'post_status'    => $args['ach_progress_status'],  // Get posts in these post statuses
    				'posts_per_page' => -1,                            // No pagination
    			);
    
    			// Run the query
    			dpa_has_progress( $progress_args );
    		}
    
    		// If multisite and running network-wide, undo the switch_to_blog
    		if ( is_multisite() && dpa_is_running_networkwide() )
    			restore_current_blog();
    
    		return apply_filters( 'dpa_has_achievements', achievements()->achievement_query->have_posts() );
    	}

    Note that the above code creates custom versions of dpa_has_progress() and dpa_has_achievements() functions of the plugin. These custom functions might break when the plugin is updated in the future. Not sure if there is a more elegant way. The important changes here are passing the order and orderby arguments to the achievement query, and including the taxonomy in the achievement query, in total only about 10 lines of code between the two functions. Please let me know if there is a better way to do this.

    Step 2: update the template file in your child theme to display achievements as needed. In my case I added /wp-content/themes/{child-theme}/achievements/loop-achievements.php, which has the following code:

    <?php
    /**
     * Achievements loop
     *
     * @package Achievements
     * @subpackage ThemeCompatibility
     */
    
    // Exit if accessed directly
    if ( ! defined( 'ABSPATH' ) ) exit;
    ?>
    
    <?php do_action( 'dpa_template_before_achievements_loop_block' ); ?>
    
    <?php
    	do_action( 'dpa_template_before_achievements_loop' );
    	$previous_achievment_category = "";
    	while ( dpa_achievements() )
    	{
    		dpa_the_achievement();
    		$current_category = "";
    
    		$categories = get_the_terms($post_id, 'dpa_achievement_category');
    		foreach($categories as $category)
    		{
    			if (strlen($current_category) > 0)
    			{
    				$current_category .= ", ";
    			}
    			$current_category .= $category->name;
    		}
    
    		if ($current_category != $previous_achievment_category)
    		{
    			$previous_achievment_category = $current_category;
    ?>
    
    	<h3><?php echo $current_category; ?></h3>
    <?php
    		}
    		dpa_get_template_part( 'loop-single-achievement' );
    	}
    	do_action( 'dpa_template_after_achievements_loop' );
    ?>
    <?php do_action( 'dpa_template_after_achievements_loop_block' ); ?>

    Step 3: add a customized content-author-achievement.php to the same directory as step two. Mine orders by taxonomy to group the different categories together, as shown in the above code in step 2.

    <?php
    /**
     * Author Achievement content part
     *
     * @package Achievements
     * @subpackage ThemeCompatibility
     *
     */
    
    // Exit if accessed directly
    if ( ! defined( 'ABSPATH' ) ) exit;
    ?>
    
    <div id="dpa-achievements">
    <?php
    	do_action( 'dpa_template_before_author_achievements' );
    
    	if ( dpa_has_progress_custom(array("author"=>bbp_get_user_id( null, true, false ), "ach_populate_achievements"=>true, "orderby"=>"konb_term_relationships.term_taxonomy_id")) && ! empty( achievements()->achievement_query->posts ) )
    	{
    		//dpa_get_template_part( 'pagination-author-achievements' );
    		dpa_get_template_part( 'loop-achievements');
    		//dpa_get_template_part( 'pagination-author-achievements' );
    	}
    	else
    	{
    		dpa_get_template_part( 'feedback-no-achievements' );
    	}
    	do_action( 'dpa_template_after_author_achievements' );
    ?>
    </div>

    Note that in the above code, the args "author"=>bbp_get_user_id( null, true, false ), "ach_populate_achievements"=>true are necessary to display achievements on bbpress user profiles. On normal pages and posts I believe these can be left off.

    I hope this helps others — better yet, would be great if Paul can integrate this into his plugin! 🙂 Thanks Paul for all your work on an excellent plugin!

    ~Mike

Viewing 15 replies - 1 through 15 (of 16 total)
  • Plugin Author Paul Wong-Gibbs

    (@djpaul)

    This is cool. I see you went the custom taxonomy route, which is probably the best way to do this 🙂

    I’ll have a proper read through in due course, and consider adding something like this if requests for categorised achievements are common.

    Thread Starter mikebronner

    (@mikebronner)

    Update: Improved achievement_with_category_edit_column function to be dynamic, in case the plugin gets updated with new columns. I choose the categories to be listed in the third column, but you can change that to whatever you like.

    function achievement_with_category_edit_columns($columns)
    	{
    		$column_position = 3; //choose what position you want the categories to be added
    		$columns_first = array_slice($columns, 0, $column_position - 1, true );
    		$columns_last = array_slice($columns, $column_position - 1, null, true );
    		$columns = array_merge(
    			$columns_first,
    			array('category' => _x('Category', 'Achievement category', 'dpa')),
    			$columns_last,
    		;)
    
    		return $columns;
    	}
    	add_filter("manage_edit-achievement_columns", "achievement_with_category_edit_columns");
    Thread Starter mikebronner

    (@mikebronner)

    Update 2: Fixed register_achievements_post_type_override() function. Had a typo, which caused achievements to become undeletable. Please replace with the following in your functions.php in your child theme:

    function register_achievements_post_type_override()
    	{
    		global $wp_post_types;
    
    		$achievements = objectToArray(get_post_types(array('name'=>dpa_get_achievement_post_type()), 'objects'));
    		$progresses = objectToArray(get_post_types(array('name'=>dpa_get_progress_post_type()), 'objects'));
    
    		$achievements = $achievements[dpa_get_achievement_post_type()];
    		$progresses = $progresses[dpa_get_progress_post_type()];
    
    		$achievements["taxonomies"] = array('dpa_achievement_category');
    		$progresses["taxonomies"] = array('dpa_achievement_category');
    
    		unset($wp_post_types[dpa_get_achievement_post_type()]);
    		unset($wp_post_types[dpa_get_progress_post_type()]);
    
    		register_post_type( dpa_get_achievement_post_type(), $achievements );
    		register_post_type( dpa_get_progress_post_type(), $progresses );
    	}

    Also, replace the achievement_with_category_edit_columns and achievement_with_category_custom_column functions with the following code. It has been updated to make the column name more unique, so as not to conflict with the normal categories in wordpress:

    function achievement_with_category_edit_columns($columns)
    	{
    		$column_position = 3; //choose what position you want the categories to be added
    		$columns_first = array_slice($columns, 0, $column_position - 1, true );
    		$columns_last = array_slice($columns, $column_position - 1, null, true );
    		$columns = array_merge(
    			$columns_first,
    			array('achievement_category' => _x('Category', 'Achievement category', 'dpa')),
    			$columns_last
    		);
    
    		return $columns;
    	}
    	add_filter("manage_edit-achievement_columns", "achievement_with_category_edit_columns");
    
    	function achievement_with_category_custom_columns( $column )
    	{
    		switch( $column )
    		{
    			case "achievement_category":
    				echo get_the_term_list( $post->ID, 'dpa_achievement_category', '', ', ', '' );
    				break;
    		}
    	}
    	add_action("manage_posts_custom_column", "achievement_with_category_custom_columns");

    Also add the following code to your functions.php in your child theme to make the achievement category column sortable:

    function dpa_achievement_sortable_category_column( $columns )
    	{
    		$columns['achievement_category'] = 'dpa_achievement_category';
    
    		return apply_filters('dpa_achievement_sortable_columns', $columns);
    	}
    	add_filter('manage_edit-achievement_sortable_columns', 'dpa_achievement_sortable_category_column');
    
    	function dpa_achievement_category_column_sorting( $vars )
    	{
    		if( isset($vars['orderby']) && 'achievement_category' == $vars['orderby'] )
    		{
    			$vars = array_merge($vars, array('meta_key' => 'dpa_achievement_category', 'orderby'  => 'meta_value'));
    		}
    		return $vars;
    	}
    	add_filter('requests', 'dpa_achievement_category_column_sorting');

    Thread Starter mikebronner

    (@mikebronner)

    Update 3: (How I wish we could update our threads instead of having this mess of additional posts, but nevertheless, here goes.)
    Updated register_achievements_post_type_override() function yet again, as the capabilities of the post type need to be reset (they are getting corrupted when they are queried, information is missing):

    function register_achievements_post_type_override()
    	{
    		global $wp_post_types;
    
    		$achievements = objectToArray(get_post_types(array('name'=>dpa_get_achievement_post_type()), 'objects'));
    		$progresses = objectToArray(get_post_types(array('name'=>dpa_get_progress_post_type()), 'objects'));
    
    		$achievements = $achievements[dpa_get_achievement_post_type()];
    		$progresses = $progresses[dpa_get_progress_post_type()];
    
    		$achievements["taxonomies"] = array('dpa_achievement_category');
    		$progresses["taxonomies"] = array('dpa_achievement_category');
    		$achievements["capabilities"] = dpa_get_achievement_caps();
    		$progresses["capabilities"] = dpa_get_achievement_progress_caps();
    
    		unset($wp_post_types[dpa_get_achievement_post_type()]);
    		unset($wp_post_types[dpa_get_progress_post_type()]);
    
    		register_post_type( dpa_get_achievement_post_type(), $achievements );
    		register_post_type( dpa_get_progress_post_type(), $progresses );
    	}

    Thread Starter mikebronner

    (@mikebronner)

    Update 4: Updated user profile admin page to group achievements by category for better overview and grouping. Add the following code to you functions.php in your child theme:

    /* Group Achievements by Category in User Profile *****************************/
    	function dpa_achievements_add_profile_fields_with_categories($user)
    	{
    		if (!is_super_admin()) {return;}
    ?>
    		<h3><?php _e( 'Achievements Settings', 'dpa' ); ?></h3>
    		<table class="form-table">
    			<tr>
    				<th><label for="dpa_achievements"><?php _ex( 'Total Points', "User&rsquo;s total points from unlocked Achievements", 'dpa' ); ?></label></th>
    				<td><input type="number" name="dpa_achievements" id="dpa_achievements" value="<?php echo esc_attr( dpa_get_user_points( $user->ID ) ); ?>" class="regular-text" />
    				</td>
    			</tr>
    <?php
    		if ( dpa_has_achievements_custom( array( 'ach_populate_progress' => $user->ID, 'ach_progress_status' => dpa_get_unlocked_status_id(), 'posts_per_page' => -1, "orderby"=>"konb_term_relationships.term_taxonomy_id",) ) )
    		{
    ?>
    			<tr>
    				<th scope="row"><?php _e( 'Unlocked Achievements', 'dpa' ); ?></th>
    				<td>
    					<fieldset>
    						<legend class="screen-reader-text"><?php _e( 'Assign or remove achievements from this user', 'dpa' ); ?></legend>
    <?php
    			$previous_achievment_category = "";
    			while ( dpa_achievements() )
    			{
    				dpa_the_achievement();
    				$current_category = "";
    				$categories = get_the_terms($post_id, 'dpa_achievement_category');
    				foreach($categories as $category)
    				{
    					if (strlen($current_category) > 0)
    					{
    						$current_category .= ", ";
    					}
    					$current_category .= $category->name;
    				}
    
    				if ($current_category != $previous_achievment_category)
    				{
    					if ($previous_achievment_category != "")
    					{
    ?>
    						<br />
    <?php
    					}
    					$previous_achievment_category = $current_category;
    ?>
    
    						<strong><?php echo $current_category; ?>:</strong><br />
    <?php
    				}
    
    ?>
    						<label><input type="checkbox" name="dpa_user_achievements[]" value="<?php echo esc_attr( dpa_get_the_achievement_ID() ); ?>" <?php checked( dpa_is_achievement_unlocked(), true ); ?>> <?php dpa_achievement_title(); ?></label><br />
    <?php
    			}
    ?>
    
    					</fieldset>
    				</td>
    			</tr>
    <?php
    		}
    ?>
    		</table>
    <?php
    		remove_action('edit_user_profile', array(achievements()->admin, 'add_profile_fields'));
    	}
    	add_action('edit_user_profile', 'dpa_achievements_add_profile_fields_with_categories', 9);

    pmcvicker

    (@pmcvicker)

    A big +1 for this. Categories means I can display a sweet, filterable achievement catalog like this for my users via Themefluent’s Ajax Content Navigator, which will be handy with the 150+ achievements we’re going to have (just 3 sample ones loaded right now). Kudos to you!

    Plugin Author Paul Wong-Gibbs

    (@djpaul)

    That’s the first useful argument for categories with Achievements. You are doing groundbreaking work with TSC, pmcvicker 🙂

    Thread Starter mikebronner

    (@mikebronner)

    Oh, so my reasons weren’t valid?! Hmmmpf 🙂 j/k

    Nice achievements catalog, pmcvicker! I will be creating something similar eventually as well. Thanks for the example, it’s inspiring. 🙂

    Plugin Author Paul Wong-Gibbs

    (@djpaul)

    A picture’s worth a thousand words 😉

    Thread Starter mikebronner

    (@mikebronner)

    You’re right, I never did post my example here:
    http://konb.info/forums/users/mike-bronner/

    The first goal was to group the various achievements together to organize them.
    The second goal will be in connection with dependent achievements to essentially build an achievements tree showing which ones you have earned, and what it takes to earn the others.

    Additional categories will include Ranks and Offices.

    Plugin Author Paul Wong-Gibbs

    (@djpaul)

    Ah hah. Neat.

    Ok, let’s figure out how to add category support into a future release 🙂

    Thread Starter mikebronner

    (@mikebronner)

    Excellent, I’ll make a branch for it.

    Mike, I have been lurking the site you have created and want to create something similar such as your badges, icons, achievement page and leaderboard. Did you do the graphics yourself? I think I can follow your instructions for the leaderboard, and I will need to get someone else to create my graphics. How did you put together this template/page http://challengebeta.mypcls.org/achievements/a-tale-for-every-tail/

    Thread Starter mikebronner

    (@mikebronner)

    Hi wickstim,
    Actually the site you are looking at belongs to pmcvicker. It appears that he modified the CSS for the achievement detail view.

    Plugin Author Paul Wong-Gibbs

    (@djpaul)

    Categories have been added to Achievements for the upcoming 3.3 release.

Viewing 15 replies - 1 through 15 (of 16 total)
  • The topic ‘How-To: Achievement Categories’ is closed to new replies.