Conditional tags inside a class

I have a couple of functions that I now combined in a class. The reason for that was that all these functions go towards one goal, and it is more appropriate way to use the globals between these functions. The class consists of three main sections, section one to add my meta boxes, section two adds a options page where sidebars are created, and section three which actually register the sidebars.

My problem now is, section one and two only needs to run on admin side. I know how to achieve that on normal functionality. My problem is how do I achieve that inside a class. I know that you can wrap the complete class inside the is_admin() tag, but that doesn’t work here as my sidebars are not displayed then on the front end.

How can I only wrap the first two sections in the is_admin() tag. Here is my class

class PieterGoosen_Custom_Sidebars {
    private $sdwas;

    public function __construct() {

        add_action( 'add_meta_boxes', array( $this, 'add_cspp' ) );
        add_action( 'save_post', array( $this, 'save_cspp' ) );
        add_action( 'admin_init', array( $this, 'init' ) );
        add_action( 'admin_menu', array( $this, 'add_page' ) );
        add_action( 'widgets_init', array( $this, 'sidebars_register' ) );

    }

    /*----------------------------------------------------------------------------------
     *
     *      Create and add meta box to page edit screen
     *
     *---------------------------------------------------------------------------------*/

    public function add_cspp() {

        //Meta box in page screen
        add_meta_box( 
            'custom_sidebar_per_page', 
            __( 'Sidebar options', 'pietergoosen' ), 
            array( $this, 'cspp_link' ),
            'page', 
            'side', 
            'high'
        );

        // Meta box in post screen
        add_meta_box( 
            'custom_sidebar_per_page', 
            __( 'Sidebar options', 'pietergoosen' ), 
            array( $this, 'cspp_link' ),
            'post', 
            'side', 
            'high'
        );
    }

    public function cspp_link( $post ) {

        wp_nonce_field( 'cspp_meta_nonce', 'cspp_nonce' );

        $custom = get_post_custom($post->ID);

        if(isset($custom['_custom_sidebar_per_page']))
            $val = $custom['_custom_sidebar_per_page'][0];
        else
            $val = "default";

        // The actual fields for data entry
        $output = '<p><label for="pietergoosen_new_field">'.__( 'Choose a sidebar to display', 'pietergoosen' ).'</label></p>';
        $output .= '<select name="custom_sidebar_per_page">';

        // Add a default option
        $output .= '<option';
        if($val == "default")
            $output .= ' selected="selected"';
        $output .= ' value="default">'.__( 'No Specified Sidebar', 'pietergoosen' ).'</option>';

        // Fill the select element with all registered sidebars
        if(!empty($this->sdwas))
            foreach($this->sdwas as $sid => $sdwa) {  
                $output .= '<option';  
                if($sdwa == $val)  
                    $output .= ' selected="selected"';  
                $output .= ' value="'.$sdwa.'">'.$sdwa.'</option>';  
            }  

        $output .= '</select>';  

        echo $output;  
    } 

    public function save_cspp($post_id){

        // Check if our nonce is set.
        $nonce = filter_input(INPUT_POST, 'cspp_nonce', FILTER_SANITIZE_STRING);

        // Verify that the nonce is valid.
        if ( empty($nonce) || ! wp_verify_nonce( $nonce, 'cspp_meta_nonce' ) )
            return $post_id;

        // If this is an autosave, our form has not been submitted, so we don't want to do anything.
        if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
        return $post_id;

        // Check the user's permissions for pages.
        if ( !current_user_can( 'edit_page', $post_id ) )
            return;

        // Check the user's permissions for posts.
        if ( !current_user_can( 'edit_post', $post_id ) )
            return; 

        /* OK, its safe for us to save the data now. */
        $custom = filter_input(INPUT_POST, 'custom_sidebar_per_page', FILTER_SANITIZE_STRING);

        if(!empty( $_POST['custom_sidebar_per_page'] )) {
            update_post_meta($post_id, '_custom_sidebar_per_page', $custom);
        }else{
            delete_post_meta( $post_id, '_custom_sidebar_per_page');
        }
    }

    /*----------------------------------------------------------------------------------
     *
     *      Register and add a options screen under the "Appearance" menu screen.
     *          Sidebars are created/deleted here.
     *
     *---------------------------------------------------------------------------------*/

