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:
/