2012-02-25 05:12:43 +01:00
< ? php
/**
2012-07-26 23:45:33 +02:00
* Customize Manager .
2012-02-25 05:12:43 +01:00
*
2014-03-04 21:21:14 +01:00
* Bootstraps the Customize experience on the server - side .
*
* Sets up the theme - switching process if a theme other than the active one is
* being previewed and customized .
*
* Serves as a factory for Customize Controls and Settings , and
* instantiates default Customize Controls and Settings .
*
2012-02-25 05:12:43 +01:00
* @ package WordPress
* @ subpackage Customize
* @ since 3.4 . 0
*/
2012-05-23 19:56:42 +02:00
final class WP_Customize_Manager {
2014-03-04 21:21:14 +01:00
/**
2014-08-09 01:31:15 +02:00
* An instance of the theme being previewed .
2014-03-04 21:21:14 +01:00
*
* @ var WP_Theme
*/
2012-04-17 23:43:47 +02:00
protected $theme ;
2014-03-04 21:21:14 +01:00
/**
* The directory name of the previously active theme ( within the theme_root ) .
*
* @ var string
*/
2012-04-17 22:49:39 +02:00
protected $original_stylesheet ;
2014-03-04 21:21:14 +01:00
/**
2014-08-09 01:31:15 +02:00
* Whether this is a Customizer pageload .
2014-03-04 21:21:14 +01:00
*
* @ var boolean
*/
2012-02-25 05:12:43 +01:00
protected $previewing = false ;
2014-03-28 15:07:14 +01:00
/**
2014-10-15 19:21:19 +02:00
* Methods and properties deailing with managing widgets in the Customizer .
2014-03-28 15:07:14 +01:00
*
* @ var WP_Customize_Widgets
*/
public $widgets ;
2014-08-14 06:43:16 +02:00
protected $settings = array ();
protected $containers = array ();
protected $panels = array ();
protected $sections = array ();
protected $controls = array ();
2012-02-25 05:12:43 +01:00
2012-06-26 20:48:18 +02:00
protected $nonce_tick ;
2012-04-30 17:46:17 +02:00
protected $customized ;
2014-03-04 21:21:14 +01:00
/**
2014-10-24 18:32:18 +02:00
* Controls that may be rendered from JS templates .
*
* @ since 4.1 . 0
2014-11-28 11:52:22 +01:00
* @ access protected
* @ var array
2014-10-24 18:32:18 +02:00
*/
protected $registered_control_types = array ();
2014-12-01 00:33:23 +01:00
/**
2015-02-03 11:15:21 +01:00
* Unsanitized values for Customize Settings parsed from $_POST [ 'customized' ] .
2014-03-04 21:21:14 +01:00
*
2015-02-09 00:11:25 +01:00
* @ var array
2014-03-04 21:21:14 +01:00
*/
2012-04-30 17:46:17 +02:00
private $_post_values ;
2012-02-25 05:12:43 +01:00
/**
* Constructor .
*
* @ since 3.4 . 0
*/
public function __construct () {
2015-02-03 11:15:21 +01:00
require_once ( ABSPATH . WPINC . '/class-wp-customize-setting.php' );
require_once ( ABSPATH . WPINC . '/class-wp-customize-panel.php' );
require_once ( ABSPATH . WPINC . '/class-wp-customize-section.php' );
require_once ( ABSPATH . WPINC . '/class-wp-customize-control.php' );
require_once ( ABSPATH . WPINC . '/class-wp-customize-widgets.php' );
2014-03-05 21:41:14 +01:00
2014-03-28 15:07:14 +01:00
$this -> widgets = new WP_Customize_Widgets ( $this );
2012-02-25 05:12:43 +01:00
2012-06-08 21:22:11 +02:00
add_filter ( 'wp_die_handler' , array ( $this , 'wp_die_handler' ) );
2012-04-25 17:44:06 +02:00
add_action ( 'setup_theme' , array ( $this , 'setup_theme' ) );
2012-03-01 01:14:51 +01:00
add_action ( 'wp_loaded' , array ( $this , 'wp_loaded' ) );
2012-02-25 05:12:43 +01:00
2012-05-24 03:48:32 +02: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 );
2014-10-15 19:21:19 +02:00
// Do not spawn cron (especially the alternate cron) while running the Customizer.
2012-05-26 05:52:14 +02:00
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 17:46:17 +02:00
add_action ( 'wp_ajax_customize_save' , array ( $this , 'save' ) );
2012-03-21 23:55:43 +01:00
add_action ( 'customize_register' , array ( $this , 'register_controls' ) );
2015-02-09 00:11:25 +01:00
add_action ( 'customize_register' , array ( $this , 'register_dynamic_settings' ), 11 ); // allow code to create settings first
2012-03-21 23:55:43 +01:00
add_action ( 'customize_controls_init' , array ( $this , 'prepare_controls' ) );
add_action ( 'customize_controls_enqueue_scripts' , array ( $this , 'enqueue_control_scripts' ) );
2012-02-25 05:12:43 +01:00
}
2012-07-26 23:45:33 +02:00
/**
2012-06-08 21:22:11 +02:00
* Return true if it ' s an AJAX request .
*
* @ since 3.4 . 0
2015-02-09 00:11:25 +01:00
* @ since 4.2 . 0 Added $action param .
2012-07-26 23:45:33 +02:00
*
2015-02-09 00:11:25 +01:00
* @ param string | null $action whether the supplied Ajax action is being run .
2012-07-26 23:45:33 +02:00
* @ return bool
2012-06-08 21:22:11 +02:00
*/
2015-02-09 00:11:25 +01:00
public function doing_ajax ( $action = null ) {
$doing_ajax = ( defined ( 'DOING_AJAX' ) && DOING_AJAX );
if ( ! $doing_ajax ) {
return false ;
}
if ( ! $action ) {
return true ;
} else {
// Note: we can't just use doing_action( "wp_ajax_{$action}" ) because we need to check before admin-ajax.php gets to that point
return isset ( $_REQUEST [ 'action' ] ) && wp_unslash ( $_REQUEST [ 'action' ] ) === $action ;
}
2012-06-08 21:22:11 +02:00
}
/**
* Custom wp_die wrapper . Returns either the standard message for UI
* or the AJAX message .
*
* @ since 3.4 . 0
2012-07-26 23:45:33 +02:00
*
* @ param mixed $ajax_message AJAX return
2012-11-17 16:11:29 +01:00
* @ param mixed $message UI message
2012-06-08 21:22:11 +02:00
*/
2012-06-12 20:39:16 +02:00
protected function wp_die ( $ajax_message , $message = null ) {
2015-02-11 23:13:25 +01:00
if ( $this -> doing_ajax () || isset ( $_POST [ 'customized' ] ) ) {
2012-06-08 21:22:11 +02:00
wp_die ( $ajax_message );
2015-02-11 23:13:25 +01:00
}
2012-06-08 21:22:11 +02:00
2015-02-11 23:13:25 +01:00
if ( ! $message ) {
2012-06-12 20:39:16 +02:00
$message = __ ( 'Cheatin’ uh?' );
2015-02-11 23:13:25 +01:00
}
2012-06-12 20:39:16 +02:00
2012-06-08 21:22:11 +02:00
wp_die ( $message );
}
2012-02-25 05:12:43 +01:00
/**
2012-06-08 21:22:11 +02:00
* Return the AJAX wp_die () handler if it ' s a customized request .
2012-04-17 23:43:47 +02:00
*
2012-06-08 21:22:11 +02:00
* @ since 3.4 . 0
2012-07-26 23:45:33 +02:00
*
* @ return string
2012-06-08 21:22:11 +02:00
*/
public function wp_die_handler () {
2015-02-11 23:13:25 +01:00
if ( $this -> doing_ajax () || isset ( $_POST [ 'customized' ] ) ) {
2012-06-08 21:22:11 +02:00
return '_ajax_wp_die_handler' ;
2015-02-11 23:13:25 +01:00
}
2012-06-08 21:22:11 +02:00
return '_default_wp_die_handler' ;
}
2012-11-17 16:11:29 +01:00
2012-06-08 21:22:11 +02:00
/**
2012-07-26 23:45:33 +02:00
* Start preview and customize theme .
*
* Check if customize query variable exist . Init filters to filter the current theme .
2012-02-25 05:12:43 +01:00
*
* @ since 3.4 . 0
*/
2012-04-25 17:44:06 +02:00
public function setup_theme () {
2012-06-12 20:39:16 +02:00
send_origin_headers ();
2015-02-11 23:13:25 +01:00
$doing_ajax_or_is_customized = ( $this -> doing_ajax () || isset ( $_POST [ 'customized' ] ) );
if ( is_admin () && ! $doing_ajax_or_is_customized ) {
auth_redirect ();
} elseif ( $doing_ajax_or_is_customized && ! is_user_logged_in () ) {
$this -> wp_die ( 0 );
}
2012-06-07 17:25:45 +02:00
2012-06-12 20:39:16 +02:00
show_admin_bar ( false );
2014-07-14 21:01:16 +02:00
if ( ! current_user_can ( 'customize' ) ) {
2012-06-12 20:39:16 +02:00
$this -> wp_die ( - 1 );
2014-07-14 21:01:16 +02:00
}
2012-05-08 22:13:34 +02:00
2012-06-06 22:34:24 +02:00
$this -> original_stylesheet = get_stylesheet ();
$this -> theme = wp_get_theme ( isset ( $_REQUEST [ 'theme' ] ) ? $_REQUEST [ 'theme' ] : null );
2012-06-12 20:39:16 +02: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 {
2014-03-04 21:21:14 +01:00
// If the requested theme is not the active theme and the user doesn't have the
// switch_themes cap, bail.
2015-02-11 23:13:25 +01:00
if ( ! current_user_can ( 'switch_themes' ) ) {
2012-06-12 20:39:16 +02:00
$this -> wp_die ( - 1 );
2015-02-11 23:13:25 +01:00
}
2012-06-06 22:34:24 +02:00
2014-03-04 21:21:14 +01:00
// If the theme has errors while loading, bail.
2015-02-11 23:13:25 +01:00
if ( $this -> theme () -> errors () ) {
2012-06-12 20:39:16 +02:00
$this -> wp_die ( - 1 );
2015-02-11 23:13:25 +01:00
}
2012-06-06 22:34:24 +02:00
2014-03-04 21:21:14 +01:00
// If the theme isn't allowed per multisite settings, bail.
2015-02-11 23:13:25 +01:00
if ( ! $this -> theme () -> is_allowed () ) {
2012-06-12 20:39:16 +02:00
$this -> wp_die ( - 1 );
2015-02-11 23:13:25 +01:00
}
2012-06-12 20:39:16 +02:00
}
2012-06-06 22:34:24 +02:00
2012-04-25 17:44:06 +02:00
$this -> start_previewing_theme ();
2012-06-12 20:39:16 +02:00
}
2012-11-17 16:11:29 +01:00
2012-07-26 23:45:33 +02:00
/**
* Callback to validate a theme once it is loaded
*
* @ since 3.4 . 0
*/
2014-05-19 07:45:16 +02:00
public function after_setup_theme () {
2015-02-11 23:13:25 +01:00
$doing_ajax_or_is_customized = ( $this -> doing_ajax () || isset ( $_SERVER [ 'customized' ] ) );
if ( ! $doing_ajax_or_is_customized && ! validate_current_theme () ) {
2012-06-12 20:39:16 +02:00
wp_redirect ( 'themes.php?broken=true' );
exit ;
}
2012-04-25 17:44:06 +02:00
}
2012-02-25 05:12:43 +01:00
2012-04-25 17:44:06 +02:00
/**
2014-08-09 01:31:15 +02:00
* If the theme to be previewed isn ' t the active theme , add filter callbacks
* to swap it out at runtime .
2012-04-25 17:44:06 +02:00
*
* @ since 3.4 . 0
*/
public function start_previewing_theme () {
2012-06-06 22:34:24 +02:00
// Bail if we're already previewing.
2015-02-11 23:13:25 +01:00
if ( $this -> is_preview () ) {
2012-04-25 17:44:06 +02:00
return ;
2015-02-11 23:13:25 +01:00
}
2012-02-25 05:12:43 +01:00
2012-04-25 17:44:06 +02:00
$this -> previewing = true ;
2012-06-12 20:39:16 +02: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 21:27:41 +02:00
2014-09-29 15:28:16 +02:00
// @link: https://core.trac.wordpress.org/ticket/20027
2012-06-12 20:39:16 +02:00
add_filter ( 'pre_option_stylesheet' , array ( $this , 'get_stylesheet' ) );
add_filter ( 'pre_option_template' , array ( $this , 'get_template' ) );
2012-06-12 21:27:41 +02:00
2012-06-12 20:39:16 +02: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 23:43:47 +02:00
2014-03-06 15:11:15 +01:00
/**
* Fires once the Customizer theme preview has started .
*
* @ since 3.4 . 0
*
* @ param WP_Customize_Manager $this WP_Customize_Manager instance .
*/
2012-04-30 19:20:32 +02:00
do_action ( 'start_previewing_theme' , $this );
2012-04-25 17:44:06 +02:00
}
/**
* Stop previewing the selected theme .
*
* Removes filters to change the current theme .
*
* @ since 3.4 . 0
*/
public function stop_previewing_theme () {
2015-02-11 23:13:25 +01:00
if ( ! $this -> is_preview () ) {
2012-04-25 17:44:06 +02:00
return ;
2015-02-11 23:13:25 +01:00
}
2012-04-25 17:44:06 +02:00
$this -> previewing = false ;
2012-06-12 20:39:16 +02: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 21:27:41 +02:00
2014-09-29 15:28:16 +02:00
// @link: https://core.trac.wordpress.org/ticket/20027
2012-06-12 20:39:16 +02:00
remove_filter ( 'pre_option_stylesheet' , array ( $this , 'get_stylesheet' ) );
remove_filter ( 'pre_option_template' , array ( $this , 'get_template' ) );
2012-06-12 21:27:41 +02:00
2012-06-12 20:39:16 +02: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 17:44:06 +02:00
2014-03-06 15:11:15 +01:00
/**
* Fires once the Customizer theme preview has stopped .
*
* @ since 3.4 . 0
*
* @ param WP_Customize_Manager $this WP_Customize_Manager instance .
*/
2012-04-30 19:20:32 +02:00
do_action ( 'stop_previewing_theme' , $this );
2012-02-25 05:12:43 +01:00
}
2012-05-23 19:56:42 +02:00
/**
2012-05-23 23:21:29 +02:00
* Get the theme being customized .
2012-05-23 19:56:42 +02:00
*
* @ since 3.4 . 0
*
* @ return WP_Theme
*/
2012-05-23 23:21:29 +02: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 ;
}
2014-08-14 06:43:16 +02:00
/**
* Get the registered containers .
*
* @ since 4.0 . 0
*
* @ return array
*/
public function containers () {
return $this -> containers ;
}
2012-05-23 23:21:29 +02:00
/**
* Get the registered sections .
*
* @ since 3.4 . 0
*
* @ return array
*/
public function sections () {
return $this -> sections ;
2012-05-23 19:56:42 +02:00
}
2014-06-26 22:17:15 +02:00
/**
* Get the registered panels .
*
* @ since 4.0 . 0
2014-07-14 02:36:15 +02:00
* @ access public
2014-06-26 22:17:15 +02:00
*
2014-07-14 02:36:15 +02:00
* @ return array Panels .
2014-06-26 22:17:15 +02:00
*/
public function panels () {
return $this -> panels ;
}
2012-05-16 07:55:54 +02:00
/**
* Checks if the current theme is active .
*
* @ since 3.4 . 0
2012-05-23 19:56:42 +02:00
*
* @ return bool
2012-05-16 07:55:54 +02:00
*/
2012-05-23 19:56:42 +02:00
public function is_theme_active () {
2012-05-16 07:55:54 +02:00
return $this -> get_stylesheet () == $this -> original_stylesheet ;
}
2012-02-25 05:12:43 +01:00
/**
2012-03-01 01:14:51 +01:00
* Register styles / scripts and initialize the preview of each setting
2012-02-25 05:12:43 +01:00
*
* @ since 3.4 . 0
*/
2012-03-01 01:14:51 +01:00
public function wp_loaded () {
2014-03-06 15:11:15 +01:00
/**
* Fires once WordPress has loaded , allowing scripts and styles to be initialized .
*
* @ since 3.4 . 0
*
* @ param WP_Customize_Manager $this WP_Customize_Manager instance .
*/
2012-04-30 19:20:32 +02:00
do_action ( 'customize_register' , $this );
2012-02-25 05:12:43 +01:00
2012-03-28 17:04:11 +02:00
if ( $this -> is_preview () && ! is_admin () )
$this -> customize_preview_init ();
2012-03-21 23:55:43 +01:00
}
2012-05-24 03:48:32 +02: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 23:45:33 +02:00
*
* @ param $status
* @ return int
2012-05-24 03:48:32 +02:00
*/
public function wp_redirect_status ( $status ) {
if ( $this -> is_preview () && ! is_admin () )
return 200 ;
return $status ;
}
2012-04-30 17:46:17 +02:00
/**
2015-02-03 11:15:21 +01:00
* Parse the incoming $_POST [ 'customized' ] JSON data and store the unsanitized
* settings for subsequent post_value () lookups .
2012-04-30 17:46:17 +02:00
*
2015-02-03 11:15:21 +01:00
* @ since 4.1 . 1
2012-07-26 23:45:33 +02:00
*
2015-02-03 11:15:21 +01:00
* @ return array
2012-04-30 17:46:17 +02:00
*/
2015-02-03 11:15:21 +01:00
public function unsanitized_post_values () {
2012-04-30 17:46:17 +02:00
if ( ! isset ( $this -> _post_values ) ) {
2015-02-03 11:15:21 +01:00
if ( isset ( $_POST [ 'customized' ] ) ) {
2013-03-03 17:30:38 +01:00
$this -> _post_values = json_decode ( wp_unslash ( $_POST [ 'customized' ] ), true );
2015-02-03 11:15:21 +01:00
}
2015-02-09 00:11:25 +01:00
if ( empty ( $this -> _post_values ) ) { // if not isset or if JSON error
$this -> _post_values = array ();
2015-02-03 11:15:21 +01:00
}
2012-04-30 17:46:17 +02:00
}
2015-02-03 11:15:21 +01:00
if ( empty ( $this -> _post_values ) ) {
return array ();
} else {
return $this -> _post_values ;
}
}
2012-04-30 17:46:17 +02:00
2015-02-03 11:15:21 +01:00
/**
* Return the sanitized value for a given setting from the request ' s POST data .
*
* @ since 3.4 . 0
2015-02-06 22:14:24 +01:00
* @ since 4.1 . 1 Introduced 'default' parameter .
2015-02-03 11:15:21 +01:00
*
* @ param WP_Customize_Setting $setting A WP_Customize_Setting derived object
* @ param mixed $default value returned $setting has no post value ( added in 4.2 . 0 ) .
* @ return string | mixed $post_value Sanitized value or the $default provided
*/
public function post_value ( $setting , $default = null ) {
$post_values = $this -> unsanitized_post_values ();
if ( array_key_exists ( $setting -> id , $post_values ) ) {
return $setting -> sanitize ( $post_values [ $setting -> id ] );
} else {
return $default ;
}
2012-04-30 17:46:17 +02:00
}
2015-02-09 00:11:25 +01:00
/**
* Override a setting 's (unsanitized) value as found in any incoming $_POST[' customized ' ]
*
* @ since 4.2 . 0
*
* @ param string $setting_id The ID for the WP_Customize_Setting instance .
* @ param mixed $value
*/
public function set_post_value ( $setting_id , $value ) {
$this -> unsanitized_post_values ();
$this -> _post_values [ $setting_id ] = $value ;
}
2012-03-21 23:55:43 +01:00
/**
2014-12-02 01:31:22 +01:00
* Print JavaScript settings .
2012-03-21 23:55:43 +01:00
*
* @ since 3.4 . 0
*/
public function customize_preview_init () {
2012-06-26 20:48:18 +02:00
$this -> nonce_tick = check_ajax_referer ( 'preview-customize_' . $this -> get_stylesheet (), 'nonce' );
2012-03-21 23:55:43 +01:00
$this -> prepare_controls ();
2012-02-25 05:12:43 +01:00
wp_enqueue_script ( 'customize-preview' );
2014-07-03 18:10:15 +02:00
add_action ( 'wp' , array ( $this , 'customize_preview_override_404_status' ) );
2012-05-24 04:07:16 +02:00
add_action ( 'wp_head' , array ( $this , 'customize_preview_base' ) );
2012-06-05 14:26:57 +02:00
add_action ( 'wp_head' , array ( $this , 'customize_preview_html5' ) );
2012-02-25 05:12:43 +01:00
add_action ( 'wp_footer' , array ( $this , 'customize_preview_settings' ), 20 );
2012-05-26 06:08:44 +02:00
add_action ( 'shutdown' , array ( $this , 'customize_preview_signature' ), 1000 );
2012-05-26 06:34:45 +02:00
add_filter ( 'wp_die_handler' , array ( $this , 'remove_preview_signature' ) );
2012-02-25 05:12:43 +01:00
foreach ( $this -> settings as $setting ) {
$setting -> preview ();
}
2012-03-21 23:55:43 +01:00
2014-03-06 15:11:15 +01:00
/**
* Fires once the Customizer preview has initialized and JavaScript
* settings have been printed .
*
* @ since 3.4 . 0
*
* @ param WP_Customize_Manager $this WP_Customize_Manager instance .
*/
2012-04-30 19:20:32 +02:00
do_action ( 'customize_preview_init' , $this );
2012-02-25 05:12:43 +01:00
}
2014-07-03 18:10:15 +02:00
/**
* Prevent sending a 404 status when returning the response for the customize
2014-08-09 21:30:17 +02:00
* preview , since it causes the jQuery AJAX to fail . Send 200 instead .
2014-07-03 18:10:15 +02:00
*
* @ since 4.0 . 0
2014-07-14 02:36:15 +02:00
* @ access public
2014-07-03 18:10:15 +02:00
*/
public function customize_preview_override_404_status () {
if ( is_404 () ) {
status_header ( 200 );
}
}
2012-05-24 04:07:16 +02: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 23:55:43 +01:00
2012-06-05 14:26:57 +02: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-25 05:12:43 +01:00
/**
2014-12-02 01:31:22 +01:00
* Print JavaScript settings for preview frame .
2012-02-25 05:12:43 +01:00
*
* @ since 3.4 . 0
*/
public function customize_preview_settings () {
$settings = array (
2012-06-04 17:51:46 +02:00
'values' => array (),
2014-07-10 01:58:16 +02:00
'channel' => wp_unslash ( $_POST [ 'customize_messenger_channel' ] ),
Improve/introduce Customizer JavaScript models for Controls, Sections, and Panels.
* Introduce models for panels and sections.
* Introduce API to expand and focus a control, section or panel.
* Allow deep-linking to panels, sections, and controls inside of the Customizer.
* Clean up `accordion.js`, removing all Customizer-specific logic.
* Add initial unit tests for `wp.customize.Class` in `customize-base.js`.
https://make.wordpress.org/core/2014/10/27/toward-a-complete-javascript-api-for-the-customizer/ provides an overview of how to use the JavaScript API.
props westonruter, celloexpressions, ryankienstra.
see #28032, #28579, #28580, #28650, #28709, #29758.
fixes #29529.
Built from https://develop.svn.wordpress.org/trunk@30102
git-svn-id: http://core.svn.wordpress.org/trunk@30102 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2014-10-29 23:51:22 +01:00
'activePanels' => array (),
'activeSections' => array (),
2014-07-10 01:58:16 +02:00
'activeControls' => array (),
2012-02-25 05:12:43 +01:00
);
2012-03-06 03:49:02 +01:00
2012-06-26 20:48:18 +02:00
if ( 2 == $this -> nonce_tick ) {
2012-07-26 23:45:33 +02: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 20:48:18 +02:00
2012-03-06 03:49:02 +01:00
foreach ( $this -> settings as $id => $setting ) {
2012-05-16 22:59:02 +02:00
$settings [ 'values' ][ $id ] = $setting -> js_value ();
2012-03-06 03:49:02 +01:00
}
Improve/introduce Customizer JavaScript models for Controls, Sections, and Panels.
* Introduce models for panels and sections.
* Introduce API to expand and focus a control, section or panel.
* Allow deep-linking to panels, sections, and controls inside of the Customizer.
* Clean up `accordion.js`, removing all Customizer-specific logic.
* Add initial unit tests for `wp.customize.Class` in `customize-base.js`.
https://make.wordpress.org/core/2014/10/27/toward-a-complete-javascript-api-for-the-customizer/ provides an overview of how to use the JavaScript API.
props westonruter, celloexpressions, ryankienstra.
see #28032, #28579, #28580, #28650, #28709, #29758.
fixes #29529.
Built from https://develop.svn.wordpress.org/trunk@30102
git-svn-id: http://core.svn.wordpress.org/trunk@30102 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2014-10-29 23:51:22 +01:00
foreach ( $this -> panels as $id => $panel ) {
$settings [ 'activePanels' ][ $id ] = $panel -> active ();
2014-11-13 13:19:23 +01:00
foreach ( $panel -> sections as $id => $section ) {
$settings [ 'activeSections' ][ $id ] = $section -> active ();
}
Improve/introduce Customizer JavaScript models for Controls, Sections, and Panels.
* Introduce models for panels and sections.
* Introduce API to expand and focus a control, section or panel.
* Allow deep-linking to panels, sections, and controls inside of the Customizer.
* Clean up `accordion.js`, removing all Customizer-specific logic.
* Add initial unit tests for `wp.customize.Class` in `customize-base.js`.
https://make.wordpress.org/core/2014/10/27/toward-a-complete-javascript-api-for-the-customizer/ provides an overview of how to use the JavaScript API.
props westonruter, celloexpressions, ryankienstra.
see #28032, #28579, #28580, #28650, #28709, #29758.
fixes #29529.
Built from https://develop.svn.wordpress.org/trunk@30102
git-svn-id: http://core.svn.wordpress.org/trunk@30102 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2014-10-29 23:51:22 +01:00
}
foreach ( $this -> sections as $id => $section ) {
$settings [ 'activeSections' ][ $id ] = $section -> active ();
}
2014-07-10 01:58:16 +02:00
foreach ( $this -> controls as $id => $control ) {
$settings [ 'activeControls' ][ $id ] = $control -> active ();
}
2012-03-06 03:49:02 +01:00
2012-02-25 05:12:43 +01:00
?>
< script type = " text/javascript " >
2014-10-28 19:35:19 +01:00
var _wpCustomizeSettings = < ? php echo wp_json_encode ( $settings ); ?> ;
2012-02-25 05:12:43 +01:00
</ script >
< ? php
}
2012-05-26 06:08:44 +02:00
/**
2014-10-15 19:21:19 +02:00
* Prints a signature so we can ensure the Customizer was properly executed .
2012-05-26 06:08:44 +02:00
*
* @ since 3.4 . 0
*/
public function customize_preview_signature () {
echo 'WP_CUSTOMIZER_SIGNATURE' ;
}
2012-05-26 06:34:45 +02:00
/**
2014-10-15 19:21:19 +02:00
* Removes the signature in case we experience a case where the Customizer was not properly executed .
2012-05-26 06:34:45 +02:00
*
* @ since 3.4 . 0
*/
public function remove_preview_signature ( $return = null ) {
remove_action ( 'shutdown' , array ( $this , 'customize_preview_signature' ), 1000 );
return $return ;
}
2012-02-25 05:12:43 +01: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 20:39:16 +02:00
return $this -> theme () -> get_template ();
2012-02-25 05:12:43 +01:00
}
/**
* Retrieve the stylesheet name of the previewed theme .
*
* @ since 3.4 . 0
*
* @ return string Stylesheet name .
*/
public function get_stylesheet () {
2012-06-12 20:39:16 +02:00
return $this -> theme () -> get_stylesheet ();
2012-02-25 05:12:43 +01: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 23:43:47 +02:00
return get_raw_theme_root ( $this -> get_template (), true );
2012-02-25 05:12:43 +01: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 23:43:47 +02:00
return get_raw_theme_root ( $this -> get_stylesheet (), true );
2012-02-25 05:12:43 +01:00
}
/**
* Filter the current theme and return the name of the previewed theme .
*
* @ since 3.4 . 0
*
2012-07-26 23:45:33 +02:00
* @ param $current_theme { @ internal Parameter is not used }
2012-02-25 05:12:43 +01:00
* @ return string Theme name .
*/
public function current_theme ( $current_theme ) {
2012-06-12 20:39:16 +02:00
return $this -> theme () -> display ( 'Name' );
2012-02-25 05:12:43 +01:00
}
/**
2014-03-04 21:21:14 +01:00
* Switch the theme and trigger the save () method on each setting .
2012-02-25 05:12:43 +01:00
*
* @ since 3.4 . 0
*/
public function save () {
2015-01-06 22:47:23 +01:00
if ( ! $this -> is_preview () ) {
wp_send_json_error ( 'not_preview' );
}
2012-02-25 05:12:43 +01:00
2015-01-06 22:47:23 +01:00
$action = 'save-customize_' . $this -> get_stylesheet ();
if ( ! check_ajax_referer ( $action , 'nonce' , false ) ) {
wp_send_json_error ( 'invalid_nonce' );
}
2012-02-25 05:12:43 +01:00
// Do we have to switch themes?
2012-06-12 20:39:16 +02:00
if ( ! $this -> is_theme_active () ) {
2012-04-25 17:44:06 +02:00
// Temporarily stop previewing the theme to allow switch_themes()
// to operate properly.
$this -> stop_previewing_theme ();
2012-06-26 07:21:04 +02:00
switch_theme ( $this -> get_stylesheet () );
2014-04-15 00:46:16 +02:00
update_option ( 'theme_switched_via_customizer' , true );
2012-04-25 17:44:06 +02:00
$this -> start_previewing_theme ();
2012-02-25 05:12:43 +01:00
}
2014-03-06 15:11:15 +01:00
/**
* Fires once the theme has switched in the Customizer , but before settings
* have been saved .
*
* @ since 3.4 . 0
*
* @ param WP_Customize_Manager $this WP_Customize_Manager instance .
*/
2012-04-30 19:20:32 +02:00
do_action ( 'customize_save' , $this );
2012-02-25 05:12:43 +01:00
foreach ( $this -> settings as $setting ) {
$setting -> save ();
}
2014-03-06 15:11:15 +01:00
/**
* Fires after Customize settings have been saved .
*
* @ since 3.6 . 0
*
* @ param WP_Customize_Manager $this WP_Customize_Manager instance .
*/
2013-05-24 12:33:30 +02:00
do_action ( 'customize_save_after' , $this );
2015-01-06 22:47:23 +01:00
/**
* Filter response data for a successful customize_save Ajax request .
2015-01-08 06:03:23 +01:00
*
2015-01-06 22:47:23 +01:00
* This filter does not apply if there was a nonce or authentication failure .
*
* @ since 4.2 . 0
*
2015-01-07 02:48:24 +01:00
* @ param array $data Additional information passed back to the 'saved'
* event on `wp.customize` .
2015-01-06 22:47:23 +01:00
* @ param WP_Customize_Manager $this WP_Customize_Manager instance .
*/
$response = apply_filters ( 'customize_save_response' , array (), $this );
wp_send_json_success ( $response );
2012-02-25 05:12:43 +01:00
}
/**
* Add a customize setting .
*
* @ since 3.4 . 0
*
2014-03-04 21:21:14 +01:00
* @ param WP_Customize_Setting | string $id Customize Setting object , or ID .
* @ param array $args Setting arguments ; passed to WP_Customize_Setting
* constructor .
2012-02-25 05:12:43 +01:00
*/
public function add_setting ( $id , $args = array () ) {
2015-01-16 02:06:24 +01:00
if ( $id instanceof WP_Customize_Setting ) {
2012-03-28 06:14:09 +02:00
$setting = $id ;
2015-01-16 02:06:24 +01:00
} else {
2012-03-28 06:14:09 +02:00
$setting = new WP_Customize_Setting ( $this , $id , $args );
2015-01-16 02:06:24 +01:00
}
2012-02-25 05:12:43 +01:00
$this -> settings [ $setting -> id ] = $setting ;
}
2015-02-09 00:11:25 +01:00
/**
* Register any dynamically - created settings , such as those from $_POST [ 'customized' ] that have no corresponding setting created .
*
* This is a mechanism to " wake up " settings that have been dynamically created
* on the frontend and have been sent to WordPress in $_POST [ 'customized' ] . When WP
* loads , the dynamically - created settings then will get created and previewed
* even though they are not directly created statically with code .
*
* @ since 4.2 . 0
*
* @ param string [] $setting_ids The setting IDs to add .
* @ return WP_Customize_Setting [] The settings added .
*/
public function add_dynamic_settings ( $setting_ids ) {
$new_settings = array ();
foreach ( $setting_ids as $setting_id ) {
// Skip settings already created
if ( $this -> get_setting ( $setting_id ) ) {
continue ;
}
$setting_args = false ;
$setting_class = 'WP_Customize_Setting' ;
/**
* Filter a dynamic setting ' s constructor args .
*
* For a dynamic setting to be registered , this filter must be employed
* to override the default false value with an array of args to pass to
* the WP_Customize_Setting constructor .
*
* @ since 4.2 . 0
*
* @ param false | array $setting_args The arguments to the WP_Customize_Setting constructor .
* @ param string $setting_id ID for dynamic setting , usually coming from $_POST [ 'customized' ] .
*/
$setting_args = apply_filters ( 'customize_dynamic_setting_args' , $setting_args , $setting_id );
if ( false === $setting_args ) {
continue ;
}
/**
* Allow non - statically created settings to be constructed with custom WP_Customize_Setting subclass .
*
* @ since 4.2 . 0
*
* @ param string $setting_class WP_Customize_Setting or a subclass .
* @ param string $setting_id ID for dynamic setting , usually coming from $_POST [ 'customized' ] .
* @ param string $setting_args WP_Customize_Setting or a subclass .
*/
$setting_class = apply_filters ( 'customize_dynamic_setting_class' , $setting_class , $setting_id , $setting_args );
$setting = new $setting_class ( $this , $setting_id , $setting_args );
$this -> add_setting ( $setting );
$new_settings [] = $setting ;
}
return $new_settings ;
}
2012-02-25 05:12:43 +01:00
/**
* Retrieve a customize setting .
*
* @ since 3.4 . 0
*
2014-03-04 21:21:14 +01:00
* @ param string $id Customize Setting ID .
* @ return WP_Customize_Setting
2012-02-25 05:12:43 +01:00
*/
public function get_setting ( $id ) {
2015-02-09 00:11:25 +01:00
if ( isset ( $this -> settings [ $id ] ) ) {
2012-02-25 05:12:43 +01:00
return $this -> settings [ $id ];
2015-02-09 00:11:25 +01:00
}
2012-02-25 05:12:43 +01:00
}
/**
* Remove a customize setting .
*
* @ since 3.4 . 0
*
2014-03-04 21:21:14 +01:00
* @ param string $id Customize Setting ID .
2012-02-25 05:12:43 +01:00
*/
public function remove_setting ( $id ) {
unset ( $this -> settings [ $id ] );
}
2014-06-26 22:17:15 +02:00
/**
* Add a customize panel .
*
* @ since 4.0 . 0
2014-07-14 02:36:15 +02:00
* @ access public
2014-06-26 22:17:15 +02:00
*
* @ param WP_Customize_Panel | string $id Customize Panel object , or Panel ID .
2014-07-14 02:36:15 +02:00
* @ param array $args Optional . Panel arguments . Default empty array .
2014-06-26 22:17:15 +02:00
*/
public function add_panel ( $id , $args = array () ) {
2015-01-16 02:06:24 +01:00
if ( $id instanceof WP_Customize_Panel ) {
2014-06-26 22:17:15 +02:00
$panel = $id ;
2015-01-16 02:06:24 +01:00
} else {
2014-06-26 22:17:15 +02:00
$panel = new WP_Customize_Panel ( $this , $id , $args );
}
$this -> panels [ $panel -> id ] = $panel ;
}
/**
* Retrieve a customize panel .
*
* @ since 4.0 . 0
2014-07-14 02:36:15 +02:00
* @ access public
2014-06-26 22:17:15 +02:00
*
2014-07-14 02:36:15 +02:00
* @ param string $id Panel ID to get .
* @ return WP_Customize_Panel Requested panel instance .
2014-06-26 22:17:15 +02:00
*/
public function get_panel ( $id ) {
if ( isset ( $this -> panels [ $id ] ) ) {
return $this -> panels [ $id ];
}
}
/**
* Remove a customize panel .
*
* @ since 4.0 . 0
2014-07-14 02:36:15 +02:00
* @ access public
2014-06-26 22:17:15 +02:00
*
2014-07-14 02:36:15 +02:00
* @ param string $id Panel ID to remove .
2014-06-26 22:17:15 +02:00
*/
public function remove_panel ( $id ) {
unset ( $this -> panels [ $id ] );
}
2012-02-25 05:12:43 +01:00
/**
* Add a customize section .
*
* @ since 3.4 . 0
*
2014-03-04 21:21:14 +01:00
* @ param WP_Customize_Section | string $id Customize Section object , or Section ID .
* @ param array $args Section arguments .
2012-02-25 05:12:43 +01:00
*/
public function add_section ( $id , $args = array () ) {
2015-01-16 02:06:24 +01:00
if ( $id instanceof WP_Customize_Section ) {
2012-03-28 06:14:09 +02:00
$section = $id ;
2015-01-16 02:06:24 +01:00
} else {
2012-03-28 06:14:09 +02:00
$section = new WP_Customize_Section ( $this , $id , $args );
2015-01-16 02:06:24 +01:00
}
2012-02-25 05:12:43 +01:00
$this -> sections [ $section -> id ] = $section ;
}
/**
* Retrieve a customize section .
*
* @ since 3.4 . 0
*
2014-03-04 21:21:14 +01:00
* @ param string $id Section ID .
* @ return WP_Customize_Section
2012-02-25 05:12:43 +01:00
*/
public function get_section ( $id ) {
if ( isset ( $this -> sections [ $id ] ) )
return $this -> sections [ $id ];
}
/**
* Remove a customize section .
*
* @ since 3.4 . 0
*
2014-03-04 21:21:14 +01:00
* @ param string $id Section ID .
2012-02-25 05:12:43 +01:00
*/
public function remove_section ( $id ) {
unset ( $this -> sections [ $id ] );
}
2012-03-28 06:14:09 +02:00
/**
* Add a customize control .
*
* @ since 3.4 . 0
*
2014-03-04 21:21:14 +01:00
* @ param WP_Customize_Control | string $id Customize Control object , or ID .
* @ param array $args Control arguments ; passed to WP_Customize_Control
* constructor .
2012-03-28 06:14:09 +02:00
*/
public function add_control ( $id , $args = array () ) {
2015-01-16 02:06:24 +01:00
if ( $id instanceof WP_Customize_Control ) {
2012-03-28 06:14:09 +02:00
$control = $id ;
2015-01-16 02:06:24 +01:00
} else {
2012-03-28 06:14:09 +02:00
$control = new WP_Customize_Control ( $this , $id , $args );
2015-01-16 02:06:24 +01:00
}
2012-03-28 06:14:09 +02:00
$this -> controls [ $control -> id ] = $control ;
}
/**
* Retrieve a customize control .
*
* @ since 3.4 . 0
*
2014-03-04 21:21:14 +01:00
* @ param string $id ID of the control .
* @ return WP_Customize_Control $control The control object .
2012-03-28 06:14:09 +02:00
*/
public function get_control ( $id ) {
if ( isset ( $this -> controls [ $id ] ) )
return $this -> controls [ $id ];
}
/**
2014-03-04 21:21:14 +01:00
* Remove a customize control .
2012-03-28 06:14:09 +02:00
*
* @ since 3.4 . 0
*
2014-03-04 21:21:14 +01:00
* @ param string $id ID of the control .
2012-03-28 06:14:09 +02:00
*/
public function remove_control ( $id ) {
unset ( $this -> controls [ $id ] );
}
2012-02-25 05:12:43 +01:00
/**
2014-10-24 18:32:18 +02:00
* Register a customize control type .
*
2014-11-28 11:52:22 +01:00
* Registered types are eligible to be rendered via JS and created dynamically .
2014-10-24 18:32:18 +02:00
*
* @ since 4.1 . 0
2014-11-28 11:52:22 +01:00
* @ access public
2014-10-24 18:32:18 +02:00
*
2014-11-28 11:52:22 +01:00
* @ param string $control Name of a custom control which is a subclass of
* { @ see WP_Customize_Control } .
2014-10-24 18:32:18 +02:00
*/
public function register_control_type ( $control ) {
$this -> registered_control_types [] = $control ;
}
/**
* Render JS templates for all registered control types .
*
* @ since 4.1 . 0
2014-11-28 11:52:22 +01:00
* @ access public
2014-10-24 18:32:18 +02:00
*/
public function render_control_templates () {
2014-11-03 22:35:23 +01:00
foreach ( $this -> registered_control_types as $control_type ) {
2014-10-24 18:32:18 +02:00
$control = new $control_type ( $this , 'temp' , array () );
$control -> print_template ();
}
}
2014-11-03 22:35:23 +01:00
/**
* Helper function to compare two objects by priority , ensuring sort stability via instance_number .
2012-02-25 05:12:43 +01:00
*
* @ since 3.4 . 0
*
2015-01-16 19:37:24 +01:00
* @ param WP_Customize_Panel | WP_Customize_Section | WP_Customize_Control $a Object A .
* @ param WP_Customize_Panel | WP_Customize_Section | WP_Customize_Control $b Object B .
2012-07-26 23:45:33 +02:00
* @ return int
2012-02-25 05:12:43 +01:00
*/
2015-01-08 07:10:46 +01:00
protected function _cmp_priority ( $a , $b ) {
2014-11-03 22:35:23 +01:00
if ( $a -> priority === $b -> priority ) {
return $a -> instance_number - $a -> instance_number ;
} else {
return $a -> priority - $b -> priority ;
}
2012-02-25 05:12:43 +01:00
}
/**
2014-06-26 22:17:15 +02:00
* Prepare panels , sections , and controls .
2012-02-25 05:12:43 +01:00
*
2014-03-04 21:21:14 +01:00
* For each , check if required related components exist ,
* whether the user has the necessary capabilities ,
* and sort by priority .
*
2012-02-25 05:12:43 +01:00
* @ since 3.4 . 0
*/
public function prepare_controls () {
2012-03-28 06:14:09 +02:00
$controls = array ();
2014-11-03 22:35:23 +01:00
uasort ( $this -> controls , array ( $this , '_cmp_priority' ) );
2012-03-21 23:55:43 +01:00
2012-03-28 06:14:09 +02:00
foreach ( $this -> controls as $id => $control ) {
2014-06-26 22:17:15 +02:00
if ( ! isset ( $this -> sections [ $control -> section ] ) || ! $control -> check_capabilities () ) {
2012-02-25 05:12:43 +01:00
continue ;
2014-06-26 22:17:15 +02:00
}
2012-02-25 05:12:43 +01:00
2012-03-28 06:14:09 +02:00
$this -> sections [ $control -> section ] -> controls [] = $control ;
$controls [ $id ] = $control ;
2012-02-25 05:12:43 +01:00
}
2012-03-28 06:14:09 +02:00
$this -> controls = $controls ;
2012-03-21 23:55:43 +01:00
2014-03-04 21:21:14 +01:00
// Prepare sections.
2012-03-21 23:55:43 +01:00
uasort ( $this -> sections , array ( $this , '_cmp_priority' ) );
$sections = array ();
2012-02-25 05:12:43 +01:00
foreach ( $this -> sections as $section ) {
2014-06-26 22:17:15 +02:00
if ( ! $section -> check_capabilities () || ! $section -> controls ) {
2012-03-21 23:55:43 +01:00
continue ;
2014-06-26 22:17:15 +02:00
}
2012-03-21 23:55:43 +01:00
2012-03-28 06:14:09 +02:00
usort ( $section -> controls , array ( $this , '_cmp_priority' ) );
2014-06-26 22:17:15 +02:00
if ( ! $section -> panel ) {
// Top-level section.
Improve/introduce Customizer JavaScript models for Controls, Sections, and Panels.
* Introduce models for panels and sections.
* Introduce API to expand and focus a control, section or panel.
* Allow deep-linking to panels, sections, and controls inside of the Customizer.
* Clean up `accordion.js`, removing all Customizer-specific logic.
* Add initial unit tests for `wp.customize.Class` in `customize-base.js`.
https://make.wordpress.org/core/2014/10/27/toward-a-complete-javascript-api-for-the-customizer/ provides an overview of how to use the JavaScript API.
props westonruter, celloexpressions, ryankienstra.
see #28032, #28579, #28580, #28650, #28709, #29758.
fixes #29529.
Built from https://develop.svn.wordpress.org/trunk@30102
git-svn-id: http://core.svn.wordpress.org/trunk@30102 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2014-10-29 23:51:22 +01:00
$sections [ $section -> id ] = $section ;
2014-06-26 22:17:15 +02:00
} else {
// This section belongs to a panel.
if ( isset ( $this -> panels [ $section -> panel ] ) ) {
Improve/introduce Customizer JavaScript models for Controls, Sections, and Panels.
* Introduce models for panels and sections.
* Introduce API to expand and focus a control, section or panel.
* Allow deep-linking to panels, sections, and controls inside of the Customizer.
* Clean up `accordion.js`, removing all Customizer-specific logic.
* Add initial unit tests for `wp.customize.Class` in `customize-base.js`.
https://make.wordpress.org/core/2014/10/27/toward-a-complete-javascript-api-for-the-customizer/ provides an overview of how to use the JavaScript API.
props westonruter, celloexpressions, ryankienstra.
see #28032, #28579, #28580, #28650, #28709, #29758.
fixes #29529.
Built from https://develop.svn.wordpress.org/trunk@30102
git-svn-id: http://core.svn.wordpress.org/trunk@30102 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2014-10-29 23:51:22 +01:00
$this -> panels [ $section -> panel ] -> sections [ $section -> id ] = $section ;
2014-06-26 22:17:15 +02:00
}
}
2012-03-21 23:55:43 +01:00
}
$this -> sections = $sections ;
2014-06-26 22:17:15 +02:00
// Prepare panels.
uasort ( $this -> panels , array ( $this , '_cmp_priority' ) );
$panels = array ();
foreach ( $this -> panels as $panel ) {
if ( ! $panel -> check_capabilities () || ! $panel -> sections ) {
continue ;
}
Improve/introduce Customizer JavaScript models for Controls, Sections, and Panels.
* Introduce models for panels and sections.
* Introduce API to expand and focus a control, section or panel.
* Allow deep-linking to panels, sections, and controls inside of the Customizer.
* Clean up `accordion.js`, removing all Customizer-specific logic.
* Add initial unit tests for `wp.customize.Class` in `customize-base.js`.
https://make.wordpress.org/core/2014/10/27/toward-a-complete-javascript-api-for-the-customizer/ provides an overview of how to use the JavaScript API.
props westonruter, celloexpressions, ryankienstra.
see #28032, #28579, #28580, #28650, #28709, #29758.
fixes #29529.
Built from https://develop.svn.wordpress.org/trunk@30102
git-svn-id: http://core.svn.wordpress.org/trunk@30102 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2014-10-29 23:51:22 +01:00
uasort ( $panel -> sections , array ( $this , '_cmp_priority' ) );
$panels [ $panel -> id ] = $panel ;
2014-06-26 22:17:15 +02:00
}
$this -> panels = $panels ;
2014-08-14 06:43:16 +02:00
// Sort panels and top-level sections together.
$this -> containers = array_merge ( $this -> panels , $this -> sections );
uasort ( $this -> containers , array ( $this , '_cmp_priority' ) );
2012-03-21 23:55:43 +01:00
}
/**
* Enqueue scripts for customize controls .
*
* @ since 3.4 . 0
*/
public function enqueue_control_scripts () {
2012-03-28 06:14:09 +02:00
foreach ( $this -> controls as $control ) {
$control -> enqueue ();
2012-02-25 05:12:43 +01:00
}
}
/**
* Register some default controls .
*
* @ since 3.4 . 0
*/
public function register_controls () {
2014-10-24 18:32:18 +02:00
/* Control Types (custom control classes) */
$this -> register_control_type ( 'WP_Customize_Color_Control' );
2014-11-12 00:52:22 +01:00
$this -> register_control_type ( 'WP_Customize_Upload_Control' );
$this -> register_control_type ( 'WP_Customize_Image_Control' );
2014-12-16 00:28:23 +01:00
$this -> register_control_type ( 'WP_Customize_Background_Image_Control' );
2014-10-24 18:32:18 +02:00
2012-05-25 21:52:54 +02:00
/* Site Title & Tagline */
2012-02-25 05:12:43 +01:00
2012-05-25 21:52:54 +02: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-25 05:12:43 +01:00
) );
$this -> add_setting ( 'header_textcolor' , array (
2012-03-28 06:14:09 +02:00
'theme_supports' => array ( 'custom-header' , 'header-text' ),
'default' => get_theme_support ( 'custom-header' , 'default-text-color' ),
2012-05-26 20:44:31 +02:00
'sanitize_callback' => array ( $this , '_sanitize_header_textcolor' ),
'sanitize_js_callback' => 'maybe_hash_hex_color' ,
2012-03-28 06:14:09 +02:00
) );
2012-05-25 21:52:54 +02:00
// Input type: checkbox
// With custom value
2012-03-28 06:14:09 +02:00
$this -> add_control ( 'display_header_text' , array (
'settings' => 'header_textcolor' ,
'label' => __ ( 'Display Header Text' ),
2012-05-25 21:52:54 +02:00
'section' => 'title_tagline' ,
2012-03-28 06:14:09 +02:00
'type' => 'checkbox' ,
2012-02-25 05:12:43 +01:00
) );
2012-04-25 23:03:29 +02:00
$this -> add_control ( new WP_Customize_Color_Control ( $this , 'header_textcolor' , array (
2012-05-26 17:24:42 +02:00
'label' => __ ( 'Header Text Color' ),
2012-05-25 21:52:54 +02:00
'section' => 'colors' ,
2012-04-25 23:03:29 +02:00
) ) );
2012-02-25 05:12:43 +01:00
// Input type: Color
// With sanitize_callback
$this -> add_setting ( 'background_color' , array (
2012-05-26 20:44:31 +02: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 06:14:09 +02:00
) );
2012-04-25 23:03:29 +02:00
$this -> add_control ( new WP_Customize_Color_Control ( $this , 'background_color' , array (
2012-03-28 06:14:09 +02:00
'label' => __ ( 'Background Color' ),
2012-05-25 21:52:54 +02:00
'section' => 'colors' ,
2012-04-25 23:03:29 +02:00
) ) );
2012-03-15 05:14:05 +01:00
2012-05-25 21:52:54 +02:00
/* Custom Header */
$this -> add_section ( 'header_image' , array (
'title' => __ ( 'Header Image' ),
'theme_supports' => 'custom-header' ,
'priority' => 60 ,
) );
2012-06-10 02:32:19 +02:00
$this -> add_setting ( new WP_Customize_Filter_Setting ( $this , 'header_image' , array (
2012-05-25 21:52:54 +02:00
'default' => get_theme_support ( 'custom-header' , 'default-image' ),
'theme_supports' => 'custom-header' ,
2012-06-10 02:32:19 +02: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 21:52:54 +02: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 05:14:05 +01:00
$this -> add_setting ( 'background_image' , array (
2012-03-24 02:02:29 +01:00
'default' => get_theme_support ( 'custom-background' , 'default-image' ),
2012-03-28 06:14:09 +02:00
'theme_supports' => 'custom-background' ,
) );
2012-06-11 22:49:45 +02:00
$this -> add_setting ( new WP_Customize_Background_Image_Setting ( $this , 'background_image_thumb' , array (
'theme_supports' => 'custom-background' ,
) ) );
2012-05-25 22:26:25 +02:00
$this -> add_control ( new WP_Customize_Background_Image_Control ( $this ) );
2012-03-22 09:07:44 +01:00
$this -> add_setting ( 'background_repeat' , array (
2014-07-11 22:27:14 +02:00
'default' => get_theme_support ( 'custom-background' , 'default-repeat' ),
2012-03-28 06:14:09 +02:00
'theme_supports' => 'custom-background' ,
) );
$this -> add_control ( 'background_repeat' , array (
'label' => __ ( 'Background Repeat' ),
2012-05-25 21:52:54 +02:00
'section' => 'background_image' ,
2012-03-28 06:14:09 +02:00
'type' => 'radio' ,
2012-03-22 09:07:44 +01:00
'choices' => array (
'no-repeat' => __ ( 'No Repeat' ),
'repeat' => __ ( 'Tile' ),
'repeat-x' => __ ( 'Tile Horizontally' ),
'repeat-y' => __ ( 'Tile Vertically' ),
),
) );
$this -> add_setting ( 'background_position_x' , array (
2014-07-11 22:27:14 +02:00
'default' => get_theme_support ( 'custom-background' , 'default-position-x' ),
2012-03-28 06:14:09 +02:00
'theme_supports' => 'custom-background' ,
) );
$this -> add_control ( 'background_position_x' , array (
'label' => __ ( 'Background Position' ),
2012-05-25 21:52:54 +02:00
'section' => 'background_image' ,
2012-03-28 06:14:09 +02:00
'type' => 'radio' ,
2012-03-22 09:07:44 +01:00
'choices' => array (
'left' => __ ( 'Left' ),
'center' => __ ( 'Center' ),
'right' => __ ( 'Right' ),
),
) );
$this -> add_setting ( 'background_attachment' , array (
2014-07-11 22:27:14 +02:00
'default' => get_theme_support ( 'custom-background' , 'default-attachment' ),
2012-03-28 06:14:09 +02:00
'theme_supports' => 'custom-background' ,
) );
$this -> add_control ( 'background_attachment' , array (
'label' => __ ( 'Background Attachment' ),
2012-05-25 21:52:54 +02:00
'section' => 'background_image' ,
2012-03-28 06:14:09 +02:00
'type' => 'radio' ,
2012-03-22 09:07:44 +01:00
'choices' => array (
'scroll' => __ ( 'Scroll' ),
2014-07-11 22:27:14 +02:00
'fixed' => __ ( 'Fixed' ),
2012-03-22 09:07:44 +01:00
),
2012-02-25 05:12:43 +01:00
) );
2012-05-25 20:41:22 +02: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-25 05:12:43 +01:00
/* Nav Menus */
$locations = get_registered_nav_menus ();
$menus = wp_get_nav_menus ();
$num_locations = count ( array_keys ( $locations ) );
$this -> add_section ( 'nav' , array (
'title' => __ ( 'Navigation' ),
'theme_supports' => 'menus' ,
2012-05-25 21:52:54 +02:00
'priority' => 100 ,
2012-04-24 01:03:09 +02: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-25 05:12:43 +01:00
) );
2012-04-24 01:03:09 +02:00
if ( $menus ) {
2015-01-07 20:50:23 +01:00
$choices = array ( '' => __ ( '— Select —' ) );
2012-02-25 05:12:43 +01:00
foreach ( $menus as $menu ) {
2013-05-09 02:22:02 +02:00
$choices [ $menu -> term_id ] = wp_html_excerpt ( $menu -> name , 40 , '…' );
2012-02-25 05:12:43 +01:00
}
2012-04-24 01:03:09 +02:00
foreach ( $locations as $location => $description ) {
$menu_setting_id = " nav_menu_locations[ { $location } ] " ;
2012-03-28 06:14:09 +02:00
2012-04-24 01:03:09 +02:00
$this -> add_setting ( $menu_setting_id , array (
'sanitize_callback' => 'absint' ,
'theme_supports' => 'menus' ,
) );
2012-03-28 06:14:09 +02:00
2012-04-24 01:03:09 +02:00
$this -> add_control ( $menu_setting_id , array (
'label' => $description ,
'section' => 'nav' ,
'type' => 'select' ,
'choices' => $choices ,
) );
}
2012-02-25 05:12:43 +01:00
}
/* Static Front Page */
// #WP19627
2015-01-18 07:01:24 +01:00
// Replicate behavior from options-reading.php and hide front page options if there are no pages
if ( get_pages () ) {
$this -> add_section ( 'static_front_page' , array (
'title' => __ ( 'Static Front Page' ),
// 'theme_supports' => 'static-front-page',
'priority' => 120 ,
'description' => __ ( 'Your theme supports a static front page.' ),
) );
$this -> add_setting ( 'show_on_front' , array (
'default' => get_option ( 'show_on_front' ),
'capability' => 'manage_options' ,
'type' => 'option' ,
// 'theme_supports' => 'static-front-page',
) );
$this -> add_control ( 'show_on_front' , array (
'label' => __ ( 'Front page displays' ),
'section' => 'static_front_page' ,
'type' => 'radio' ,
'choices' => array (
'posts' => __ ( 'Your latest posts' ),
'page' => __ ( 'A static page' ),
),
) );
$this -> add_setting ( 'page_on_front' , array (
'type' => 'option' ,
'capability' => 'manage_options' ,
// 'theme_supports' => 'static-front-page',
) );
$this -> add_control ( 'page_on_front' , array (
'label' => __ ( 'Front page' ),
'section' => 'static_front_page' ,
'type' => 'dropdown-pages' ,
) );
$this -> add_setting ( 'page_for_posts' , array (
'type' => 'option' ,
'capability' => 'manage_options' ,
// 'theme_supports' => 'static-front-page',
) );
$this -> add_control ( 'page_for_posts' , array (
'label' => __ ( 'Posts page' ),
'section' => 'static_front_page' ,
'type' => 'dropdown-pages' ,
) );
}
2012-02-25 05:12:43 +01:00
}
2012-05-23 17:36:27 +02:00
2015-02-09 00:11:25 +01:00
/**
* Add settings from the POST data that were not added with code , e . g . dynamically - created settings for Widgets
*
* @ since 4.2 . 0
*/
public function register_dynamic_settings () {
$this -> add_dynamic_settings ( array_keys ( $this -> unsanitized_post_values () ) );
}
2012-05-26 20:44:31 +02:00
/**
* Callback for validating the header_textcolor value .
*
* Accepts 'blank' , and otherwise uses sanitize_hex_color_no_hash () .
2013-07-12 22:41:46 +02:00
* Returns default text color if hex color is empty .
2012-05-26 20:44:31 +02:00
*
* @ since 3.4 . 0
2012-07-26 23:45:33 +02:00
*
* @ param string $color
* @ return string
2012-05-26 20:44:31 +02:00
*/
public function _sanitize_header_textcolor ( $color ) {
2013-07-12 22:41:46 +02: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 20:44:31 +02:00
}
2014-05-22 21:01:15 +02:00
}
2012-05-23 17:36:27 +02:00
2012-05-26 20:44:31 +02:00
/**
2014-03-04 21:21:14 +01:00
* Sanitizes a hex color .
2012-05-26 20:44:31 +02:00
*
* Returns either '' , a 3 or 6 digit hex color ( with #), or null.
2014-03-04 21:21:14 +01:00
* For sanitizing values without a #, see sanitize_hex_color_no_hash().
2012-05-26 20:44:31 +02:00
*
* @ since 3.4 . 0
2012-07-26 23:45:33 +02:00
*
* @ param string $color
* @ return string | null
2012-05-26 20:44:31 +02:00
*/
function sanitize_hex_color ( $color ) {
if ( '' === $color )
return '' ;
2012-02-25 05:12:43 +01:00
2012-05-25 22:58:49 +02:00
// 3 or 6 hex digits, or the empty string.
2012-05-26 20:44:31 +02:00
if ( preg_match ( '|^#([A-Fa-f0-9]{3}){1,2}$|' , $color ) )
2012-02-25 05:12:43 +01:00
return $color ;
2012-05-25 20:54:57 +02:00
return null ;
2012-05-23 19:56:42 +02:00
}
2012-05-26 20:44:31 +02: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 23:45:33 +02:00
*
* @ param string $color
* @ return string | null
2012-05-26 20:44:31 +02: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 23:45:33 +02:00
*
* @ param string $color
* @ return string
2012-05-26 20:44:31 +02:00
*/
function maybe_hash_hex_color ( $color ) {
if ( $unhashed = sanitize_hex_color_no_hash ( $color ) )
return '#' . $unhashed ;
return $color ;
2012-06-08 21:22:11 +02:00
}