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();