1

I'm trying to create a WP theme (for personal learning purposes, still pretty new to wp) where Header/Container/Footer are each chosen based on a dedicated customizer setting (still plain text, possible choices will be based on a pre-defined list probably).

The idea:

A Theme singleton(i know... that's not an happy choice) handles class instances which will be created in the "after_theme_setup" hook. After this, each instance will have the right to hook depending on its needs (for example , to register customizer sections/controls etc...)

class VTheme extends VRSharedContextSingleton{
    protected $mHeader = null;
    protected $mContainer = null;
    protected $mFooter = null;

    protected function __construct(){
        add_action( 'after_setup_theme' , function(){
            spl_autoload_register(function ($class) {
                $fn = '/classes/' . $class . '.class.php';
                if(file_exists(get_stylesheet_directory().$fn)){
                    include get_stylesheet_directory().$fn;
                }else if(file_exists(get_template_directory().$fn)){
                    include get_template_directory().$fn;
                }
            });

            $hc=caw_get_theme_mod('vs_header_class','vrm_HeaderA');
            $cc=caw_get_theme_mod('vs_container_class','vrm_ContainerA');
            $fc=caw_get_theme_mod('vs_footer_class','vrm_FooterA');

            if(class_exists($hc)) $this->LinkHeader(new $hc());
            if(class_exists($cc)) $this->LinkContainer(new $cc());
            if(class_exists($fc)) $this->LinkFooter(new $fc());

        });

         add_action( 'customize_register', function($wp_customize){
             require get_template_directory().'/auxiliary/wp-core-customizer.part.php';
         });
    }

    public function &LinkHeader(VRModule $module){
        if($module) {$this->mHeader = $module->LinkTo($this);}
        return $this;
    }
...
abstract class VRModule{
    protected $mParent = null;
    protected $mStreams = array();

    public final function &LinkTo(VRSharedContext &$parent){
        $this->mParent = $parent;
        $this->OnLink();
        return $this;
    }
    ...
 class vrm_HeaderA extends VRModule{
        protected function OnLink(){
            add_action( 'customize_register', function($wp_customize){
                $wp_customize->add_setting( 'vscst_header_fontcolor_setting',
                array(
                   'default' => '',
                   'validate_callback' => '',
                   'sanitize_callback' => '',
                   'sanitize_js_callback' => '',
                ));
                $wp_customize->add_control( 'vscst_header_fontcolor_control',
                array(
                   'settings'=>'vscst_header_fontcolor_setting',
                   'label' => __( 'Font color' ),
                   'description' => esc_html__( 'Font color' ),
                   'section' => 'vscst_header_settings_section',
                   'type' => 'text',
                ));
            });
        }
...

The main issue i'm stuck against is that module changes ( for example , changing Header class name in the customizer) , do not reflect in Customizer preview iFrame...(at least not until i fully refresh the page from browser after saving)

I supspect that might be because of hooks order (p.s: using "QueryMonitor" plugin to check behaviour) ..or maybe "get_theme_mod" acting differently while customizing?

P.s: trying to hook on "customizer_preview_init" and using the conditional "is_customize_preview()" made the changes reflect in Customizer iFrame, but i think that is a bit hacky and restricts what can be done in the hooked function ("customizer_preview_init" is way further "after_setup_theme")

Other issues i'm having (dynamically registered, by an Header for example, customizer's panels/controls etc , not appearing before save and refresh), i think are both related to the first issue , and might involve some js/ajax as a workaround as well...

Any idea about this?
Is it reasonable to try to achieve this kind of "modular" behaviour with this approach in WP?

Thanks in advance !

Update:

Digging into wp-customize-manager.php and Customizer API docs, i think i found a relatively elegant workaround:

Creating an auxiliary function "caw_get_theme_mod" (standing for "customize aware"..) with this definition:

function caw_get_theme_mod( $name, $default = false){
    if(is_customize_preview()){
        global $wp_customize;
        $s = new WP_Customize_Setting($wp_customize,$name);
        $v = $s->post_value();
        if($v!==null) return $v;
    }
    return get_theme_mod($name,$default);
}

And using in the theme in place of get_theme_mod, customizer is now able to successfully show the preview with the temporarly updated fields and newly registered elements also show as expected in the customizer UI without the need of a full/hard page refresh.

That works because "post_value()" returns the value , sanitized as far as i could read, taken from the request sent to server (that's why i have to test against the default "null" , since there is no request sent on the first customizer load, in this case i fallback to the default get_theme_mod)

I leave link references to documentation, they might be usefull for anyone interested:
https://developer.wordpress.org/reference/classes/wp_customize_setting/

Your Answer

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

Browse other questions tagged or ask your own question.