Portfolio Press has always used custom post types to display portfolio content. When the theme was released in 2010 this was a novel way to do it (custom post types had just been released in WordPress 3.0).
Post types allowed the portfolio to be styled differently, use different templates, and keep portfolio content separate from standard content. In the dark ages before WordPress 3.0, developers had only achieved this by requiring users to post in a pre-defined category or tag.
But since WordPress 3.4 we’ve had post formats like “gallery” and “image” which are now supported by most new themes. With the latest version of Portfolio Press, I wanted users to be able to choose which to use. Post formats are the new default, but users can install the Portfolio Post Type plugin and use post types instead if they choose.
To save a lot of duplication in template code and styling, I used a bit of template hijacking and a few other useful styling tricks. I doubt anyone is working on this exact same issue, but I think some of the ideas might be useful for other applications.
Reusing Template Files
These are all the views that require “portfolio” styling:
is_post_type_archive( 'portfolio' ) is_page_template( 'templates/portfolio.php' ) is_page_template( 'templates/full-width-portfolio.php' ) is_page_template( 'templates/post-format-gallery-image.php' ) is_tax( 'post_format', 'post-format-image' ) is_tax( 'post_format', 'post-format-gallery' ) is_tax( 'portfolio_category' ) is_tax( 'portfolio_tag' )
Since they are all essentially archive views it makes sense to have them use the same template- but by default they will look for different ones. (Read more about template hierarchy in WordPress.)
is_post_type_archive( 'portfolio' ) -> archive-portfolio.php is_tax( 'post_format', 'post-format-image' ) -> taxonomy-post_format-image.php is_tax( 'post_format', 'post-format-gallery' ) -> taxonomy-post_format-gallery.php is_tax( 'portfolio_category' ) -> taxonomy-portfolio_category.php is_tax( 'portfolio_tag' ) -> taxonomy-portfolio_tag.php
To avoid having to create separate template files, I used template_include filter (thanks to Bill Erickson for the original idea). This is the template hijacking I referred to, and it works like this:
function portfoliopress_template_chooser( $template ) { if ( is_tax( 'portfolio_tag' ) || is_tax( 'portfolio_category' ) ) $template = get_query_template( 'archive-portfolio' ); if ( is_tax( 'post_format', 'post-format-image' ) || is_tax( 'post_format', 'post-format-gallery' ) ) $template = get_query_template( 'archive-portfolio' ); return $template; } add_filter( 'template_include', 'portfoliopress_template_chooser' );
Now all the taxonomies pull from the same archive-portfolio.php file.
Common Body Classes
The portfolio view requires it’s own unique styling. This is difficult since page templates are being used in some places and archive-portfolio.php in others. The easiest way I found was to apply a common body class ‘portfolio-view’ using the body_class filter:
function portfoliopress_body_class( $classes ) { if ( is_post_type_archive( 'portfolio' ) || is_page_template( 'templates/portfolio.php' ) || is_page_template( 'templates/full-width-portfolio.php' ) || is_page_template( 'templates/post-format-gallery-image.php' ) || is_tax( 'post_format', 'post-format-image' ) || is_tax( 'post_format', 'post-format-gallery' ) || is_tax( 'portfolio_category' ) || is_tax( 'portfolio_tag' ) ) { $classes[] = 'portfolio-view'; } return $classes; } add_filter( 'body_class','portfoliopress_body_class' );
Changing the Query
One final issue is that each portfolio view needed to display just 9 items. The images are displayed in 3 columns, so if the default 10 were displayed there would always be one hanging at the bottom.
To alter the query on all these templates, I used the pre_get_posts filter. Here’s how it works:
function portfoliopress_portfolio_posts( $query ) { if ( is_post_type_archive( 'portfolio' ) || is_page_template( 'templates/portfolio.php' ) || is_page_template( 'templates/full-width-portfolio.php' ) || is_page_template( 'templates/post-format-gallery-image.php' ) || is_tax( 'post_format', 'post-format-image' ) || is_tax( 'post_format', 'post-format-gallery' ) || is_tax( 'portfolio_category' ) || is_tax( 'portfolio_tag' ) ) { $posts_per_page = apply_filters( 'portfoliopress_posts_per_page', of_get_option('portfolio_num','9') ); $query->set( 'posts_per_page', $posts_per_page ); } } add_action( 'pre_get_posts', 'portfoliopress_portfolio_posts' );
Conclusions
Reusing templates and styling can be a bit tricky to think through- but it can save a ton of code duplication. If you want to see how all this works in a theme, check out Portfolio Press on GitHub.
Sounds exciting. Will we see these updates in Portfolio+ soon, too? :)