6
\$\begingroup\$

I have created this class for my WP theme. It allows you to create templates for a meta box which relates directly to a custom frontend template to have better control of the content displayed on the page.

So for example:

The meta box content file, which defines a "template":

theme_folder/post-templates/templates/admin/print.php

The file would define variables containing information about the template:

<?php
/* Print Design Post Template */
global $post;
$this->templates[] = array( 
    'print' =>  array(
        'admin_filepath'    =>  basename(__FILE__),
        'template_name'     =>  'Print Design Project',
        'template_id'       =>  'print',
        'frontend_file'     =>  'print-design.php'
    )
);
if( self::TEMPLATE_PARSER ) return;

$data = $this->_getLayoutData($post->ID);

?>
<p>
    <label>Test Field</label>
    <input type="text" name="brave_template_data[test_field]" value="<?php echo $data['test_field']; ?>" />
</p>
<p>
    <label>Test Field 2</label>
    <input type="text" name="brave_template_data[test_field_2]" value="<?php echo $data['test_field_2']; ?>" />
</p>
<p>
    <label>Test Field 3</label>
    <input type="text" name="brave_template_data[test_field_3]" value="<?php echo $data['test_field_3']; ?>" />
</p>

Here's the front end file which would look pretty much the same as a normal WP template file:

    <?php 
    global $brave_templater,$post;
    get_header(); ?>
    Custom Print Template
    <?php var_dump($brave_templater->_getLayoutData($post->ID)); ?>
    <?php get_footer(); ?>

The engine file:

<?php
class Brave_Post_Templates {

    var $body_class;
    var $templates = array();
    var $enabled_post_types = array('portfolio');

    const FRONTEND_THEMES ='post-templates/templates/frontend';
    const ADMIN_THEMES = 'post-templates/templates/admin';
    const TEMPLATE_PARSER = false;

    /**
     * Attach WP Action Hooks
     */ 
    public function __construct() {

        // Load Templates
        $this->_getAvailableTemplates();

        // Meta Box Hooks
        add_action('admin_menu', array( $this, 'add_meta_boxes' ) );
        add_action('save_post', array( $this, 'save_meta_box_content' ));

        // Frontend Template Redirect
        add_action('template_redirect', array($this, '_interceptTemplateDisplay'));

        // AJAX
        add_action('wp_ajax_braveGetMetaBoxContent', array( $this, 'ajax_braveGetMetaBoxContent' ));
        add_action('wp_ajax_nopriv_braveGetMetaBoxContent', array( $this, 'ajax_braveGetMetaBoxContent' )); 

    }

    /**
     * _interceptTemplateDisplay
     *
     * Load custom template file if one is set.
     *
     */ 
    public function _interceptTemplateDisplay() {

        global $post;

        if( $post && in_array($post->post_type, $this->enabled_post_types) ) {

            if($this->hasPostTemplate($post->ID)) {

                $this->_loadFrontEndTemplate($this->_getTemplate($post->ID));

            } 

        }

    }

    /**
     * _addPostTypeSupport
     *
     * Add post type support for custom templates.
     *
     */     
    public function _addPostTypeSupport($post_type) {
        return $this->enabled_post_types[] = $post_type;
    }

    /*
     * Add Meta Boxes for Custom Fields
    */      
    public function add_meta_boxes() {

        foreach($this->enabled_post_types as $post_type) {
            add_meta_box($post_type.'-meta-box-settings', 'Template Settings', array($this,'meta_box_content'), $post_type, 'normal', 'high');
        }

    }   

    /*
     * Meta Box Content
    */      
    public function meta_box_content() { 
        global $post;   
    ?>
    <div id="brave_post_templates">
        <p>
            <label><strong>Template:</strong></label>
            <select name="brave_post_template" id="brave_post_template_select">
                <?php if(!$this->hasPostTemplate($post->ID)): ?>
                <option value="default" selected="selected">Default Post Type Template (single-<?php echo $post->post_type; ?>.php)</option>
                <?php else: ?>
                <option value="default">Default Post Type Template (single-<?php echo $post->post_type; ?>.php)</option>
                <?php endif; ?>     
                <?php if( count($this->_getTemplates()) > 0 ): ?>
                    <?php foreach($this->_getTemplates() as $templates): ?>
                        <?php foreach($templates as $template): ?>
                            <option value="<?php echo $template['template_id']; ?>" <?php selected($template['template_id'], $this->_getTemplate($post->ID)); ?>><?php echo $template['template_name']; ?> (<?php echo $template['frontend_file']; ?>)</option>
                        <?php endforeach; ?>
                    <?php endforeach; ?>
                <?php endif; ?>
            </select>
        </p>  

        <div class="brave_post_template_meta_box_content">  
        <?php if($this->hasPostTemplate($post->ID)): ?>
            <?php echo $this->_loadAdminMetaBoxTemplate($this->_getTemplate($post->ID)); ?>
        <?php else: ?>
            <p>No custom template selected, please choose a template above.</p>
        <?php endif; ?>
        </div>
        <script type="text/javascript">
            jQuery(document).ready(function(){

                var brave_templater_select = jQuery('#brave_post_template_select');
                var brave_templater_container = jQuery('.brave_post_template_meta_box_content');

                brave_templater_select.change(function(){

                    var template_id = this.value;

                    if(template_id == 'default') {
                        brave_templater_container.html('<p>No custom template selected, please choose a template above.</p>');
                        return false;
                    }

                    var data = {
                        action: 'braveGetMetaBoxContent',
                        template_id: template_id,
                        post_id: '<?php echo $post->ID; ?>'
                    };

                    jQuery.post('<?php echo admin_url('admin-ajax.php'); ?>', data, function(response) {
                        brave_templater_container.fadeOut(100, function(){
                            jQuery(this).empty().html(response).fadeIn(100);
                        });
                    });         

                });     

            });
        </script>
    </div>
    <?php   
    }