    public function init() {

        register_setting( 
            'set_fields', 
            'cspp_get_option', 
            array( $this, 'sanitation' )
        );

        add_settings_section( 
            'general',  
            __( 'Custom sidebars per page', 'pietergoosen' ), 
            '__return_false', 
            'theme_options' 
        );

        add_settings_field( 
            'custom_sidebar_per_page', 
            __( 'Custom sidebars', 'pietergoosen' ), 
            array( $this, 'settings_field' ), 
            'theme_options', 
            'general' 
        );

    }

    public function add_page() {
        add_theme_page(
            __( 'Custom Sidebars', 'pietergoosen' ),     
            __( 'Custom Sidebars', 'pietergoosen' ),     
            'edit_theme_options',                       
            'theme_options',                             
            array( $this, 'render_page' )                
        );
    }

    public function render_page() {
        if (! current_user_can('edit_theme_options') ) 
            return;
         ?>
        <div class="wrap">
            <h2><?php _e( 'Custom Sidebars Per Page Options', 'pietergoosen' ); ?></h2>  
            <p>
                <?php 
                _e( 'Create or remove custom sidebars that can be individually used on posts and pages', 'pietergoosen' )
                ?>
            </p>
            <form method="post" action="options.php">
            <?php
                // This prints out all hidden setting fields
                settings_fields( 'set_fields' ); 
                do_settings_sections( 'theme_options' );
                submit_button(); 
            ?>
            </form>
        </div>
        <?php
    }

    public function sanitation( $input ) {

        $output = array();

        if ( isset( $input['_custom_sidebar_per_page'] ) ) {
        $output['_custom_sidebar_per_page'] = $input['_custom_sidebar_per_page'];
        }   
        return $output;
    }

    public function settings_field() {

        $option1 = get_option( 'cspp_get_option' );

        // A bit of jQuery to handle interactions (add / remove sidebars)
        $val1 = '<script type="text/javascript">';
        $val1 .= '
                    var $ = jQuery;
                    $(document).ready(function(){
                        $(".sidebar_management").on("click", ".delete", function(){
                            $(this).parent().remove();
                        });

                        $("#add_sidebar").click(function(){
                            $(".sidebar_management ul").append("<li>"+$("#new_sidebar_name").val()+" <a href=\'#\' class=\'delete\'>'.__('Delete', 'pietergoosen').'</a> <input type=\'hidden\' name=\'cspp_get_option[_custom_sidebar_per_page][]\' value=\'"+$("#new_sidebar_name").val()+"\' /></li>");
                            $("#new_sidebar_name").val("");
                        })

                    })
        ';

        $val1 .= '</script>';

        $val1 .= '<div class="sidebar_management">';

        $val1 .= '<p><input type="text" id="new_sidebar_name" /></p><p><input class="button-primary" type="button" id="add_sidebar" value="'.__('Add', 'pietergoosen').'" /></p>';

        $val1 .= '<ul>';

        // Display all custom sidebars
        if(isset($option1['_custom_sidebar_per_page']) ? esc_attr($option1['_custom_sidebar_per_page']) : '') {
            $csppval = $option1['_custom_sidebar_per_page'];
            $i = 0;

            foreach($csppval as $sdwa) {
                $val1 .= '<li>'.$sdwa.' <a href="#" class="delete">'.__( 'Delete', 'pietergoosen' ).'</a><input type="hidden" name="cspp_get_option[_custom_sidebar_per_page][]" value="'.$sdwa.'" /></li>';
                $i++;
            }
        }

        $val1 .= '</ul>';

        $val1 .= '</div>';

        echo $val1;
    }

    /*----------------------------------------------------------------------------------
     *
     *      Register the custom sidebars if a value is entered in save in the options
     *          screens. Also create a sidebar ID from this value
     *
     *---------------------------------------------------------------------------------*/

    public function sidebars_register() {

        $option2 = get_option( 'cspp_get_option' );
            if( isset($option2['_custom_sidebar_per_page']))
                $this->sdwas = $option2['_custom_sidebar_per_page'];

        if( isset($this->sdwas) && sizeof($this->sdwas) > 0) {  
            foreach($this->sdwas as $sid => $sdwa) {

                register_sidebar(
                    array (
                        'name'          => $sdwa,
                        'id'            => sanitize_title($sdwa),
                        'description'   => __( 'Page specific sidebars that can be chosen per page', 'pietergoosen' ),
                        'before_widget' => '<aside id="%1$s" class="widget %2$s">',
                        'after_widget'  => '</aside>',
                        'before_title'  => '<h1 class="widget-title">',
                        'after_title'   => '</h1>',
                    )
                );
            }
        }
    }
}

