* @copyright Copyright (c) 2010 - 2013, Justin Tadlock * @link http://justintadlock.com * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ /* Register metadata with WordPress. */ add_action( 'init', 'post_stylesheets_register_meta' ); /* Add post type support for the 'post-stylesheets' feature. */ add_action( 'init', 'post_stylesheets_add_post_type_support' ); add_action( 'init', 'post_stylesheets_remove_post_type_support' ); /* Filters stylesheet_uri with a function for adding a new style. */ add_filter( 'stylesheet_uri', 'post_stylesheets_stylesheet_uri', 10, 2 ); /* Admin setup for the 'post-stylesheets' feature. */ add_action( 'admin_menu', 'post_stylesheets_admin_setup' ); /** * Registers the post stylesheets meta key ('Stylesheet') for posts and provides a function to sanitize * the metadata on update. * * @since 0.3.0 * @access public * @return void */ function post_stylesheets_register_meta() { register_meta( 'post', post_stylesheets_get_meta_key(), 'post_stylesheets_sanitize_meta' ); } /** * Callback function for sanitizing meta when add_metadata() or update_metadata() is called by WordPress. * If a developer wants to set up a custom method for sanitizing the data, they should use the * "sanitize_{$meta_type}_meta_{$meta_key}" filter hook to do so. * * @since 0.3.0 * @access public * @param mixed $meta_value The value of the data to sanitize. * @param string $meta_key The meta key name. * @param string $meta_type The type of metadata (post, comment, user, etc.) * @return mixed $meta_value */ function post_stylesheets_sanitize_meta( $meta_value, $meta_key, $meta_type ) { return esc_attr( strip_tags( $meta_value ) ); } /** * Adds post type support for the 'post-stylesheets' feature to all 'public' post types. * * @since 0.3.0 * @access public * @return void */ function post_stylesheets_add_post_type_support() { /* Get all available 'public' post types. */ $post_types = get_post_types( array( 'public' => true ) ); /* Loop through each of the public post types and add support for post stylesheets. */ foreach ( $post_types as $type ) add_post_type_support( $type, 'post-stylesheets' ); } /** * Removes post stylesheets support for certain post types created by plugins. * * @since 0.3.0 * @access public * @return void */ function post_stylesheets_remove_post_type_support() { /* Removes post stylesheets support of the bbPress 'topic' post type. */ if ( function_exists( 'bbp_get_topic_post_type' ) ) remove_post_type_support( bbp_get_topic_post_type(), 'post-stylesheets' ); /* Removes post stylesheets support of the bbPress 'reply' post type. */ if ( function_exists( 'bbp_get_reply_post_type' ) ) remove_post_type_support( bbp_get_reply_post_type(), 'post-stylesheets' ); } /** * Checks if a post (or any post type) has the given meta key of 'Stylesheet' when on the singular view of * the post on the front of the site. If found, the function checks within the '/css' folder of the stylesheet * directory (child theme) and the template directory (parent theme). If the file exists, it is used rather * than the typical style.css file. * * @since 0.1.0 * @todo Use features from Ticket #18302 when available. http://core.trac.wordpress.org/ticket/18302 * @access public * @param string $stylesheet_uri The URI of the active theme's stylesheet. * @param string $stylesheet_dir_uri The directory URI of the active theme's stylesheet. * @return string $stylesheet_uri */ function post_stylesheets_stylesheet_uri( $stylesheet_uri, $stylesheet_dir_uri ) { /* Check if viewing a singular post. */ if ( is_singular() ) { /* If viewing a bbPress topic, use its forum object. */ if ( function_exists( 'bbp_is_single_topic' ) && bbp_is_single_topic() ) $post = get_post( bbp_get_topic_forum_id( get_queried_object_id() ) ); /* If viewing a bbPress reply, use its forum object. */ elseif ( function_exists( 'bbp_is_single_reply' ) && bbp_is_single_reply() ) $post = get_post( bbp_get_reply_forum_id( get_queried_object_id() ) ); /* Get the queried object (post). */ else $post = get_queried_object(); /* Check if the post type supports 'post-stylesheets' before proceeding. */ if ( post_type_supports( $post->post_type, 'post-stylesheets' ) ) { /* Check if the user has set a value for the post stylesheet. */ $stylesheet = get_post_stylesheet( $post->ID ); /* If a meta value was given and the file exists, set $stylesheet_uri to the new file. */ if ( !empty( $stylesheet ) ) { /* If the stylesheet is found in the child theme, use it. */ if ( file_exists( trailingslashit( get_stylesheet_directory() ) . $stylesheet ) ) { $stylesheet_uri = trailingslashit( $stylesheet_dir_uri ) . $stylesheet; } /* Else, if the stylesheet is found in the parent theme, use it. */ elseif ( file_exists( trailingslashit( get_template_directory() ) . $stylesheet ) ) { $stylesheet_uri = trailingslashit( get_template_directory_uri() ) . $stylesheet; } /* @deprecated 0.4.0 Back compatibility. */ else { /* If the stylesheet is found in the child theme '/css' folder, use it. */ if ( file_exists( trailingslashit( get_stylesheet_directory() ) . "css/{$stylesheet}" ) ) { $stylesheet_uri = trailingslashit( $stylesheet_dir_uri ) . "css/{$stylesheet}"; /* Set the post stylesheet to the correct directory. */ set_post_stylesheet( $post->ID, str_replace( get_stylesheet_directory_uri(), 'css/', $stylesheet_uri ) ); } /* Else, if the stylesheet is found in the parent theme '/css' folder, use it. */ elseif ( file_exists( trailingslashit( get_template_directory() ) . "css/{$stylesheet}" ) ) { $stylesheet_uri = trailingslashit( get_template_directory_uri() ) . "css/{$stylesheet}"; /* Set the post stylesheet to the correct directory. */ set_post_stylesheet( $post->ID, str_replace( get_template_directory_uri(), 'css/', $stylesheet_uri ) ); } } } } } /* Return the stylesheet URI. */ return $stylesheet_uri; } /** * Returns the post stylesheet if one is saved as post metadata. * * @since 0.3.0 * @access public * @param int $post_id The ID of the post to get the stylesheet for. * @return string Stylesheet name if given. Empty string for no stylesheet. */ function get_post_stylesheet( $post_id ) { return get_post_meta( $post_id, post_stylesheets_get_meta_key(), true ); } /** * Adds/updates the post stylesheet for a specific post. * * @since 0.3.0 * @access public * @param int $post_id The ID of the post to set the stylesheet for. * @param string $stylesheet The filename of the stylesheet. * @return bool True on successful update, false on failure. */ function set_post_stylesheet( $post_id, $stylesheet ) { return update_post_meta( $post_id, post_stylesheets_get_meta_key(), $stylesheet ); } /** * Deletes a post stylesheet. * * @since 0.3.0 * @access public * @param int $post_id The ID of the post to delete the stylesheet for. * @return bool True on successful delete, false on failure. */ function delete_post_stylesheet( $post_id ) { return delete_post_meta( $post_id, post_stylesheets_get_meta_key() ); } /** * Checks if a post has a specific post stylesheet. * * @since 0.3.0 * @access public * @param string $stylesheet The filename of the stylesheet. * @param int $post_id The ID of the post to check. * @return bool True|False depending on whether the post has the stylesheet. */ function has_post_stylesheet( $stylesheet, $post_id = '' ) { /* If no post ID is given, use WP's get_the_ID() to get it and assume we're in the post loop. */ if ( empty( $post_id ) ) $post_id = get_the_ID(); /* Return true/false based on whether the stylesheet matches. */ return ( $stylesheet == get_post_stylesheet( $post_id ) ? true : false ); } /** * Admin setup for the post stylesheets script. * * @since 0.3.0 * @access public * @return void */ function post_stylesheets_admin_setup() { /* Load the post meta boxes on the new post and edit post screens. */ add_action( 'load-post.php', 'post_stylesheets_load_meta_boxes' ); add_action( 'load-post-new.php', 'post_stylesheets_load_meta_boxes' ); } /** * Hooks into the 'add_meta_boxes' hook to add the post stylesheets meta box and the 'save_post' hook * to save the metadata. * * @since 0.3.0 * @access public * @return void */ function post_stylesheets_load_meta_boxes() { /* Add the post stylesheets meta box on the 'add_meta_boxes' hook. */ add_action( 'add_meta_boxes', 'post_stylesheets_create_meta_box', 10, 2 ); /* Saves the post meta box data. */ add_action( 'save_post', 'post_stylesheets_meta_box_save', 10, 2 ); add_action( 'add_attachment', 'post_stylesheets_meta_box_save' ); add_action( 'edit_attachment', 'post_stylesheets_meta_box_save' ); } /** * Adds the post stylesheets meta box if the post type supports 'post-stylesheets' and the current user has * permission to edit post meta. * * @since 0.2.0 * @access public * @param string $post_type The post type of the current post being edited. * @param object $post The current post object. * @return void */ function post_stylesheets_create_meta_box( $post_type, $post ) { /* Get the post styles. */ $styles = post_stylesheets_get_styles( $post_type ); /* If there are no post styles, don't show the meta box. */ if ( empty( $styles ) ) return; /* Add the meta box if the post type supports 'post-stylesheets'. */ if ( ( post_type_supports( $post_type, 'post-stylesheets' ) ) && ( current_user_can( 'edit_post_meta', $post->ID ) || current_user_can( 'add_post_meta', $post->ID ) || current_user_can( 'delete_post_meta', $post->ID ) ) ) add_meta_box( "post-stylesheets", __( 'Stylesheet', 'post-stylesheets' ), 'post_stylesheets_meta_box', $post_type, 'side', 'default' ); } /** * Displays the input field for entering a custom stylesheet. * * @since 0.2.0 * @access public * @param object $object The post object currently being edited. * @param array $box Specific information about the meta box being loaded. * @return void */ function post_stylesheets_meta_box( $object, $box ) { ?>