    /*
     * Save Meta Box Custom Fields
    */  
    public function save_meta_box_content($post_id) {

        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
            return $post_id;
        }

        if ( in_array($_POST['post_type'], $this->enabled_post_types) ) {
            if (!current_user_can('edit_page', $post_id)) {
                return $post_id;
            } else {

                $post_template = $_POST['brave_post_template'];
                $data = $_POST['brave_template_data'];

                update_post_meta($post_id, 'brave_post_template', $post_template);

                if($data) {
                    update_post_meta($post_id, 'brave_template_data', serialize($data));
                }

            }
        } elseif (!current_user_can('edit_post', $post_id)) {
            return $post_id;
        }       

    }

    /**
     * _getTemplate
     *
     * Get current custom template.
     *
     */ 
    public function _getTemplate($post_id) {

        return get_post_meta($post_id, 'brave_post_template', true);

    }   

    /**
     * hasPostTemplate
     *
     * Check to see if a custom template has been set.
     *
     */     
    public function hasPostTemplate($post_id) {

        $template = get_post_meta($post_id, 'brave_post_template', true);
        if( $template && $template != 'default' ) return true;
        return false;

    }

    /**
     * _getAvailableTemplates
     *
     * Populates self::templates (array) with available templates found.
     *
     */     
    public function _getAvailableTemplates() {

        self::TEMPLATE_PARSER == true;

        $path = BRAVE_LIB . self::ADMIN_THEMES;         

        $dir = glob($path.'/*.php');

        foreach( $dir as $file) {                   
            ob_start();
            include_once($file);
            $file = ob_get_contents();              
            ob_end_clean();
        }   

        return $this;

    }

    /**
     * _getTemplates
     *
     * Returns self::templates (array)
     *
     */     
    public function _getTemplates() {
        return $this->templates;
    }

    /**
     * _loadAdminMetaBoxTemplate
     *
     * Loads Meta Box HTML based on template.
     *
     */ 
    public function _loadAdminMetaBoxTemplate($template_id) {

        self::TEMPLATE_PARSER == false;

        foreach($this->_getTemplates() as $template) {

            $file = BRAVE_LIB . self::ADMIN_THEMES . '/' . $template[$template_id]['admin_filepath'];

            if( array_key_exists($template_id, $template) && file_exists($file) ) {

                require($file);

            }

        }

        return false;

    }

    /*
     * Load Meta Box Content with AJAX
    */      
    public function ajax_braveGetMetaBoxContent() {

        global $post;
        $post->ID = $_POST['post_id'];
        $template_id = $_POST['template_id'];

        self::TEMPLATE_PARSER == false;

        foreach($this->_getTemplates() as $template) {

            $file = BRAVE_LIB . self::ADMIN_THEMES . '/' . $template[$template_id]['admin_filepath'];

            if( array_key_exists($template_id, $template) && file_exists($file) ) {

                $file = file_get_contents($file);
                $file = preg_replace('/<?php/', '', $file, 1);
                eval('?>'.$file);
                die(1);

            }

        }

    }

    /**
     * _loadFrontEndTemplate
     *
     * Loads frontend template.
     *
     */ 
    public function _loadFrontEndTemplate($template_id) {

        foreach($this->_getTemplates() as $template) {

            $file = BRAVE_LIB . self::FRONTEND_THEMES . '/' . $template[$template_id]['frontend_file'];

            if( array_key_exists($template_id, $template) && file_exists($file) ) {

                $this->body_class = 'brave-post-template-'.$template_id;
                add_filter('body_class', array($this,'addPostBodyClasses'));                
                require($file);
                exit;

            } else {
                wp_die('Invalid Template ID or Template file is missing.');
            }

        }

    }

    /**
     * addPostBodyClasses
     *
     * Add body class for current template.
     *
     */     
    public function addPostBodyClasses($classes) {
        $classes[] = $this->body_class;
        return $classes;
    }

    /**
     * _getLayoutData
     *
     * Gets custom field data for key: brave_template_data to be used on the frontend.
     *
     */     
    public function _getLayoutData($post_id) {
        return unserialize(get_post_meta($post_id, 'brave_template_data', true));
    }


}

I was just wondering if this is a good attempt, as I am not a proflific PHP programmer and I have never had an opinion on my code really!

\$\endgroup\$
  • \$\begingroup\$ Your code is very pretty and easy to read. Why do some methods begin with an underscore. Like, _interceptTemplateDisplay? I'm not complaining about it. Just curious. \$\endgroup\$ – Charles Clarkson Aug 23 '13 at 13:41
3
\$\begingroup\$

Your code looks good, (although I did not review each particular) The only thing that stood out to me is that your files do not begin with a check to see if the file is being accessed directly. You should have a variable defined at the beginning of the theme that is checked for at the beginning of each other file, and if the variable is not defined, reject the access. There is a section about that here: https://www.wordfence.com/learn/how-to-write-secure-php-code/

| improve this answer | |
\$\endgroup\$
-2
\$\begingroup\$

The formatting is a little off to what is considered normal/good. It is widely accepted that each word in a class name should have it's first letter capitalized. Function names are most commonly written in "camelCase".

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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