Or, embed this snippet using GenerateWP WordPress Plugin.

Download

Clone

GWP Simple Post Series final calls

A plugin to add posts series as a part to the GWP tutorial https://generatewp.com/group-post-series-custom-taxonomy

/*
Plugin Name: GWP Simple Post Series
Plugin URI: https://generatewp.com/group-post-series-custom-taxonomy
Description: A plugin to add posts series as a part to the GWP tutorial https://generatewp.com/group-post-series-custom-taxonomy
Version: 1.0
Author: Ohad Raz
Author URI: https://generatewp.com
*/
/*
* GWP_Post_Series
*/
class GWP_Post_Series{
	
	/*
	 * $tax_name 
	 * used to avoid writing post series
	 * taxonomy name over and over.
	 * @var string
	 */
	public $tax_name = 'GWP_post_series';

	/*
	 * __construct 
	 * Class constructor
	 */
	function __construct(){
		add_action( 'plugins_loaded', array( $this, 'hooks' ) );
	}

	/*
	 * hooks
	 * Used to hook all our functions
	 * @return void
	 */
	function hooks(){
		add_action( 'init', array( $this, 'register_post_series_taxonomy') );
		if (! is_admin() ){
			add_filter( 'the_content', array( $this, 'the_content' ), 35 );	
		}
	}

	/*
	 * register_post_series_taxonomy
	 * this will be generated using our Taxonomy generator
	 * @return void
	 */
	function register_post_series_taxonomy() {

		$labels = array(
			'name'                       => _x( 'Post Series', 'Taxonomy General Name', 'GWP_simple_post_series' ),
			'singular_name'              => _x( 'Post Series', 'Taxonomy Singular Name', 'GWP_simple_post_series' ),
			'menu_name'                  => __( 'Post Series', 'GWP_simple_post_series' ),
			'all_items'                  => __( 'All Post Series', 'GWP_simple_post_series' ),
			'parent_item'                => __( 'Parent Post Series', 'GWP_simple_post_series' ),
			'parent_item_colon'          => __( 'Parent Post Series:', 'GWP_simple_post_series' ),
			'new_item_name'              => __( 'New Post Series Name', 'GWP_simple_post_series' ),
			'add_new_item'               => __( 'Add New Post Series', 'GWP_simple_post_series' ),
			'edit_item'                  => __( 'Edit Post Series', 'GWP_simple_post_series' ),
			'update_item'                => __( 'Update Post Series', 'GWP_simple_post_series' ),
			'view_item'                  => __( 'View Post Series', 'GWP_simple_post_series' ),
			'separate_items_with_commas' => __( 'Separate Post Series with commas', 'GWP_simple_post_series' ),
			'add_or_remove_items'        => __( 'Add or remove Post Series', 'GWP_simple_post_series' ),
			'choose_from_most_used'      => __( 'Choose from the most used', 'GWP_simple_post_series' ),
			'popular_items'              => __( 'Popular Post Series', 'GWP_simple_post_series' ),
			'search_items'               => __( 'Search Post Series', 'GWP_simple_post_series' ),
			'not_found'                  => __( 'Not Found', 'GWP_simple_post_series' ),
			'no_terms'                   => __( 'No Post Series', 'GWP_simple_post_series' ),
			'items_list'                 => __( 'Post Series list', 'GWP_simple_post_series' ),
			'items_list_navigation'      => __( 'Post Series list navigation', 'GWP_simple_post_series' ),
		);
		$rewrite = array(
			'slug'                       => 'series',
			'with_front'                 => true,
			'hierarchical'               => false,
		);
		$args = array(
			'labels'                     => $labels,
			'hierarchical'               => false,
			'public'                     => true,
			'show_ui'                    => true,
			'show_admin_column'          => true,
			'show_in_nav_menus'          => true,
			'show_tagcloud'              => false,
			'rewrite'                    => $rewrite,
		);
		register_taxonomy( 'GWP_post_series', array( 'post' ), $args );
	}

