Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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.

Suggestions?

share|improve this question
    
Is the cover intended to be a separate page from the post content? –  supertrue Sep 20 '12 at 1:04
    
No, it's essentially a DIV set to 100% width and height. The post content is below. So, in the end it will be code that is either imported/included in the post page (ideal), manually pasted into the post in a custom field (not ideal), or loaded via ajax (also not ideal). –  Brandon Durham Sep 20 '12 at 1:10
    
@BrandonDurham I wrote you two solutions. The second is a pretty complete one. Hope this was what you were searching for. –  kaiser Sep 20 '12 at 13:03
add comment

2 Answers

up vote 2 down vote accepted

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!

share|improve this answer
    
Amazing. Thank you!! –  Brandon Durham Sep 22 '12 at 1:11
    
@BrandonDurham You're welcome. Would be nice to have a link to the final outcome. –  kaiser Sep 22 '12 at 12:04
add comment

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!

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.