post_type ); ?>

post_type, 'post-stylesheets' ) ) return; /* Get the meta key. */ $meta_key = post_stylesheets_get_meta_key(); /* Get the previous post stylesheet. */ $meta_value = get_post_stylesheet( $post_id ); /* Get the submitted post stylesheet. */ $new_meta_value = $_POST['post-stylesheets']; /* If there is no new meta value but an old value exists, delete it. */ if ( current_user_can( 'delete_post_meta', $post_id, $meta_key ) && '' == $new_meta_value && $meta_value ) delete_post_stylesheet( $post_id ); /* If a new meta value was added and there was no previous value, add it. */ elseif ( current_user_can( 'add_post_meta', $post_id, $meta_key ) && $new_meta_value && '' == $meta_value ) set_post_stylesheet( $post_id, $new_meta_value ); /* If the old layout doesn't match the new layout, update the post layout meta. */ elseif ( current_user_can( 'edit_post_meta', $post_id, $meta_key ) && $meta_value !== $new_meta_value ) set_post_stylesheet( $post_id, $new_meta_value ); } /** * Gets the stylesheet files within the parent or child theme and checks if they have the 'Style Name' * header. If any files are found, they are returned in an array. * * @since 0.4.0 * @access public * @global array $_post_stylesheets Array of post-type specific stylesheets. * @return array */ function post_stylesheets_get_styles( $post_type = 'post' ) { global $_post_stylesheets; /* If stylesheets have already been loaded, return them. */ if ( !empty( $_post_stylesheets ) && isset( $_post_stylesheets[ $post_type ] ) ) return $_post_stylesheets[ $post_type ]; /* Set up an empty styles array. */ $_post_stylesheets[ $post_type ] = array(); /* Get the theme object. */ $theme = wp_get_theme(); /* Get the theme CSS files two levels deep. */ $files = (array) $theme->get_files( 'css', 2, true ); /* Loop through each of the CSS files and check if they are styles. */ foreach ( $files as $file => $path ) { /* Get file data based on the 'Style Name' header. */ $headers = get_file_data( $path, array( 'Style Name' => 'Style Name', "{$post_type} Style" => "{$post_type} Style" ) ); /* Add the CSS filename and template name to the array. */ if ( !empty( $headers['Style Name'] ) ) $_post_stylesheets[ $post_type ][ $file ] = $headers['Style Name']; elseif ( !empty( $headers["{$post_type} Style"] ) ) $_post_stylesheets[ $post_type ][ $file ] = $headers["{$post_type} Style"]; } /* Flip the array of styles. */ $_post_stylesheets[ $post_type ] = array_flip( $_post_stylesheets[ $post_type ] ); /* Return array of styles. */ return $_post_stylesheets[ $post_type ]; } /** * Returns the meta key used by the script for post metadata. * * @since 0.3.0 * @access public * @return string */ function post_stylesheets_get_meta_key() { return apply_filters( 'post_stylesheets_meta_key', 'Stylesheet' ); } ?>