2012-02-24 23:12:43 -05:00
< ? php
/**
2012-07-26 17:45:33 -04:00
* Customize Manager .
2012-02-24 23:12:43 -05:00
*
* @ package WordPress
* @ subpackage Customize
* @ since 3.4 . 0
*/
2012-05-23 13:56:42 -04:00
final class WP_Customize_Manager {
2012-04-17 17:43:47 -04:00
protected $theme ;
2012-04-17 16:49:39 -04:00
protected $original_stylesheet ;
2012-02-24 23:12:43 -05:00
protected $previewing = false ;
protected $settings = array ();
protected $sections = array ();
2012-03-28 00:14:09 -04:00
protected $controls = array ();
2012-02-24 23:12:43 -05:00
2012-06-26 14:48:18 -04:00
protected $nonce_tick ;
2012-04-30 11:46:17 -04:00
protected $customized ;
private $_post_values ;
2012-02-24 23:12:43 -05:00
/**
* Constructor .
*
* @ since 3.4 . 0
*/
public function __construct () {
require ( ABSPATH . WPINC . '/class-wp-customize-setting.php' );
require ( ABSPATH . WPINC . '/class-wp-customize-section.php' );
2012-03-28 00:14:09 -04:00
require ( ABSPATH . WPINC . '/class-wp-customize-control.php' );
2012-02-24 23:12:43 -05:00
2012-06-08 15:22:11 -04:00
add_filter ( 'wp_die_handler' , array ( $this , 'wp_die_handler' ) );
2012-04-25 11:44:06 -04:00
add_action ( 'setup_theme' , array ( $this , 'setup_theme' ) );
2012-02-29 19:14:51 -05:00
add_action ( 'wp_loaded' , array ( $this , 'wp_loaded' ) );
2012-02-24 23:12:43 -05:00
2012-05-23 21:48:32 -04:00
// Run wp_redirect_status late to make sure we override the status last.
add_action ( 'wp_redirect_status' , array ( $this , 'wp_redirect_status' ), 1000 );
2012-05-25 23:52:14 -04:00
// Do not spawn cron (especially the alternate cron) while running the customizer.
remove_action ( 'init' , 'wp_cron' );
// Do not run update checks when rendering the controls.
remove_action ( 'admin_init' , '_maybe_update_core' );
remove_action ( 'admin_init' , '_maybe_update_plugins' );
remove_action ( 'admin_init' , '_maybe_update_themes' );
2012-04-30 11:46:17 -04:00
add_action ( 'wp_ajax_customize_save' , array ( $this , 'save' ) );
2012-03-21 18:55:43 -04:00
add_action ( 'customize_register' , array ( $this , 'register_controls' ) );
add_action ( 'customize_controls_init' , array ( $this , 'prepare_controls' ) );
add_action ( 'customize_controls_enqueue_scripts' , array ( $this , 'enqueue_control_scripts' ) );
2012-02-24 23:12:43 -05:00
}
2012-07-26 17:45:33 -04:00
/**
2012-06-08 15:22:11 -04:00
* Return true if it ' s an AJAX request .
*
* @ since 3.4 . 0
2012-07-26 17:45:33 -04:00
*
* @ return bool
2012-06-08 15:22:11 -04:00
*/
public function doing_ajax () {
return isset ( $_POST [ 'customized' ] ) || ( defined ( 'DOING_AJAX' ) && DOING_AJAX );
}
/**
* Custom wp_die wrapper . Returns either the standard message for UI
* or the AJAX message .
*
* @ since 3.4 . 0
2012-07-26 17:45:33 -04:00
*
* @ param mixed $ajax_message AJAX return
2012-11-17 10:11:29 -05:00
* @ param mixed $message UI message
2012-06-08 15:22:11 -04:00
*/
2012-06-12 14:39:16 -04:00
protected function wp_die ( $ajax_message , $message = null ) {
2012-06-08 15:22:11 -04:00
if ( $this -> doing_ajax () )
wp_die ( $ajax_message );
2012-06-12 14:39:16 -04:00
if ( ! $message )
$message = __ ( 'Cheatin’ uh?' );
2012-06-08 15:22:11 -04:00
wp_die ( $message );
}
2012-02-24 23:12:43 -05:00
/**
2012-06-08 15:22:11 -04:00
* Return the AJAX wp_die () handler if it ' s a customized request .
2012-04-17 17:43:47 -04:00
*
2012-06-08 15:22:11 -04:00
* @ since 3.4 . 0
2012-07-26 17:45:33 -04:00
*
* @ return string
2012-06-08 15:22:11 -04:00
*/
public function wp_die_handler () {
if ( $this -> doing_ajax () )
return '_ajax_wp_die_handler' ;
return '_default_wp_die_handler' ;
}
2012-11-17 10:11:29 -05:00
2012-06-08 15:22:11 -04:00
/**
2012-07-26 17:45:33 -04:00
* Start preview and customize theme .
*
* Check if customize query variable exist . Init filters to filter the current theme .
2012-02-24 23:12:43 -05:00
*
* @ since 3.4 . 0
*/
2012-04-25 11:44:06 -04:00
public function setup_theme () {
2012-06-12 14:39:16 -04:00
send_origin_headers ();
2012-06-08 15:22:11 -04:00
if ( is_admin () && ! $this -> doing_ajax () )
auth_redirect ();
2012-06-12 14:39:16 -04:00
elseif ( $this -> doing_ajax () && ! is_user_logged_in () )
$this -> wp_die ( 0 );
2012-06-07 11:25:45 -04:00
2012-06-12 14:39:16 -04:00
show_admin_bar ( false );
if ( ! current_user_can ( 'edit_theme_options' ) )
$this -> wp_die ( - 1 );
2012-05-08 16:13:34 -04:00
2012-06-06 16:34:24 -04:00
$this -> original_stylesheet = get_stylesheet ();
$this -> theme = wp_get_theme ( isset ( $_REQUEST [ 'theme' ] ) ? $_REQUEST [ 'theme' ] : null );
2017-05-16 08:23:10 -04:00
/*
* Clear incoming post data if the user lacks a CSRF token ( nonce ) . Note that the customizer
* application will inject the customize_preview_nonce query parameter into all Ajax requests .
* For similar behavior elsewhere in WordPress , see rest_cookie_check_errors () which logs out
* a user when a valid nonce isn ' t present .
*/
$has_post_data_nonce = (
check_ajax_referer ( 'preview-customize_' . $this -> get_stylesheet (), 'nonce' , false )
||
check_ajax_referer ( 'save-customize_' . $this -> get_stylesheet (), 'nonce' , false )
||
check_ajax_referer ( 'preview-customize_' . $this -> get_stylesheet (), 'customize_preview_nonce' , false )
);
if ( ! $has_post_data_nonce ) {
unset ( $_POST [ 'customized' ] );
unset ( $_REQUEST [ 'customized' ] );
}
2012-06-12 14:39:16 -04:00
if ( $this -> is_theme_active () ) {
// Once the theme is loaded, we'll validate it.
add_action ( 'after_setup_theme' , array ( $this , 'after_setup_theme' ) );
} else {
if ( ! current_user_can ( 'switch_themes' ) )
$this -> wp_die ( - 1 );
2012-06-06 16:34:24 -04:00
2012-06-12 14:39:16 -04:00
// If the theme isn't active, you can't preview it if it is not allowed or has errors.
if ( $this -> theme () -> errors () )
$this -> wp_die ( - 1 );
2012-06-06 16:34:24 -04:00
2012-06-12 14:39:16 -04:00
if ( ! $this -> theme () -> is_allowed () )
$this -> wp_die ( - 1 );
}
2012-06-06 16:34:24 -04:00
2012-04-25 11:44:06 -04:00
$this -> start_previewing_theme ();
2012-06-12 14:39:16 -04:00
}
2012-11-17 10:11:29 -05:00
2012-07-26 17:45:33 -04:00
/**
* Callback to validate a theme once it is loaded
*
* @ since 3.4 . 0
*/
2012-06-12 14:39:16 -04:00
function after_setup_theme () {
if ( ! $this -> doing_ajax () && ! validate_current_theme () ) {
wp_redirect ( 'themes.php?broken=true' );
exit ;
}
2012-04-25 11:44:06 -04:00
}
2012-02-24 23:12:43 -05:00
2012-04-25 11:44:06 -04:00
/**
* Start previewing the selected theme .
*
* Adds filters to change the current theme .
*
* @ since 3.4 . 0
*/
public function start_previewing_theme () {
2012-06-06 16:34:24 -04:00
// Bail if we're already previewing.
if ( $this -> is_preview () )
2012-04-25 11:44:06 -04:00
return ;
2012-02-24 23:12:43 -05:00
2012-04-25 11:44:06 -04:00
$this -> previewing = true ;
2012-06-12 14:39:16 -04:00
if ( ! $this -> is_theme_active () ) {
add_filter ( 'template' , array ( $this , 'get_template' ) );
add_filter ( 'stylesheet' , array ( $this , 'get_stylesheet' ) );
add_filter ( 'pre_option_current_theme' , array ( $this , 'current_theme' ) );
2012-06-12 15:27:41 -04:00
2012-06-12 14:39:16 -04:00
// @link: http://core.trac.wordpress.org/ticket/20027
add_filter ( 'pre_option_stylesheet' , array ( $this , 'get_stylesheet' ) );
add_filter ( 'pre_option_template' , array ( $this , 'get_template' ) );
2012-06-12 15:27:41 -04:00
2012-06-12 14:39:16 -04:00
// Handle custom theme roots.
add_filter ( 'pre_option_stylesheet_root' , array ( $this , 'get_stylesheet_root' ) );
add_filter ( 'pre_option_template_root' , array ( $this , 'get_template_root' ) );
}
2012-04-17 17:43:47 -04:00
2012-04-30 13:20:32 -04:00
do_action ( 'start_previewing_theme' , $this );
2012-04-25 11:44:06 -04:00
}
/**
* Stop previewing the selected theme .
*
* Removes filters to change the current theme .
*
* @ since 3.4 . 0
*/
public function stop_previewing_theme () {
if ( ! $this -> is_preview () )
return ;
$this -> previewing = false ;
2012-06-12 14:39:16 -04:00
if ( ! $this -> is_theme_active () ) {
remove_filter ( 'template' , array ( $this , 'get_template' ) );
remove_filter ( 'stylesheet' , array ( $this , 'get_stylesheet' ) );
remove_filter ( 'pre_option_current_theme' , array ( $this , 'current_theme' ) );
2012-06-12 15:27:41 -04:00
2012-06-12 14:39:16 -04:00
// @link: http://core.trac.wordpress.org/ticket/20027
remove_filter ( 'pre_option_stylesheet' , array ( $this , 'get_stylesheet' ) );
remove_filter ( 'pre_option_template' , array ( $this , 'get_template' ) );
2012-06-12 15:27:41 -04:00
2012-06-12 14:39:16 -04:00
// Handle custom theme roots.
remove_filter ( 'pre_option_stylesheet_root' , array ( $this , 'get_stylesheet_root' ) );
remove_filter ( 'pre_option_template_root' , array ( $this , 'get_template_root' ) );
}
2012-04-25 11:44:06 -04:00
2012-04-30 13:20:32 -04:00
do_action ( 'stop_previewing_theme' , $this );
2012-02-24 23:12:43 -05:00
}
2012-05-23 13:56:42 -04:00
/**
2012-05-23 17:21:29 -04:00
* Get the theme being customized .
2012-05-23 13:56:42 -04:00
*
* @ since 3.4 . 0
*
* @ return WP_Theme
*/
2012-05-23 17:21:29 -04:00
public function theme () {
return $this -> theme ;
}
/**
* Get the registered settings .
*
* @ since 3.4 . 0
*
* @ return array
*/
public function settings () {
return $this -> settings ;
}
/**
* Get the registered controls .
*
* @ since 3.4 . 0
*
* @ return array
*/
public function controls () {
return $this -> controls ;
}
/**
* Get the registered sections .
*
* @ since 3.4 . 0
*
* @ return array
*/
public function sections () {
return $this -> sections ;
2012-05-23 13:56:42 -04:00
}
2012-05-16 01:55:54 -04:00
/**
* Checks if the current theme is active .
*
* @ since 3.4 . 0
2012-05-23 13:56:42 -04:00
*
* @ return bool
2012-05-16 01:55:54 -04:00
*/
2012-05-23 13:56:42 -04:00
public function is_theme_active () {
2012-05-16 01:55:54 -04:00
return $this -> get_stylesheet () == $this -> original_stylesheet ;
}
2012-02-24 23:12:43 -05:00
/**
2012-02-29 19:14:51 -05:00
* Register styles / scripts and initialize the preview of each setting
2012-02-24 23:12:43 -05:00
*
* @ since 3.4 . 0
*/
2012-02-29 19:14:51 -05:00
public function wp_loaded () {
2012-04-30 13:20:32 -04:00
do_action ( 'customize_register' , $this );
2012-02-24 23:12:43 -05:00
2012-03-28 11:04:11 -04:00
if ( $this -> is_preview () && ! is_admin () )
$this -> customize_preview_init ();
2012-03-21 18:55:43 -04:00
}
2012-05-23 21:48:32 -04:00
/**
* Prevents AJAX requests from following redirects when previewing a theme
* by issuing a 200 response instead of a 30 x .
*
* Instead , the JS will sniff out the location header .
*
* @ since 3.4 . 0
2012-07-26 17:45:33 -04:00
*
* @ param $status
* @ return int
2012-05-23 21:48:32 -04:00
*/
public function wp_redirect_status ( $status ) {
if ( $this -> is_preview () && ! is_admin () )
return 200 ;
return $status ;
}
2012-04-30 11:46:17 -04:00
/**
* Decode the $_POST attribute used to override the WP_Customize_Setting values .
*
* @ since 3.4 . 0
2012-07-26 17:45:33 -04:00
*
* @ param mixed $setting A WP_Customize_Setting derived object
* @ return string Sanitized attribute
2012-04-30 11:46:17 -04:00
*/
public function post_value ( $setting ) {
if ( ! isset ( $this -> _post_values ) ) {
if ( isset ( $_POST [ 'customized' ] ) )
2013-03-03 11:30:38 -05:00
$this -> _post_values = json_decode ( wp_unslash ( $_POST [ 'customized' ] ), true );
2012-04-30 11:46:17 -04:00
else
$this -> _post_values = false ;
}
if ( isset ( $this -> _post_values [ $setting -> id ] ) )
return $setting -> sanitize ( $this -> _post_values [ $setting -> id ] );
}
2012-03-21 18:55:43 -04:00
/**
* Print javascript settings .
*
* @ since 3.4 . 0
*/
public function customize_preview_init () {
2012-06-26 14:48:18 -04:00
$this -> nonce_tick = check_ajax_referer ( 'preview-customize_' . $this -> get_stylesheet (), 'nonce' );
2012-03-21 18:55:43 -04:00
$this -> prepare_controls ();
2012-02-24 23:12:43 -05:00
wp_enqueue_script ( 'customize-preview' );
2012-05-23 22:07:16 -04:00
add_action ( 'wp_head' , array ( $this , 'customize_preview_base' ) );
2012-06-05 08:26:57 -04:00
add_action ( 'wp_head' , array ( $this , 'customize_preview_html5' ) );
2012-02-24 23:12:43 -05:00
add_action ( 'wp_footer' , array ( $this , 'customize_preview_settings' ), 20 );
2012-05-26 00:08:44 -04:00
add_action ( 'shutdown' , array ( $this , 'customize_preview_signature' ), 1000 );
2012-05-26 00:34:45 -04:00
add_filter ( 'wp_die_handler' , array ( $this , 'remove_preview_signature' ) );
2012-02-24 23:12:43 -05:00
foreach ( $this -> settings as $setting ) {
$setting -> preview ();
}
2012-03-21 18:55:43 -04:00
2012-04-30 13:20:32 -04:00
do_action ( 'customize_preview_init' , $this );
2012-02-24 23:12:43 -05:00
}
2012-05-23 22:07:16 -04:00
/**
* Print base element for preview frame .
*
* @ since 3.4 . 0
*/
public function customize_preview_base () {
?> <base href="<?php echo home_url( '/' ); ?>" /><?php
}
2012-03-21 18:55:43 -04:00
2012-06-05 08:26:57 -04:00
/**
* Print a workaround to handle HTML5 tags in IE < 9
*
* @ since 3.4 . 0
*/
public function customize_preview_html5 () { ?>
<!-- [ if lt IE 9 ] >
< script type = " text/javascript " >
var e = [ 'abbr' , 'article' , 'aside' , 'audio' , 'canvas' , 'datalist' , 'details' ,
'figure' , 'footer' , 'header' , 'hgroup' , 'mark' , 'menu' , 'meter' , 'nav' ,
'output' , 'progress' , 'section' , 'time' , 'video' ];
for ( var i = 0 ; i < e . length ; i ++ ) {
document . createElement ( e [ i ] );
}
</ script >
<! [ endif ] -->< ? php
}
2012-02-24 23:12:43 -05:00
/**
2012-05-23 22:07:16 -04:00
* Print javascript settings for preview frame .
2012-02-24 23:12:43 -05:00
*
* @ since 3.4 . 0
*/
public function customize_preview_settings () {
$settings = array (
2012-06-04 11:51:46 -04:00
'values' => array (),
'channel' => esc_js ( $_POST [ 'customize_messenger_channel' ] ),
2012-02-24 23:12:43 -05:00
);
2012-03-05 21:49:02 -05:00
2012-06-26 14:48:18 -04:00
if ( 2 == $this -> nonce_tick ) {
2012-07-26 17:45:33 -04:00
$settings [ 'nonce' ] = array (
'save' => wp_create_nonce ( 'save-customize_' . $this -> get_stylesheet () ),
'preview' => wp_create_nonce ( 'preview-customize_' . $this -> get_stylesheet () )
);
}
2012-06-26 14:48:18 -04:00
2012-03-05 21:49:02 -05:00
foreach ( $this -> settings as $id => $setting ) {
2012-05-16 16:59:02 -04:00
$settings [ 'values' ][ $id ] = $setting -> js_value ();
2012-03-05 21:49:02 -05:00
}
2012-02-24 23:12:43 -05:00
?>
< script type = " text/javascript " >
2012-05-07 16:03:39 -04:00
var _wpCustomizeSettings = < ? php echo json_encode ( $settings ); ?> ;
2012-02-24 23:12:43 -05:00
</ script >
< ? php
}
2012-05-26 00:08:44 -04:00
/**
* Prints a signature so we can ensure the customizer was properly executed .
*
* @ since 3.4 . 0
*/
public function customize_preview_signature () {
echo 'WP_CUSTOMIZER_SIGNATURE' ;
}
2012-05-26 00:34:45 -04:00
/**
* Removes the signature in case we experience a case where the customizer was not properly executed .
*
* @ since 3.4 . 0
*/
public function remove_preview_signature ( $return = null ) {
remove_action ( 'shutdown' , array ( $this , 'customize_preview_signature' ), 1000 );
return $return ;
}
2012-02-24 23:12:43 -05:00
/**
* Is it a theme preview ?
*
* @ since 3.4 . 0
*
* @ return bool True if it ' s a preview , false if not .
*/
public function is_preview () {
return ( bool ) $this -> previewing ;
}
/**
* Retrieve the template name of the previewed theme .
*
* @ since 3.4 . 0
*
* @ return string Template name .
*/
public function get_template () {
2012-06-12 14:39:16 -04:00
return $this -> theme () -> get_template ();
2012-02-24 23:12:43 -05:00
}
/**
* Retrieve the stylesheet name of the previewed theme .
*
* @ since 3.4 . 0
*
* @ return string Stylesheet name .
*/
public function get_stylesheet () {
2012-06-12 14:39:16 -04:00
return $this -> theme () -> get_stylesheet ();
2012-02-24 23:12:43 -05:00
}
/**
* Retrieve the template root of the previewed theme .
*
* @ since 3.4 . 0
*
* @ return string Theme root .
*/
public function get_template_root () {
2012-04-17 17:43:47 -04:00
return get_raw_theme_root ( $this -> get_template (), true );
2012-02-24 23:12:43 -05:00
}
/**
* Retrieve the stylesheet root of the previewed theme .
*
* @ since 3.4 . 0
*
* @ return string Theme root .
*/
public function get_stylesheet_root () {
2012-04-17 17:43:47 -04:00
return get_raw_theme_root ( $this -> get_stylesheet (), true );
2012-02-24 23:12:43 -05:00
}
/**
* Filter the current theme and return the name of the previewed theme .
*
* @ since 3.4 . 0
*
2012-07-26 17:45:33 -04:00
* @ param $current_theme { @ internal Parameter is not used }
2012-02-24 23:12:43 -05:00
* @ return string Theme name .
*/
public function current_theme ( $current_theme ) {
2012-06-12 14:39:16 -04:00
return $this -> theme () -> display ( 'Name' );
2012-02-24 23:12:43 -05:00
}
/**
* Switch the theme and trigger the save action of each setting .
*
* @ since 3.4 . 0
*/
public function save () {
2012-04-25 11:44:06 -04:00
if ( ! $this -> is_preview () )
2012-04-30 11:46:17 -04:00
die ;
2012-02-24 23:12:43 -05:00
2012-06-26 14:48:18 -04:00
check_ajax_referer ( 'save-customize_' . $this -> get_stylesheet (), 'nonce' );
2012-02-24 23:12:43 -05:00
// Do we have to switch themes?
2012-06-12 14:39:16 -04:00
if ( ! $this -> is_theme_active () ) {
2012-04-25 11:44:06 -04:00
// Temporarily stop previewing the theme to allow switch_themes()
// to operate properly.
$this -> stop_previewing_theme ();
2012-06-26 01:21:04 -04:00
switch_theme ( $this -> get_stylesheet () );
2012-04-25 11:44:06 -04:00
$this -> start_previewing_theme ();
2012-02-24 23:12:43 -05:00
}
2012-04-30 13:20:32 -04:00
do_action ( 'customize_save' , $this );
2012-02-24 23:12:43 -05:00
foreach ( $this -> settings as $setting ) {
$setting -> save ();
}
2013-05-24 06:33:30 -04:00
do_action ( 'customize_save_after' , $this );
2012-04-30 11:46:17 -04:00
die ;
2012-02-24 23:12:43 -05:00
}
/**
* Add a customize setting .
*
* @ since 3.4 . 0
*
2012-03-28 00:14:09 -04:00
* @ param string $id A specific ID of the setting . Can be a
2012-02-24 23:12:43 -05:00
* theme mod or option name .
* @ param array $args Setting arguments .
*/
public function add_setting ( $id , $args = array () ) {
2012-03-28 00:14:09 -04:00
if ( is_a ( $id , 'WP_Customize_Setting' ) )
$setting = $id ;
else
$setting = new WP_Customize_Setting ( $this , $id , $args );
2012-02-24 23:12:43 -05:00
$this -> settings [ $setting -> id ] = $setting ;
}
/**
* Retrieve a customize setting .
*
* @ since 3.4 . 0
*
2012-03-28 00:14:09 -04:00
* @ param string $id A specific ID of the setting .
2012-02-24 23:12:43 -05:00
* @ return object The settings object .
*/
public function get_setting ( $id ) {
if ( isset ( $this -> settings [ $id ] ) )
return $this -> settings [ $id ];
}
/**
* Remove a customize setting .
*
* @ since 3.4 . 0
*
2012-03-28 00:14:09 -04:00
* @ param string $id A specific ID of the setting .
2012-02-24 23:12:43 -05:00
*/
public function remove_setting ( $id ) {
unset ( $this -> settings [ $id ] );
}
/**
* Add a customize section .
*
* @ since 3.4 . 0
*
2012-03-28 00:14:09 -04:00
* @ param string $id A specific ID of the section .
2012-02-24 23:12:43 -05:00
* @ param array $args Section arguments .
*/
public function add_section ( $id , $args = array () ) {
2012-03-28 00:14:09 -04:00
if ( is_a ( $id , 'WP_Customize_Section' ) )
$section = $id ;
else
$section = new WP_Customize_Section ( $this , $id , $args );
2012-02-24 23:12:43 -05:00
$this -> sections [ $section -> id ] = $section ;
}
/**
* Retrieve a customize section .
*
* @ since 3.4 . 0
*
2012-03-28 00:14:09 -04:00
* @ param string $id A specific ID of the section .
2012-02-24 23:12:43 -05:00
* @ return object The section object .
*/
public function get_section ( $id ) {
if ( isset ( $this -> sections [ $id ] ) )
return $this -> sections [ $id ];
}
/**
* Remove a customize section .
*
* @ since 3.4 . 0
*
2012-03-28 00:14:09 -04:00
* @ param string $id A specific ID of the section .
2012-02-24 23:12:43 -05:00
*/
public function remove_section ( $id ) {
unset ( $this -> sections [ $id ] );
}
2012-03-28 00:14:09 -04:00
/**
* Add a customize control .
*
* @ since 3.4 . 0
*
* @ param string $id A specific ID of the control .
* @ param array $args Setting arguments .
*/
public function add_control ( $id , $args = array () ) {
if ( is_a ( $id , 'WP_Customize_Control' ) )
$control = $id ;
else
$control = new WP_Customize_Control ( $this , $id , $args );
$this -> controls [ $control -> id ] = $control ;
}
/**
* Retrieve a customize control .
*
* @ since 3.4 . 0
*
* @ param string $id A specific ID of the control .
* @ return object The settings object .
*/
public function get_control ( $id ) {
if ( isset ( $this -> controls [ $id ] ) )
return $this -> controls [ $id ];
}
/**
* Remove a customize setting .
*
* @ since 3.4 . 0
*
* @ param string $id A specific ID of the control .
*/
public function remove_control ( $id ) {
unset ( $this -> controls [ $id ] );
}
2012-02-24 23:12:43 -05:00
/**
* Helper function to compare two objects by priority .
*
* @ since 3.4 . 0
*
* @ param object $a Object A .
* @ param object $b Object B .
2012-07-26 17:45:33 -04:00
* @ return int
2012-02-24 23:12:43 -05:00
*/
2012-03-21 18:55:43 -04:00
protected final function _cmp_priority ( $a , $b ) {
2012-02-24 23:12:43 -05:00
$ap = $a -> priority ;
$bp = $b -> priority ;
if ( $ap == $bp )
return 0 ;
return ( $ap > $bp ) ? 1 : - 1 ;
}
/**
2012-03-21 18:55:43 -04:00
* Prepare settings and sections .
2012-02-24 23:12:43 -05:00
*
* @ since 3.4 . 0
*/
public function prepare_controls () {
2012-03-28 00:14:09 -04:00
// Prepare controls
2012-02-24 23:12:43 -05:00
// Reversing makes uasort sort by time added when conflicts occur.
2012-03-28 00:14:09 -04:00
$this -> controls = array_reverse ( $this -> controls );
$controls = array ();
2012-03-21 18:55:43 -04:00
2012-03-28 00:14:09 -04:00
foreach ( $this -> controls as $id => $control ) {
if ( ! isset ( $this -> sections [ $control -> section ] ) || ! $control -> check_capabilities () )
2012-02-24 23:12:43 -05:00
continue ;
2012-03-28 00:14:09 -04:00
$this -> sections [ $control -> section ] -> controls [] = $control ;
$controls [ $id ] = $control ;
2012-02-24 23:12:43 -05:00
}
2012-03-28 00:14:09 -04:00
$this -> controls = $controls ;
2012-03-21 18:55:43 -04:00
// Prepare sections
$this -> sections = array_reverse ( $this -> sections );
uasort ( $this -> sections , array ( $this , '_cmp_priority' ) );
$sections = array ();
2012-02-24 23:12:43 -05:00
foreach ( $this -> sections as $section ) {
2012-03-28 00:14:09 -04:00
if ( ! $section -> check_capabilities () || ! $section -> controls )
2012-03-21 18:55:43 -04:00
continue ;
2012-03-28 00:14:09 -04:00
usort ( $section -> controls , array ( $this , '_cmp_priority' ) );
2012-03-21 18:55:43 -04:00
$sections [] = $section ;
}
$this -> sections = $sections ;
}
/**
* Enqueue scripts for customize controls .
*
* @ since 3.4 . 0
*/
public function enqueue_control_scripts () {
2012-03-28 00:14:09 -04:00
foreach ( $this -> controls as $control ) {
$control -> enqueue ();
2012-02-24 23:12:43 -05:00
}
}
/**
* Register some default controls .
*
* @ since 3.4 . 0
*/
public function register_controls () {
2012-05-25 15:52:54 -04:00
/* Site Title & Tagline */
2012-02-24 23:12:43 -05:00
2012-05-25 15:52:54 -04:00
$this -> add_section ( 'title_tagline' , array (
'title' => __ ( 'Site Title & Tagline' ),
'priority' => 20 ,
) );
$this -> add_setting ( 'blogname' , array (
'default' => get_option ( 'blogname' ),
'type' => 'option' ,
'capability' => 'manage_options' ,
) );
$this -> add_control ( 'blogname' , array (
'label' => __ ( 'Site Title' ),
'section' => 'title_tagline' ,
) );
$this -> add_setting ( 'blogdescription' , array (
'default' => get_option ( 'blogdescription' ),
'type' => 'option' ,
'capability' => 'manage_options' ,
) );
$this -> add_control ( 'blogdescription' , array (
'label' => __ ( 'Tagline' ),
'section' => 'title_tagline' ,
) );
/* Colors */
$this -> add_section ( 'colors' , array (
'title' => __ ( 'Colors' ),
'priority' => 40 ,
2012-02-24 23:12:43 -05:00
) );
$this -> add_setting ( 'header_textcolor' , array (
2012-03-28 00:14:09 -04:00
'theme_supports' => array ( 'custom-header' , 'header-text' ),
'default' => get_theme_support ( 'custom-header' , 'default-text-color' ),
2012-05-26 14:44:31 -04:00
'sanitize_callback' => array ( $this , '_sanitize_header_textcolor' ),
'sanitize_js_callback' => 'maybe_hash_hex_color' ,
2012-03-28 00:14:09 -04:00
) );
2012-05-25 15:52:54 -04:00
// Input type: checkbox
// With custom value
2012-03-28 00:14:09 -04:00
$this -> add_control ( 'display_header_text' , array (
'settings' => 'header_textcolor' ,
'label' => __ ( 'Display Header Text' ),
2012-05-25 15:52:54 -04:00
'section' => 'title_tagline' ,
2012-03-28 00:14:09 -04:00
'type' => 'checkbox' ,
2012-02-24 23:12:43 -05:00
) );
2012-04-25 17:03:29 -04:00
$this -> add_control ( new WP_Customize_Color_Control ( $this , 'header_textcolor' , array (
2012-05-26 11:24:42 -04:00
'label' => __ ( 'Header Text Color' ),
2012-05-25 15:52:54 -04:00
'section' => 'colors' ,
2012-04-25 17:03:29 -04:00
) ) );
2012-02-24 23:12:43 -05:00
// Input type: Color
// With sanitize_callback
$this -> add_setting ( 'background_color' , array (
2012-05-26 14:44:31 -04:00
'default' => get_theme_support ( 'custom-background' , 'default-color' ),
'theme_supports' => 'custom-background' ,
'sanitize_callback' => 'sanitize_hex_color_no_hash' ,
'sanitize_js_callback' => 'maybe_hash_hex_color' ,
2012-03-28 00:14:09 -04:00
) );
2012-04-25 17:03:29 -04:00
$this -> add_control ( new WP_Customize_Color_Control ( $this , 'background_color' , array (
2012-03-28 00:14:09 -04:00
'label' => __ ( 'Background Color' ),
2012-05-25 15:52:54 -04:00
'section' => 'colors' ,
2012-04-25 17:03:29 -04:00
) ) );
2012-03-15 00:14:05 -04:00
2012-05-25 15:52:54 -04:00
/* Custom Header */
$this -> add_section ( 'header_image' , array (
'title' => __ ( 'Header Image' ),
'theme_supports' => 'custom-header' ,
'priority' => 60 ,
) );
2012-06-09 20:32:19 -04:00
$this -> add_setting ( new WP_Customize_Filter_Setting ( $this , 'header_image' , array (
2012-05-25 15:52:54 -04:00
'default' => get_theme_support ( 'custom-header' , 'default-image' ),
'theme_supports' => 'custom-header' ,
2012-06-09 20:32:19 -04:00
) ) );
$this -> add_setting ( new WP_Customize_Header_Image_Setting ( $this , 'header_image_data' , array (
// 'default' => get_theme_support( 'custom-header', 'default-image' ),
'theme_supports' => 'custom-header' ,
) ) );
2012-05-25 15:52:54 -04:00
$this -> add_control ( new WP_Customize_Header_Image_Control ( $this ) );
/* Custom Background */
$this -> add_section ( 'background_image' , array (
'title' => __ ( 'Background Image' ),
'theme_supports' => 'custom-background' ,
'priority' => 80 ,
) );
2012-03-15 00:14:05 -04:00
$this -> add_setting ( 'background_image' , array (
2012-03-23 21:02:29 -04:00
'default' => get_theme_support ( 'custom-background' , 'default-image' ),
2012-03-28 00:14:09 -04:00
'theme_supports' => 'custom-background' ,
) );
2012-06-11 16:49:45 -04:00
$this -> add_setting ( new WP_Customize_Background_Image_Setting ( $this , 'background_image_thumb' , array (
'theme_supports' => 'custom-background' ,
) ) );
2012-05-25 16:26:25 -04:00
$this -> add_control ( new WP_Customize_Background_Image_Control ( $this ) );
2012-03-22 04:07:44 -04:00
$this -> add_setting ( 'background_repeat' , array (
2012-03-28 00:14:09 -04:00
'default' => 'repeat' ,
'theme_supports' => 'custom-background' ,
) );
$this -> add_control ( 'background_repeat' , array (
'label' => __ ( 'Background Repeat' ),
2012-05-25 15:52:54 -04:00
'section' => 'background_image' ,
2012-03-28 00:14:09 -04:00
'type' => 'radio' ,
2012-03-22 04:07:44 -04:00
'choices' => array (
'no-repeat' => __ ( 'No Repeat' ),
'repeat' => __ ( 'Tile' ),
'repeat-x' => __ ( 'Tile Horizontally' ),
'repeat-y' => __ ( 'Tile Vertically' ),
),
) );
$this -> add_setting ( 'background_position_x' , array (
2012-03-28 00:14:09 -04:00
'default' => 'left' ,
'theme_supports' => 'custom-background' ,
) );
$this -> add_control ( 'background_position_x' , array (
'label' => __ ( 'Background Position' ),
2012-05-25 15:52:54 -04:00
'section' => 'background_image' ,
2012-03-28 00:14:09 -04:00
'type' => 'radio' ,
2012-03-22 04:07:44 -04:00
'choices' => array (
'left' => __ ( 'Left' ),
'center' => __ ( 'Center' ),
'right' => __ ( 'Right' ),
),
) );
$this -> add_setting ( 'background_attachment' , array (
2012-03-28 00:14:09 -04:00
'default' => 'fixed' ,
'theme_supports' => 'custom-background' ,
) );
$this -> add_control ( 'background_attachment' , array (
'label' => __ ( 'Background Attachment' ),
2012-05-25 15:52:54 -04:00
'section' => 'background_image' ,
2012-03-28 00:14:09 -04:00
'type' => 'radio' ,
2012-03-22 04:07:44 -04:00
'choices' => array (
'fixed' => __ ( 'Fixed' ),
'scroll' => __ ( 'Scroll' ),
),
2012-02-24 23:12:43 -05:00
) );
2012-05-25 14:41:22 -04:00
// If the theme is using the default background callback, we can update
// the background CSS using postMessage.
if ( get_theme_support ( 'custom-background' , 'wp-head-callback' ) === '_custom_background_cb' ) {
foreach ( array ( 'color' , 'image' , 'position_x' , 'repeat' , 'attachment' ) as $prop ) {
$this -> get_setting ( 'background_' . $prop ) -> transport = 'postMessage' ;
}
}
2012-02-24 23:12:43 -05:00
/* Nav Menus */
$locations = get_registered_nav_menus ();
$menus = wp_get_nav_menus ();
$menu_locations = get_nav_menu_locations ();
$num_locations = count ( array_keys ( $locations ) );
$this -> add_section ( 'nav' , array (
'title' => __ ( 'Navigation' ),
'theme_supports' => 'menus' ,
2012-05-25 15:52:54 -04:00
'priority' => 100 ,
2012-04-23 19:03:09 -04:00
'description' => sprintf ( _n ( 'Your theme supports %s menu. Select which menu you would like to use.' , 'Your theme supports %s menus. Select which menu appears in each location.' , $num_locations ), number_format_i18n ( $num_locations ) ) . " \n \n " . __ ( 'You can edit your menu content on the Menus screen in the Appearance section.' ),
2012-02-24 23:12:43 -05:00
) );
2012-04-23 19:03:09 -04:00
if ( $menus ) {
$choices = array ( 0 => __ ( '— Select —' ) );
2012-02-24 23:12:43 -05:00
foreach ( $menus as $menu ) {
2013-05-08 20:22:02 -04:00
$choices [ $menu -> term_id ] = wp_html_excerpt ( $menu -> name , 40 , '…' );
2012-02-24 23:12:43 -05:00
}
2012-04-23 19:03:09 -04:00
foreach ( $locations as $location => $description ) {
$menu_setting_id = " nav_menu_locations[ { $location } ] " ;
2012-03-28 00:14:09 -04:00
2012-04-23 19:03:09 -04:00
$this -> add_setting ( $menu_setting_id , array (
'sanitize_callback' => 'absint' ,
'theme_supports' => 'menus' ,
) );
2012-03-28 00:14:09 -04:00
2012-04-23 19:03:09 -04:00
$this -> add_control ( $menu_setting_id , array (
'label' => $description ,
'section' => 'nav' ,
'type' => 'select' ,
'choices' => $choices ,
) );
}
2012-02-24 23:12:43 -05:00
}
/* Static Front Page */
// #WP19627
$this -> add_section ( 'static_front_page' , array (
'title' => __ ( 'Static Front Page' ),
// 'theme_supports' => 'static-front-page',
2012-05-25 15:52:54 -04:00
'priority' => 120 ,
2012-02-24 23:12:43 -05:00
'description' => __ ( 'Your theme supports a static front page.' ),
) );
$this -> add_setting ( 'show_on_front' , array (
'default' => get_option ( 'show_on_front' ),
2012-03-22 03:17:26 -04:00
'capability' => 'manage_options' ,
2012-03-28 00:14:09 -04:00
'type' => 'option' ,
// 'theme_supports' => 'static-front-page',
) );
$this -> add_control ( 'show_on_front' , array (
'label' => __ ( 'Front page displays' ),
'section' => 'static_front_page' ,
'type' => 'radio' ,
2012-04-06 20:18:02 -04:00
'choices' => array (
'posts' => __ ( 'Your latest posts' ),
'page' => __ ( 'A static page' ),
),
2012-02-24 23:12:43 -05:00
) );
$this -> add_setting ( 'page_on_front' , array (
2012-03-28 00:14:09 -04:00
'type' => 'option' ,
'capability' => 'manage_options' ,
2012-02-24 23:12:43 -05:00
// 'theme_supports' => 'static-front-page',
2012-03-28 00:14:09 -04:00
) );
$this -> add_control ( 'page_on_front' , array (
'label' => __ ( 'Front page' ),
'section' => 'static_front_page' ,
'type' => 'dropdown-pages' ,
2012-02-24 23:12:43 -05:00
) );
$this -> add_setting ( 'page_for_posts' , array (
'type' => 'option' ,
2012-03-22 03:17:26 -04:00
'capability' => 'manage_options' ,
2012-03-28 00:14:09 -04:00
// 'theme_supports' => 'static-front-page',
) );
$this -> add_control ( 'page_for_posts' , array (
'label' => __ ( 'Posts page' ),
'section' => 'static_front_page' ,
'type' => 'dropdown-pages' ,
2012-02-24 23:12:43 -05:00
) );
}
2012-05-23 11:36:27 -04:00
2012-05-26 14:44:31 -04:00
/**
* Callback for validating the header_textcolor value .
*
* Accepts 'blank' , and otherwise uses sanitize_hex_color_no_hash () .
2013-07-12 16:41:46 -04:00
* Returns default text color if hex color is empty .
2012-05-26 14:44:31 -04:00
*
* @ since 3.4 . 0
2012-07-26 17:45:33 -04:00
*
* @ param string $color
* @ return string
2012-05-26 14:44:31 -04:00
*/
public function _sanitize_header_textcolor ( $color ) {
2013-07-12 16:41:46 -04:00
if ( 'blank' === $color )
return 'blank' ;
$color = sanitize_hex_color_no_hash ( $color );
if ( empty ( $color ) )
$color = get_theme_support ( 'custom-header' , 'default-text-color' );
return $color ;
2012-05-26 14:44:31 -04:00
}
};
2012-05-23 11:36:27 -04:00
2012-05-26 14:44:31 -04:00
/**
* Validates a hex color .
*
* Returns either '' , a 3 or 6 digit hex color ( with #), or null.
* For validating values without a #, see sanitize_hex_color_no_hash().
*
* @ since 3.4 . 0
2012-07-26 17:45:33 -04:00
*
* @ param string $color
* @ return string | null
2012-05-26 14:44:31 -04:00
*/
function sanitize_hex_color ( $color ) {
if ( '' === $color )
return '' ;
2012-02-24 23:12:43 -05:00
2012-05-25 16:58:49 -04:00
// 3 or 6 hex digits, or the empty string.
2012-05-26 14:44:31 -04:00
if ( preg_match ( '|^#([A-Fa-f0-9]{3}){1,2}$|' , $color ) )
2012-02-24 23:12:43 -05:00
return $color ;
2012-05-25 14:54:57 -04:00
return null ;
2012-05-23 13:56:42 -04:00
}
2012-05-26 14:44:31 -04:00
/**
* Sanitizes a hex color without a hash . Use sanitize_hex_color () when possible .
*
* Saving hex colors without a hash puts the burden of adding the hash on the
* UI , which makes it difficult to use or upgrade to other color types such as
* rgba , hsl , rgb , and html color names .
*
* Returns either '' , a 3 or 6 digit hex color ( without a #), or null.
*
* @ since 3.4 . 0
2012-07-26 17:45:33 -04:00
* @ uses sanitize_hex_color ()
*
* @ param string $color
* @ return string | null
2012-05-26 14:44:31 -04:00
*/
function sanitize_hex_color_no_hash ( $color ) {
$color = ltrim ( $color , '#' );
if ( '' === $color )
return '' ;
return sanitize_hex_color ( '#' . $color ) ? $color : null ;
}
/**
* Ensures that any hex color is properly hashed .
* Otherwise , returns value untouched .
*
* This method should only be necessary if using sanitize_hex_color_no_hash () .
*
* @ since 3.4 . 0
2012-07-26 17:45:33 -04:00
*
* @ param string $color
* @ return string
2012-05-26 14:44:31 -04:00
*/
function maybe_hash_hex_color ( $color ) {
if ( $unhashed = sanitize_hex_color_no_hash ( $color ) )
return '#' . $unhashed ;
return $color ;
2012-06-08 15:22:11 -04:00
}