I need to add a custom “cover” to every new post — plugin or custom setup?

I’m creating a site that’s basically like an online book, and every post is a chapter. Each chapter gets a customized, specially designed “cover” page that can’t really be designed in the WordPress WYSIWYG. There are certain aspects of each cover that can be templatized (like an h1, h2, and single paragraph — every chapter will have that) but everything else is going to be special to each chapter. This “cover” will also have specific CSS only relevant to this chapter.

Ideally I’ll be able to design and code these covers outside of WordPress and somehow be able to inform each post which cover to use. Whether that means WordPress actually imports that code or simply includes it with a php include doesn’t much matter to me. I’d just like this to be as streamlined as possible.

Read More

Suggestions?

Related posts

Leave a Reply

2 comments

  1. Another solution, that doesn’t invoke page attributes:

    Explanation: To-Do List

    Go and download the RW_Meta_Box Library. I’m one of the authors/contributers.

    The Plugins

    Here you can see two small plugins (which I wrote especially for your question).

    Input

    The first one is a dependency of the RW Meta Box library. You just change what you need (User cap checks) and upload it to your plugins folder. The change you need to make is pretty simple: Search for the right User Role or Capability and add it where you currently can read 'edit_theme_options'. It should match your designers capability but not your authors.

    It adds two textarea meta boxes.

    <?php
    ! defined( 'ABSPATH' ) AND exit;
    /** Plugin Name: (#65707) »kaiser« Add Meta Boxes */
    
    function wpse65707_add_meta_boxes()
    {
        // Don't add it for all users, but only for your designers
        if (
            ! current_user_can( 'edit_theme_options' ) # CHANGE ME!!!
            OR ! class_exists( 'RW_Meta_Box' )
        )
            return;
    
        $prefix = 'wpse65707_';
        $meta_boxes[] = array(
            // Meta box id, UNIQUE per meta box
             'id' => 'cover'
            // Meta box title - Will appear at the drag and drop handle bar
            ,'title' => 'Designers Space'
            // Post types, accept custom post types as well - DEFAULT is array('post'); (optional)
            ,'pages' => array( 'post' )
            // Where the meta box appear: normal (default), advanced, side; optional
            ,'context' => 'normal'
            // Order of meta box: high (default), low; optional
            ,'priority' => 'high'
            // List of meta fields
            ,'fields' => array(
                array(
                     'name' => 'Styles'
                    ,'desc' => "Only valid CSS here"
                    ,'id'   => "{$prefix}styles"
                    ,'type' => 'textarea'
                    ,'std'  => "h1 { color: #009ee0; }"
                    ,'cols' => "40"
                    ,'rows' => "8"
                ),
                array(
                     'name' => 'MarkUp'
                    ,'desc' => "Only valid HTML here"
                    ,'id'   => "{$prefix}markup"
                    ,'type' => 'textarea'
                    ,'std'  => "<h1>Hello Me!</h1>"
                    ,'cols' => "40"
                    ,'rows' => "8"
                )
            )
        );
    
        # Add additional Meta Boxes here.
        # For example a drop-down with a list of users that
        # have a custom role of "Designer"
        # (Hint) Use the "Members" plugin for that and 
        # WP_User_Query to get the users as values
    
        foreach ( $meta_boxes as $meta_box )
            new RW_Meta_Box( $meta_box );
    }
    # Performance: Only load on post edit & new admin UI screens.
    add_action( 'load-post-new.php', 'wpse65707_add_meta_boxes' );
    add_action( 'load-post.php', 'wpse65707_add_meta_boxes' );
    

    Output

    This one now cares about our output.

    The 1st task it has is adding our styles to the wp_head-hook. This way, we have the possibility to inject whatever custom style the Designer adds.

    The 2nd thing it does is adding the current post ID to the post_class filter for the post_class(); template tag. This way, we can easily target only our current post content and nothing aside it.

    The 3rd functionality is a parser. This parser allows your designers to add template tags via an abstraction layer: Custom %Template Tags%. So everything that is defined inside the wpse65707_custom_post_styles_parser will be replaced with the set template tag. The function itself is a filter callback for the_content, so you don’t really have to change anything to get it working with whatever theme you’re using.

    <?php
    ! defined( 'ABSPATH' ) AND exit;
    /** Plugin Name: (#65707) »kaiser« Custom Post Styles */
    
    // Add custom styles to the `wp_head` hook in the header.php file.
    function wpse65707_custom_post_styles()
    {
        $styles = get_post_meta( get_the_ID(), 'wpse65707_styles', true );
        $styles = str_replace( 
             '%ID%'
            ,get_the_ID()
            ,$styles
        );
    
        return print "<style type='text/css>{$styles}</style>";
    }
    add_action( 'wp_head', 'wpse65707_custom_post_styles' );
    
    // Add the plain ID to the post classes for easier styling
    // Prevents overriding everything else outside
    function wpse65707_post_class ( $classes )
    {
        $classes[] = get_the_ID();
        return $classes;
    } 
    add_filter ( 'post_class' , 'wpse65707_post_class' );
    
    // Parse the content to add Template tags on the fly
    function wpse65707_custom_post_styles_parser( $content )
    {
        $markup = get_post_meta( get_the_ID(), 'wpse65707_markup', true );
        return strtr(
             $markup
            ,array(
                 '%CONTENT%' => $content
                ,'%AUTHOR%'  => get_the_author()
                // Add other template tags here
             )
        );
    }
    add_filter( 'the_content', 'wpse65707_custom_post_styles_parser' );
    

    Templates: single.php & header.php

    The only things that are important to get this working with a theme are the following template tags inside those two files:

    • header.php must have a wp_head() tag.
    • single.php must use the post_class(); function on the post container div/article HTML tag.
    • single.php must use the_content(); to display its content.

    How does it work now?

    It’s easy: Every template tag, that is allowed inside wpse65707_custom_post_styles_parser(), will be exchanged with what your designer wrote.

    // Example content for the "MarkUp"-Meta Box
    <h1>Hello Me!</h1>
    <h2>A fairy tale by %AUTHOR%</h2>
    This is story of love and joy.
    %CONTENT%
    <p>We hope you liked it.</p>
    

    Now %CONTENT% gets replaced with the actual post content and %AUTHOR%, with the authors display name. Feel free to extend it.

    Important is the only tag, that your designers should use to prefix their styles: The %ID% tag. This makes sure, that they aren’t targeting anything outside the current article container.

    That’s all folks!

  2. Custom MarkUp: Post Templates

    Use Page Templates.

    function wpse65707_post_templates()
    {
       add_post_type_support( 'post', 'page-attributes' );
    }
    add_action( 'init', 'wpse65707_post_templates' );
    

    Then simply upload a new template for each custom layout.

    Custom Look: Conditional Styles

    To add css to a post, just add a new stylesheet, that you enqueue only for that page.

    function wpse65707_single_styles()
    {
        if ( ! is_single() )
            return;
    
        wp_enqueue_style(
             'style_'.get_the_ID()
            ,get_stylesheet_directory_uri().'/single-styles/style-'.get_the_ID().'.css'
            ,array()
            ,filemtime( get_stylesheet_directory().'/single-styles/style-'.get_the_ID().'.css' )
        );
    }
    add_action( 'wp_enqueue_scripts', 'wpse65707_single_styles' );
    

    This way, you simply can add a folder named ~/single-styles to your theme and then add a file named style-IDHERE.css to that folder that only enqueues for that page. So it’s something along the line of contextual stylesheets.

    Have fun!