	/*
	 * the_content
	 * Used to add the post series box to the single post view
	 * @param  string $content post content
	 * @return string 
	 */
	function the_content( $content = null ){
		global $post;
		//bail out if not single post or no post series was found
		if ( ! is_single() && ! $this->has_post_series( $post->id ) ){
			return $content;
		}

		//get post series taxonomy term
		$series = $this->get_post_series( $post->ID );
		//if no series was found return the content
		if ( false == $series || ! isset( $series->term_id ) ){
			return $content;
		}

		//get posts in series
		$posts_in_series = $this->get_posts_in_series( $series->term_id );
		//if no posts were found in series return the content
		if ( false == $posts_in_series ){
			return $content;
		}

		//get post series box
		$series_box = $this->create_post_series_box( $post->ID, $posts_in_series, $series );

		//return the content with the post series on top (filterable)
		return apply_filters( 'GWP_series_content', $series_box.$content, $content, $series_box, $series, $posts_in_series, $post );
	}

	/*
	 * has_post_series 
	 * used to determine if a post is a part of a post series
	 * @param  int  $post_id  post ID
	 * @return boolean        true if the post is a part of a post series
	 */
	function has_post_series( $post_id ){
		return has_term('', $this->tax_name, $post_id);
	}

	/*
	 * get_posts_in_series
	 * Get post ids of posts in a series by series ID 
	 * @param  int $series_id series term ID
	 * @return array|boolean  array of post IDs or false if none found 
	 */
	function get_posts_in_series( $series_id ){
		$args = array(
			//get both published and future posts (filterable)
			'post_status'    => apply_filters('GWP_series_post_status', array('publish','future') ),
			//number of posts to list (filterable)
			'posts_per_page' => apply_filters('GWP_series_post_limit', 8 ),
			//order by date
			'orderby'        => 'date',
			//Ascending order
			'order'          => 'ASC',
			//we only need the IDs of the posts
			'fields'         => 'ids',
			//tax query this is where we tell WordPress to select posts grouped by our taxonomy
			'tax_query'      => array(
				array(
					'taxonomy' => $this->tax_name, 
					'field'    => 'term_id', 
					'terms'    => $series_id
				)
			)
		);

		//select all posts in series
		$posts = new WP_Query( 
			apply_filters('GWP_series_get_posts_args', $args, $series_id ) //allow filtering of arguments 
		);

		//check if any posts were found
		if ( $posts->have_posts() ){
			//posts were found in the series so we return them
			return $posts->posts;
		}else{
			//no posts were found so we return false;
			return false;
		}
	}

	/*
	 * get_post_series
	 * Get post series term object by post ID
	 * @param  int $post_id post ID
	 * @return WP_Term|boolean  series term object if found or false if not.
	 */
	function get_post_series( $post_id ){
		$series = wp_get_post_terms( $post_id, $this->tax_name );
		if ( ! is_wp_error( $series ) ){
			return $series[0];
		}
		return false;
	}

	/*
	 * create_post_series_box
	 * Create post series box html markup
	 * @param  int 		$current_id      	current post ID.
	 * @param  array 	$posts_in_series 	array of post IDs.
	 * @param  WP_Term 	$series          	Post Series taxonomy term.
	 * @return string 						HTML markup of post series box
	 */
	function create_post_series_box( $current_id, $posts_in_series, $series ){
		//box template (filterable)
		$template = apply_filters( 'GWP_series_box_template', '
			<div id="post-series">
				<div class="series-title">Post Series: {series_title}</div>
				{series_list}
			</div>
		');

		//list tag (filterable) 
		$list_tag = apply_filters( 'GWP_series_list_tag', 'ul' );
		
		//create an array of all posts in series as li tags
		$items = array();
		foreach ( $posts_in_series as $id ) {
			$title = get_the_title( $id );
			if ( $id == $current_id ){
				//this is the current post so no link anchor tag is needed
				$items[] = '<li class="current series-item">' . $title .'</li>';	
			}else{
				$items[] = '<li class="series-item"><a title="'.esc_attr( $title ).'" href="' .get_permalink( $id ) .'">' . $title .'</a></li>';
			}
		}
		//connect the items to a list
		$list = '<' . $list_tag .'>' . implode( "n", $items ). '</'. $list_tag .'>'; 

		//array of template tokens
		$search = array(
			'{series_id}',
			'{series_slug}',
			'{series_title}',
			'{series_description}',
			'{series_url}',
			'{series_list}'
		);

		//array of token replacements
		$replace = array(
			$series->term_id,
			$series->slug,
			$series->name,
			$series->description,
			get_term_link( $series, $this->tax_name ),
			$list
		);

		//replace tokens in template with actual data
		$box = str_replace( $search, $replace, $template );

		//return box html (filterable)
		return apply_filters( 'GWP_series_box', $box, $current_id, $posts_in_series, $series );
	} 
}
new GWP_Post_Series();