$pgsidebar = new PieterGoosen_Custom_Sidebars();

EDIT

As @isNaN suggested, I have tried that.

public function __construct() {
    if (is_admin()) {
        add_action( 'add_meta_boxes', array( $this, 'add_cspp' ) );
        add_action( 'save_post', array( $this, 'save_cspp' ) );
        add_action( 'admin_init', array( $this, 'init' ) );
        add_action( 'admin_menu', array( $this, 'add_page' ) );
    } 
        add_action( 'widgets_init', array( $this, 'sidebars_register' ) );
    }

I’m not sure if that is the correct way. All functions are still executed by using this method. It is just the hooks that are not executed as they are inside the conditional tag. I really think that there should be a way to completely wrap all relevant functions in the is_admin() conditional tag, not just the action hooks

Solutions Collecting From Web of "Conditional tags inside a class"

Your real problem is the god class. You put rendering, sanitation, validation, saving and fetching data, and registration into one class.
Separate your tasks to make it it OOP, and let the main class be a very simple front controller that handles the initial registration only.

Here is a rough start, illustrating how I would do that:

// validate nonces
interface PG_Nonce_Validator_Interface {
    public function is_valid();
    public function get_name();
    public function get_action();
}
class PG_Nonce_Validator implements PG_Nonce_Validator_Interface {
    public function __construct( $base_string ) {}
    public function is_valid() {}
    public function get_name() {}
    public function get_action() {}
}

// validate request for the action 'save_post'
interface PG_Request_Validator_Interface {
    public function is_valid();
}
class PG_Save_Post_Validator implements PG_Request_Validator_Interface {
    public function __construct( PG_Nonce_Validator_Interface $nonce_validator ) {}
    public function is_valid() {}
}

// sanitation
interface PG_Sanitize_Data_Interface {
    public function sanitize( $data );
}
class PG_Sanitize_Data implements PG_Sanitize_Data_Interface {
    public function sanitize( $data ) {}
}

// data access
interface PG_Data_Interface {
    public function save( $data );
    public function get();
}
class PG_Option_Data implements PG_Data_Interface {
    public function __construct( $option_name ) {}
    public function save( $data ) {}
    public function get() {}
}

interface PG_View_Interface {
    public function render();
}

interface PG_Event {
    public function trigger( $name, $data = NULL );
}

class PG_Settings_Page implements PG_View_Interface {

    public function __construct() {

    }

    public function render() {}
}


class PG_Custom_Sidebars {

    private $option_name = 'cspp_get_option';

    // we do not run methods automatically in a constructor
    public function setup() {

        if ( is_admin() )
            $this->register_admin_actions();

        add_action( 'widgets_init', array( $this, 'register_sidebars' ) );
    }

    public function register_sidebars() {}

    private function register_admin_actions() {

        $nonce             = new PG_Nonce_Validator( 'pg_nonce' );
        $request_validator = new PG_Save_Post_Validator( $nonce );
        // and so on …
    }
}

$pg_custom_sidebars = new PG_Custom_Sidebars;
$pg_custom_sidebars->setup();

You can find examples for similar classes in Multilingual Press:

  • Nonce_Validator that doesn’t delete user data in a multisite.
  • Save_Post_Request_Validator using the Nonce_Validator.
  • Post_Data handler, probably too complex for your use case and not as clean as I would like it. 🙂
  • Metabox controller (still does too much).

The basic idea is: load and instantiate only the code you actually need. Keep your classes as small as possible, keep them testable.

A View class should never know when it has to show something, just what (a title, a description, a submit button). And it shouldn’t even know where the data comes from.

Maybe you want to store the data in a user meta field later, not in an option? Just create a new concrete implementation for PG_Data_Interface and call that in your controller – without touching any of the other classes.

You can add the is_admin() function in your constructor to separate the logic.

/* php */
public function __construct() {
    if (is_admin()) {
        /* add actions for admins here */
        add_action( 'init', array( $this, 'do_admin_stuff' ) );
    } else {
        /* add actions for front-end here */
        add_action( 'init', array( $this, 'do_front_end_stuff' ) ); 
    }
}