2014-03-05 15:41:14 -05:00
< ? php
/**
2014-03-26 18:29:15 -04:00
* Customize Widgets Class
*
* Implements widget management in the Customizer .
*
* @ package WordPress
* @ subpackage Customize
2014-03-28 10:07:14 -04:00
* @ since 3.9 . 0
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
final class WP_Customize_Widgets {
2014-04-02 01:45:16 -04:00
2014-03-28 10:07:14 -04:00
/**
2014-04-02 01:45:16 -04:00
* WP_Customize_Manager instance .
*
* @ since 3.9 . 0
2014-03-28 10:07:14 -04:00
* @ access public
* @ var WP_Customize_Manager
*/
public $manager ;
2014-03-05 15:41:14 -05:00
/**
2014-04-02 01:45:16 -04:00
* All id_bases for widgets defined in core .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access protected
2014-03-05 15:41:14 -05:00
* @ var array
*/
2014-03-28 10:07:14 -04:00
protected $core_widget_id_bases = array (
2014-04-02 02:12:16 -04:00
'archives' , 'calendar' , 'categories' , 'links' , 'meta' ,
'nav_menu' , 'pages' , 'recent-comments' , 'recent-posts' ,
'rss' , 'search' , 'tag_cloud' , 'text' ,
2014-03-05 15:41:14 -05:00
);
2014-03-26 18:29:15 -04:00
/**
* @ since 3.9 . 0
* @ access protected
* @ var
*/
2014-03-28 10:07:14 -04:00
protected $_customized ;
2014-03-26 18:29:15 -04:00
/**
* @ since 3.9 . 0
* @ access protected
* @ var array
*/
2014-03-28 10:07:14 -04:00
protected $_prepreview_added_filters = array ();
2014-03-26 18:29:15 -04:00
/**
* @ since 3.9 . 0
* @ access protected
* @ var array
*/
2014-03-28 10:07:14 -04:00
protected $rendered_sidebars = array ();
2014-03-26 18:29:15 -04:00
/**
* @ since 3.9 . 0
* @ access protected
* @ var array
*/
2014-03-28 10:07:14 -04:00
protected $rendered_widgets = array ();
2014-03-26 18:29:15 -04:00
2014-04-14 18:46:16 -04:00
/**
* @ since 3.9 . 0
* @ access protected
* @ var array
*/
protected $old_sidebars_widgets = array ();
2014-03-05 15:41:14 -05:00
/**
* Initial loader .
2014-03-26 18:29:15 -04:00
*
* @ since 3.9 . 0
* @ access public
2014-04-02 01:45:16 -04:00
*
* @ param WP_Customize_Manager $manager Customize manager bootstrap instance .
2014-03-05 15:41:14 -05:00
*/
2014-04-06 14:54:14 -04:00
public function __construct ( $manager ) {
2014-03-28 10:07:14 -04:00
$this -> manager = $manager ;
add_action ( 'after_setup_theme' , array ( $this , 'setup_widget_addition_previews' ) );
2014-04-14 18:46:16 -04:00
add_action ( 'wp_loaded' , array ( $this , 'override_sidebars_widgets_for_theme_switch' ) );
2014-03-28 10:07:14 -04:00
add_action ( 'customize_controls_init' , array ( $this , 'customize_controls_init' ) );
add_action ( 'customize_register' , array ( $this , 'schedule_customize_register' ), 1 );
2014-04-02 13:04:14 -04:00
add_action ( 'customize_controls_enqueue_scripts' , array ( $this , 'enqueue_scripts' ) );
add_action ( 'customize_controls_print_styles' , array ( $this , 'print_styles' ) );
add_action ( 'customize_controls_print_scripts' , array ( $this , 'print_scripts' ) );
add_action ( 'customize_controls_print_footer_scripts' , array ( $this , 'print_footer_scripts' ) );
2014-03-28 10:07:14 -04:00
add_action ( 'customize_controls_print_footer_scripts' , array ( $this , 'output_widget_control_templates' ) );
add_action ( 'customize_preview_init' , array ( $this , 'customize_preview_init' ) );
add_action ( 'dynamic_sidebar' , array ( $this , 'tally_rendered_widgets' ) );
add_filter ( 'is_active_sidebar' , array ( $this , 'tally_sidebars_via_is_active_sidebar_calls' ), 10 , 2 );
add_filter ( 'dynamic_sidebar_has_widgets' , array ( $this , 'tally_sidebars_via_dynamic_sidebar_calls' ), 10 , 2 );
2014-03-05 15:41:14 -05:00
}
/**
2014-03-26 18:29:15 -04:00
* Get an unslashed post value or return a default .
*
* @ since 3.9 . 0
*
2014-03-28 10:07:14 -04:00
* @ access protected
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ param string $name Post value .
* @ param mixed $default Default post value .
* @ return mixed Unslashed post value or default value .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
protected function get_post_value ( $name , $default = null ) {
2014-03-26 18:29:15 -04:00
if ( ! isset ( $_POST [ $name ] ) ) {
2014-03-05 15:41:14 -05:00
return $default ;
}
2014-03-28 10:07:14 -04:00
2014-03-05 15:41:14 -05:00
return wp_unslash ( $_POST [ $name ] );
}
/**
2014-04-02 01:45:16 -04:00
* Set up widget addition previews .
2014-03-26 18:29:15 -04:00
*
2014-10-15 13:21:19 -04:00
* Since the widgets get registered on 'widgets_init' before the Customizer
2014-04-02 01:45:16 -04:00
* settings are set up on 'customize_register' , we have to filter the options
* similarly to how the setting previewer will filter the options later .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
*
* @ access public
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function setup_widget_addition_previews () {
2014-03-28 13:09:15 -04:00
$is_customize_preview = false ;
2014-04-02 02:12:16 -04:00
2014-03-28 13:09:15 -04:00
if ( ! empty ( $this -> manager ) && ! is_admin () && 'on' === $this -> get_post_value ( 'wp_customize' ) ) {
$is_customize_preview = check_ajax_referer ( 'preview-customize_' . $this -> manager -> get_stylesheet (), 'nonce' , false );
}
$is_ajax_widget_update = false ;
2014-04-14 18:46:16 -04:00
if ( $this -> manager -> doing_ajax () && 'update-widget' === $this -> get_post_value ( 'action' ) ) {
2014-03-28 13:09:15 -04:00
$is_ajax_widget_update = check_ajax_referer ( 'update-widget' , 'nonce' , false );
}
$is_ajax_customize_save = false ;
2014-04-14 18:46:16 -04:00
if ( $this -> manager -> doing_ajax () && 'customize_save' === $this -> get_post_value ( 'action' ) ) {
2014-03-28 13:09:15 -04:00
$is_ajax_customize_save = check_ajax_referer ( 'save-customize_' . $this -> manager -> get_stylesheet (), 'nonce' , false );
}
2014-03-05 15:41:14 -05:00
$is_valid_request = ( $is_ajax_widget_update || $is_customize_preview || $is_ajax_customize_save );
if ( ! $is_valid_request ) {
return ;
}
2014-10-15 13:21:19 -04:00
// Input from Customizer preview.
2014-03-05 15:41:14 -05:00
if ( isset ( $_POST [ 'customized' ] ) ) {
2014-04-15 20:11:35 -04:00
$this -> _customized = json_decode ( $this -> get_post_value ( 'customized' ), true );
2014-04-02 02:12:16 -04:00
} else { // Input from ajax widget update request.
2014-04-15 20:11:35 -04:00
$this -> _customized = array ();
$id_base = $this -> get_post_value ( 'id_base' );
$widget_number = $this -> get_post_value ( 'widget_number' , false );
$option_name = 'widget_' . $id_base ;
$this -> _customized [ $option_name ] = array ();
if ( preg_match ( '/^[0-9]+$/' , $widget_number ) ) {
2014-03-05 15:41:14 -05:00
$option_name .= '[' . $widget_number . ']' ;
2014-04-15 20:11:35 -04:00
$this -> _customized [ $option_name ][ $widget_number ] = array ();
2014-03-05 15:41:14 -05:00
}
}
2014-03-28 10:07:14 -04:00
$function = array ( $this , 'prepreview_added_sidebars_widgets' );
2014-03-05 15:41:14 -05:00
$hook = 'option_sidebars_widgets' ;
add_filter ( $hook , $function );
2014-03-28 10:07:14 -04:00
$this -> _prepreview_added_filters [] = compact ( 'hook' , 'function' );
2014-03-05 15:41:14 -05:00
$hook = 'default_option_sidebars_widgets' ;
add_filter ( $hook , $function );
2014-03-28 10:07:14 -04:00
$this -> _prepreview_added_filters [] = compact ( 'hook' , 'function' );
2014-03-05 15:41:14 -05:00
2014-04-15 20:11:35 -04:00
$function = array ( $this , 'prepreview_added_widget_instance' );
foreach ( $this -> _customized as $setting_id => $value ) {
if ( preg_match ( '/^(widget_.+?)(?:\[(\d+)\])?$/' , $setting_id , $matches ) ) {
2014-04-02 01:45:16 -04:00
$option = $matches [ 1 ];
2014-03-05 15:41:14 -05:00
$hook = sprintf ( 'option_%s' , $option );
2014-04-15 20:11:35 -04:00
if ( ! has_filter ( $hook , $function ) ) {
add_filter ( $hook , $function );
$this -> _prepreview_added_filters [] = compact ( 'hook' , 'function' );
}
2014-03-05 15:41:14 -05:00
$hook = sprintf ( 'default_option_%s' , $option );
2014-04-15 20:11:35 -04:00
if ( ! has_filter ( $hook , $function ) ) {
add_filter ( $hook , $function );
$this -> _prepreview_added_filters [] = compact ( 'hook' , 'function' );
}
2014-03-05 15:41:14 -05:00
2014-04-02 01:45:16 -04:00
/*
* Make sure the option is registered so that the update_option ()
* won ' t fail due to the filters providing a default value , which
* causes the update_option () to get confused .
2014-03-05 15:41:14 -05:00
*/
add_option ( $option , array () );
}
}
}
/**
* Ensure that newly - added widgets will appear in the widgets_sidebars .
2014-04-02 01:45:16 -04:00
*
2014-10-15 13:21:19 -04:00
* This is necessary because the Customizer ' s setting preview filters
2014-04-02 01:45:16 -04:00
* are added after the widgets_init action , which is too late for the
* widgets to be set up properly .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
2014-04-02 01:45:16 -04:00
* @ param array $sidebars_widgets Associative array of sidebars and their widgets .
* @ return array Filtered array of sidebars and their widgets .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function prepreview_added_sidebars_widgets ( $sidebars_widgets ) {
foreach ( $this -> _customized as $setting_id => $value ) {
2014-03-05 15:41:14 -05:00
if ( preg_match ( '/^sidebars_widgets\[(.+?)\]$/' , $setting_id , $matches ) ) {
$sidebar_id = $matches [ 1 ];
2014-04-15 20:11:35 -04:00
$sidebars_widgets [ $sidebar_id ] = $value ;
2014-03-05 15:41:14 -05:00
}
}
return $sidebars_widgets ;
}
/**
2014-04-02 01:45:16 -04:00
* Ensure newly - added widgets have empty instances so they
* will be recognized .
2014-03-26 18:29:15 -04:00
*
2014-10-15 13:21:19 -04:00
* This is necessary because the Customizer ' s setting preview
2014-04-02 01:45:16 -04:00
* filters are added after the widgets_init action , which is
* too late for the widgets to be set up properly .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
2014-04-15 20:11:35 -04:00
* @ param array | bool | mixed $value Widget instance ( s ), false if open was empty .
* @ return array | mixed Widget instance ( s ) with additions .
2014-03-05 15:41:14 -05:00
*/
2014-04-15 20:11:35 -04:00
public function prepreview_added_widget_instance ( $value = false ) {
if ( ! preg_match ( '/^(?:default_)?option_(widget_(.+))/' , current_filter (), $matches ) ) {
return $value ;
}
$id_base = $matches [ 2 ];
foreach ( $this -> _customized as $setting_id => $setting ) {
2014-03-28 10:07:14 -04:00
$parsed_setting_id = $this -> parse_widget_setting_id ( $setting_id );
2014-04-15 20:11:35 -04:00
if ( is_wp_error ( $parsed_setting_id ) || $id_base !== $parsed_setting_id [ 'id_base' ] ) {
continue ;
}
$widget_number = $parsed_setting_id [ 'number' ];
2014-03-05 15:41:14 -05:00
if ( is_null ( $widget_number ) ) {
2014-04-15 20:11:35 -04:00
// Single widget.
if ( false === $value ) {
$value = array ();
2014-03-05 15:41:14 -05:00
}
2014-04-15 20:11:35 -04:00
} else {
// Multi widget.
if ( empty ( $value ) ) {
$value = array ( '_multiwidget' => 1 );
2014-03-05 15:41:14 -05:00
}
2014-04-15 20:11:35 -04:00
if ( ! isset ( $value [ $widget_number ] ) ) {
$value [ $widget_number ] = array ();
2014-03-05 15:41:14 -05:00
}
}
}
2014-04-15 20:11:35 -04:00
return $value ;
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* Remove pre - preview filters .
*
* Removes filters added in setup_widget_addition_previews ()
* to ensure widgets are populating the options during
* 'widgets_init' .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function remove_prepreview_filters () {
foreach ( $this -> _prepreview_added_filters as $prepreview_added_filter ) {
2014-03-05 15:41:14 -05:00
remove_filter ( $prepreview_added_filter [ 'hook' ], $prepreview_added_filter [ 'function' ] );
}
2014-03-28 10:07:14 -04:00
$this -> _prepreview_added_filters = array ();
2014-03-05 15:41:14 -05:00
}
2014-04-14 18:46:16 -04:00
/**
* Override sidebars_widgets for theme switch .
*
2014-10-15 13:21:19 -04:00
* When switching a theme via the Customizer , supply any previously - configured
2014-04-14 18:46:16 -04:00
* sidebars_widgets from the target theme as the initial sidebars_widgets
* setting . Also store the old theme ' s existing settings so that they can
* be passed along for storing in the sidebars_widgets theme_mod when the
* theme gets switched .
*
* @ since 3.9 . 0
* @ access public
*/
public function override_sidebars_widgets_for_theme_switch () {
global $sidebars_widgets ;
if ( $this -> manager -> doing_ajax () || $this -> manager -> is_theme_active () ) {
return ;
}
$this -> old_sidebars_widgets = wp_get_sidebars_widgets ();
add_filter ( 'customize_value_old_sidebars_widgets_data' , array ( $this , 'filter_customize_value_old_sidebars_widgets_data' ) );
// retrieve_widgets() looks at the global $sidebars_widgets
$sidebars_widgets = $this -> old_sidebars_widgets ;
$sidebars_widgets = retrieve_widgets ( 'customize' );
add_filter ( 'option_sidebars_widgets' , array ( $this , 'filter_option_sidebars_widgets_for_theme_switch' ), 1 );
}
/**
2014-10-15 13:21:19 -04:00
* Filter old_sidebars_widgets_data Customizer setting .
2014-04-14 18:46:16 -04:00
*
* When switching themes , filter the Customizer setting
* old_sidebars_widgets_data to supply initial $sidebars_widgets before they
* were overridden by retrieve_widgets () . The value for
* old_sidebars_widgets_data gets set in the old theme ' s sidebars_widgets
* theme_mod .
*
* @ see WP_Customize_Widgets :: handle_theme_switch ()
* @ since 3.9 . 0
* @ access public
*
2014-11-30 18:33:23 -05:00
* @ param array $old_sidebars_widgets
2014-04-14 18:46:16 -04:00
*/
public function filter_customize_value_old_sidebars_widgets_data ( $old_sidebars_widgets ) {
return $this -> old_sidebars_widgets ;
}
/**
* Filter sidebars_widgets option for theme switch .
*
* When switching themes , the retrieve_widgets () function is run when the
* Customizer initializes , and then the new sidebars_widgets here get
* supplied as the default value for the sidebars_widgets option .
*
* @ see WP_Customize_Widgets :: handle_theme_switch ()
* @ since 3.9 . 0
* @ access public
*
* @ param array $sidebars_widgets
*/
public function filter_option_sidebars_widgets_for_theme_switch ( $sidebars_widgets ) {
$sidebars_widgets = $GLOBALS [ 'sidebars_widgets' ];
$sidebars_widgets [ 'array_version' ] = 3 ;
return $sidebars_widgets ;
}
2014-03-05 15:41:14 -05:00
/**
2014-04-02 01:45:16 -04:00
* Make sure all widgets get loaded into the Customizer .
*
* Note : these actions are also fired in wp_ajax_update_widget () .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function customize_controls_init () {
2014-04-02 01:45:16 -04:00
/** This action is documented in wp-admin/includes/ajax-actions.php */
2014-03-05 15:41:14 -05:00
do_action ( 'load-widgets.php' );
2014-04-02 01:45:16 -04:00
/** This action is documented in wp-admin/includes/ajax-actions.php */
2014-03-05 15:41:14 -05:00
do_action ( 'widgets.php' );
2014-03-28 15:47:15 -04:00
/** This action is documented in wp-admin/widgets.php */
2014-03-05 15:41:14 -05:00
do_action ( 'sidebar_admin_setup' );
}
/**
2014-04-02 01:45:16 -04:00
* Ensure widgets are available for all types of previews .
*
* When in preview , hook to 'customize_register' for settings
* after WordPress is loaded so that all filters have been
* initialized ( e . g . Widget Visibility ) .
2014-03-26 18:29:15 -04:00
*
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function schedule_customize_register () {
2014-03-05 15:41:14 -05:00
if ( is_admin () ) { // @todo for some reason, $wp_customize->is_preview() is true here?
2014-03-28 10:07:14 -04:00
$this -> customize_register ();
2014-03-05 15:41:14 -05:00
} else {
2014-03-28 10:07:14 -04:00
add_action ( 'wp' , array ( $this , 'customize_register' ) );
2014-03-05 15:41:14 -05:00
}
}
/**
2014-10-15 13:21:19 -04:00
* Register Customizer settings and controls for all sidebars and widgets .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function customize_register () {
2014-03-14 16:01:14 -04:00
global $wp_registered_widgets , $wp_registered_widget_controls , $wp_registered_sidebars ;
2014-03-05 15:41:14 -05:00
$sidebars_widgets = array_merge (
array ( 'wp_inactive_widgets' => array () ),
array_fill_keys ( array_keys ( $GLOBALS [ 'wp_registered_sidebars' ] ), array () ),
wp_get_sidebars_widgets ()
);
$new_setting_ids = array ();
2014-03-26 18:29:15 -04:00
/*
2014-04-02 01:45:16 -04:00
* Register a setting for all widgets , including those which are active ,
* inactive , and orphaned since a widget may get suppressed from a sidebar
* via a plugin ( like Widget Visibility ) .
2014-03-05 15:41:14 -05:00
*/
foreach ( array_keys ( $wp_registered_widgets ) as $widget_id ) {
2014-03-28 10:07:14 -04:00
$setting_id = $this -> get_setting_id ( $widget_id );
$setting_args = $this -> get_setting_args ( $setting_id );
2014-04-02 02:12:16 -04:00
2014-03-28 10:07:14 -04:00
$setting_args [ 'sanitize_callback' ] = array ( $this , 'sanitize_widget_instance' );
$setting_args [ 'sanitize_js_callback' ] = array ( $this , 'sanitize_widget_js_instance' );
2014-04-02 02:12:16 -04:00
2014-03-28 10:07:14 -04:00
$this -> manager -> add_setting ( $setting_id , $setting_args );
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
$new_setting_ids [] = $setting_id ;
}
2014-04-14 18:46:16 -04:00
/*
* Add a setting which will be supplied for the theme ' s sidebars_widgets
* theme_mod when the the theme is switched .
*/
if ( ! $this -> manager -> is_theme_active () ) {
$setting_id = 'old_sidebars_widgets_data' ;
$setting_args = $this -> get_setting_args ( $setting_id , array (
'type' => 'global_variable' ,
) );
$this -> manager -> add_setting ( $setting_id , $setting_args );
}
2014-06-26 16:17:15 -04:00
$this -> manager -> add_panel ( 'widgets' , array (
2014-08-14 00:43:16 -04:00
'title' => __ ( 'Widgets' ),
2014-06-26 16:17:15 -04:00
'description' => __ ( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ),
2014-08-14 00:43:16 -04:00
'priority' => 110 ,
2014-06-26 16:17:15 -04:00
) );
2014-03-05 15:41:14 -05:00
foreach ( $sidebars_widgets as $sidebar_id => $sidebar_widget_ids ) {
if ( empty ( $sidebar_widget_ids ) ) {
$sidebar_widget_ids = array ();
}
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
$is_registered_sidebar = isset ( $GLOBALS [ 'wp_registered_sidebars' ][ $sidebar_id ] );
$is_inactive_widgets = ( 'wp_inactive_widgets' === $sidebar_id );
$is_active_sidebar = ( $is_registered_sidebar && ! $is_inactive_widgets );
2014-04-02 01:45:16 -04:00
// Add setting for managing the sidebar's widgets.
2014-03-05 15:41:14 -05:00
if ( $is_registered_sidebar || $is_inactive_widgets ) {
$setting_id = sprintf ( 'sidebars_widgets[%s]' , $sidebar_id );
2014-03-28 10:07:14 -04:00
$setting_args = $this -> get_setting_args ( $setting_id );
2014-04-02 02:12:16 -04:00
2014-03-28 10:07:14 -04:00
$setting_args [ 'sanitize_callback' ] = array ( $this , 'sanitize_sidebar_widgets' );
$setting_args [ 'sanitize_js_callback' ] = array ( $this , 'sanitize_sidebar_widgets_js_instance' );
2014-04-02 02:12:16 -04:00
2014-03-28 10:07:14 -04:00
$this -> manager -> add_setting ( $setting_id , $setting_args );
2014-03-05 15:41:14 -05:00
$new_setting_ids [] = $setting_id ;
2014-04-02 01:45:16 -04:00
// Add section to contain controls.
2014-03-05 15:41:14 -05:00
$section_id = sprintf ( 'sidebar-widgets-%s' , $sidebar_id );
if ( $is_active_sidebar ) {
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
$section_args = array (
2014-06-26 16:17:15 -04:00
'title' => $GLOBALS [ 'wp_registered_sidebars' ][ $sidebar_id ][ 'name' ],
'description' => $GLOBALS [ 'wp_registered_sidebars' ][ $sidebar_id ][ 'description' ],
'priority' => array_search ( $sidebar_id , array_keys ( $wp_registered_sidebars ) ),
'panel' => 'widgets' ,
2014-11-13 07:19:23 -05:00
'sidebar_id' => $sidebar_id ,
2014-03-05 15:41:14 -05:00
);
2014-04-14 14:41:17 -04:00
/**
* Filter Customizer widget section arguments for a given sidebar .
*
* @ since 3.9 . 0
*
* @ param array $section_args Array of Customizer widget section arguments .
* @ param string $section_id Customizer section ID .
* @ param int | string $sidebar_id Sidebar ID .
*/
2014-03-05 15:41:14 -05:00
$section_args = apply_filters ( 'customizer_widgets_section_args' , $section_args , $section_id , $sidebar_id );
2014-04-02 02:12:16 -04:00
2014-11-13 07:19:23 -05:00
$section = new WP_Customize_Sidebar_Section ( $this -> manager , $section_id , $section_args );
$this -> manager -> add_section ( $section );
2014-03-05 15:41:14 -05:00
2014-04-02 02:12:16 -04:00
$control = new WP_Widget_Area_Customize_Control ( $this -> manager , $setting_id , array (
'section' => $section_id ,
'sidebar_id' => $sidebar_id ,
'priority' => count ( $sidebar_widget_ids ), // place 'Add Widget' and 'Reorder' buttons at end.
) );
2014-03-05 15:41:14 -05:00
$new_setting_ids [] = $setting_id ;
2014-04-02 02:12:16 -04:00
2014-03-28 10:07:14 -04:00
$this -> manager -> add_control ( $control );
2014-03-05 15:41:14 -05:00
}
}
2014-03-26 18:29:15 -04:00
// Add a control for each active widget (located in a sidebar).
2014-03-05 15:41:14 -05:00
foreach ( $sidebar_widget_ids as $i => $widget_id ) {
2014-03-26 18:29:15 -04:00
// Skip widgets that may have gone away due to a plugin being deactivated.
2014-03-05 15:41:14 -05:00
if ( ! $is_active_sidebar || ! isset ( $GLOBALS [ 'wp_registered_widgets' ][ $widget_id ] ) ) {
continue ;
}
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
$registered_widget = $GLOBALS [ 'wp_registered_widgets' ][ $widget_id ];
2014-04-02 02:12:16 -04:00
$setting_id = $this -> get_setting_id ( $widget_id );
$id_base = $GLOBALS [ 'wp_registered_widget_controls' ][ $widget_id ][ 'id_base' ];
$control = new WP_Widget_Form_Customize_Control ( $this -> manager , $setting_id , array (
'label' => $registered_widget [ 'name' ],
'section' => $section_id ,
'sidebar_id' => $sidebar_id ,
'widget_id' => $widget_id ,
'widget_id_base' => $id_base ,
'priority' => $i ,
'width' => $wp_registered_widget_controls [ $widget_id ][ 'width' ],
'height' => $wp_registered_widget_controls [ $widget_id ][ 'height' ],
'is_wide' => $this -> is_wide_widget ( $widget_id ),
) );
2014-03-28 10:07:14 -04:00
$this -> manager -> add_control ( $control );
2014-03-05 15:41:14 -05:00
}
}
2014-03-26 18:29:15 -04:00
/*
* We have to register these settings later than customize_preview_init
* so that other filters have had a chance to run .
2014-03-05 15:41:14 -05:00
*/
if ( did_action ( 'customize_preview_init' ) ) {
foreach ( $new_setting_ids as $new_setting_id ) {
2014-03-28 10:07:14 -04:00
$this -> manager -> get_setting ( $new_setting_id ) -> preview ();
2014-03-05 15:41:14 -05:00
}
}
2014-03-28 10:07:14 -04:00
$this -> remove_prepreview_filters ();
2014-03-05 15:41:14 -05:00
}
/**
2014-10-15 13:21:19 -04:00
* Covert a widget_id into its corresponding Customizer setting ID ( option name ) .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param string $widget_id Widget ID .
* @ return string Maybe - parsed widget ID .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function get_setting_id ( $widget_id ) {
$parsed_widget_id = $this -> parse_widget_id ( $widget_id );
2014-04-02 02:12:16 -04:00
$setting_id = sprintf ( 'widget_%s' , $parsed_widget_id [ 'id_base' ] );
2014-03-05 15:41:14 -05:00
if ( ! is_null ( $parsed_widget_id [ 'number' ] ) ) {
$setting_id .= sprintf ( '[%d]' , $parsed_widget_id [ 'number' ] );
}
return $setting_id ;
}
/**
2014-04-02 01:45:16 -04:00
* Determine whether the widget is considered " wide " .
*
* Core widgets which may have controls wider than 250 , but can
2014-10-15 13:21:19 -04:00
* still be shown in the narrow Customizer panel . The RSS and Text
2014-04-02 01:45:16 -04:00
* widgets in Core , for example , have widths of 400 and yet they
2014-10-15 13:21:19 -04:00
* still render fine in the Customizer panel . This method will
2014-04-02 01:45:16 -04:00
* return all Core widgets as being not wide , but this can be
* overridden with the is_wide_widget_in_customizer filter .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param string $widget_id Widget ID .
* @ return bool Whether or not the widget is a " wide " widget .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function is_wide_widget ( $widget_id ) {
2014-03-05 15:41:14 -05:00
global $wp_registered_widget_controls ;
2014-04-02 02:12:16 -04:00
2014-03-28 10:07:14 -04:00
$parsed_widget_id = $this -> parse_widget_id ( $widget_id );
2014-04-02 02:12:16 -04:00
$width = $wp_registered_widget_controls [ $widget_id ][ 'width' ];
$is_core = in_array ( $parsed_widget_id [ 'id_base' ], $this -> core_widget_id_bases );
$is_wide = ( $width > 250 && ! $is_core );
2014-03-26 18:29:15 -04:00
/**
* Filter whether the given widget is considered " wide " .
*
* @ since 3.9 . 0
*
* @ param bool $is_wide Whether the widget is wide , Default false .
* @ param string $widget_id Widget ID .
*/
2014-04-02 01:45:16 -04:00
return apply_filters ( 'is_wide_widget_in_customizer' , $is_wide , $widget_id );
2014-03-05 15:41:14 -05:00
}
/**
2014-03-26 18:29:15 -04:00
* Covert a widget ID into its id_base and number components .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param string $widget_id Widget ID .
* @ return array Array containing a widget ' s id_base and number components .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function parse_widget_id ( $widget_id ) {
2014-03-05 15:41:14 -05:00
$parsed = array (
'number' => null ,
'id_base' => null ,
);
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
if ( preg_match ( '/^(.+)-(\d+)$/' , $widget_id , $matches ) ) {
$parsed [ 'id_base' ] = $matches [ 1 ];
$parsed [ 'number' ] = intval ( $matches [ 2 ] );
} else {
// likely an old single widget
$parsed [ 'id_base' ] = $widget_id ;
}
return $parsed ;
}
/**
2014-03-26 18:29:15 -04:00
* Convert a widget setting ID ( option path ) to its id_base and number components .
*
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ param string $setting_id Widget setting ID .
2014-04-02 01:45:16 -04:00
* @ return WP_Error | array Array containing a widget ' s id_base and number components ,
2014-03-26 18:29:15 -04:00
* or a WP_Error object .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function parse_widget_setting_id ( $setting_id ) {
2014-03-05 15:41:14 -05:00
if ( ! preg_match ( '/^(widget_(.+?))(?:\[(\d+)\])?$/' , $setting_id , $matches ) ) {
2014-03-29 17:44:14 -04:00
return new WP_Error ( 'widget_setting_invalid_id' );
2014-03-05 15:41:14 -05:00
}
2014-03-22 16:55:18 -04:00
2014-03-05 15:41:14 -05:00
$id_base = $matches [ 2 ];
$number = isset ( $matches [ 3 ] ) ? intval ( $matches [ 3 ] ) : null ;
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
return compact ( 'id_base' , 'number' );
}
2014-04-02 13:04:14 -04:00
/**
* Call admin_print_styles - widgets . php and admin_print_styles hooks to
* allow custom styles from plugins .
*
* @ since 3.9 . 0
* @ access public
*/
public function print_styles () {
/** This action is documented in wp-admin/admin-header.php */
do_action ( 'admin_print_styles-widgets.php' );
/** This action is documented in wp-admin/admin-header.php */
do_action ( 'admin_print_styles' );
}
/**
* Call admin_print_scripts - widgets . php and admin_print_scripts hooks to
* allow custom scripts from plugins .
*
* @ since 3.9 . 0
* @ access public
*/
public function print_scripts () {
/** This action is documented in wp-admin/admin-header.php */
do_action ( 'admin_print_scripts-widgets.php' );
/** This action is documented in wp-admin/admin-header.php */
do_action ( 'admin_print_scripts' );
}
2014-03-05 15:41:14 -05:00
/**
2014-10-15 13:21:19 -04:00
* Enqueue scripts and styles for Customizer panel and export data to JavaScript .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*/
2014-04-02 13:04:14 -04:00
public function enqueue_scripts () {
2014-03-13 15:41:14 -04:00
wp_enqueue_style ( 'customize-widgets' );
wp_enqueue_script ( 'customize-widgets' );
2014-03-05 15:41:14 -05:00
2014-04-02 13:04:14 -04:00
/** This action is documented in wp-admin/admin-header.php */
do_action ( 'admin_enqueue_scripts' , 'widgets.php' );
2014-04-02 01:45:16 -04:00
/*
* Export available widgets with control_tpl removed from model
* since plugins need templates to be in the DOM .
*/
2014-03-05 15:41:14 -05:00
$available_widgets = array ();
2014-04-02 02:12:16 -04:00
2014-03-28 10:07:14 -04:00
foreach ( $this -> get_available_widgets () as $available_widget ) {
2014-03-05 15:41:14 -05:00
unset ( $available_widget [ 'control_tpl' ] );
$available_widgets [] = $available_widget ;
}
$widget_reorder_nav_tpl = sprintf (
2014-03-19 04:18:14 -04:00
'<div class="widget-reorder-nav"><span class="move-widget" tabindex="0">%1$s</span><span class="move-widget-down" tabindex="0">%2$s</span><span class="move-widget-up" tabindex="0">%3$s</span></div>' ,
__ ( 'Move to another area…' ),
__ ( 'Move down' ),
__ ( 'Move up' )
2014-03-05 15:41:14 -05:00
);
$move_widget_area_tpl = str_replace (
array ( '{description}' , '{btn}' ),
array (
2014-04-07 05:04:14 -04:00
__ ( 'Select an area to move this widget into:' ),
_x ( 'Move' , 'Move widget' ),
2014-03-05 15:41:14 -05:00
),
2014-04-06 16:40:15 -04:00
' < div class = " move-widget-area " >
< p class = " description " > { description } </ p >
< ul class = " widget-area-select " >
<% _ . each ( sidebars , function ( sidebar ){ %>
< li class = " " data - id = " <%- sidebar.id %> " title = " <%- sidebar.description %> " tabindex = " 0 " ><%- sidebar . name %></ li >
<% }); %>
</ ul >
< div class = " move-widget-actions " >
< button class = " move-widget-btn button-secondary " type = " button " > { btn } </ button >
2014-03-05 15:41:14 -05:00
</ div >
2014-04-06 16:40:15 -04:00
</ div > '
2014-03-05 15:41:14 -05:00
);
global $wp_scripts ;
2014-04-02 02:12:16 -04:00
2014-04-07 05:04:14 -04:00
$settings = array (
'nonce' => wp_create_nonce ( 'update-widget' ),
'registeredSidebars' => array_values ( $GLOBALS [ 'wp_registered_sidebars' ] ),
'registeredWidgets' => $GLOBALS [ 'wp_registered_widgets' ],
'availableWidgets' => $available_widgets , // @todo Merge this with registered_widgets
'l10n' => array (
'saveBtnLabel' => __ ( 'Apply' ),
'saveBtnTooltip' => __ ( 'Save and preview changes before publishing them.' ),
'removeBtnLabel' => __ ( 'Remove' ),
'removeBtnTooltip' => __ ( 'Trash widget by moving it to the inactive widgets sidebar.' ),
'error' => __ ( 'An error has occurred. Please reload the page and try again.' ),
2014-12-06 19:45:24 -05:00
'widgetMovedUp' => __ ( 'Widget moved up' ),
'widgetMovedDown' => __ ( 'Widget moved down' ),
2014-03-05 15:41:14 -05:00
),
2014-04-07 05:04:14 -04:00
'tpl' => array (
'widgetReorderNav' => $widget_reorder_nav_tpl ,
'moveWidgetArea' => $move_widget_area_tpl ,
2014-03-05 15:41:14 -05:00
),
);
2014-04-02 02:12:16 -04:00
2014-04-07 05:04:14 -04:00
foreach ( $settings [ 'registeredWidgets' ] as & $registered_widget ) {
2014-03-05 15:41:14 -05:00
unset ( $registered_widget [ 'callback' ] ); // may not be JSON-serializeable
}
$wp_scripts -> add_data (
2014-03-13 15:41:14 -04:00
'customize-widgets' ,
2014-03-05 15:41:14 -05:00
'data' ,
2014-10-28 14:35:19 -04:00
sprintf ( 'var _wpCustomizeWidgetsSettings = %s;' , wp_json_encode ( $settings ) )
2014-03-05 15:41:14 -05:00
);
}
/**
2014-04-02 01:45:16 -04:00
* Render the widget form control templates into the DOM .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function output_widget_control_templates () {
2014-03-05 15:41:14 -05:00
?>
< div id = " widgets-left " ><!-- compatibility with JS which looks for widget templates here -->
< div id = " available-widgets " >
< div id = " available-widgets-filter " >
2014-04-07 05:04:14 -04:00
< label class = " screen-reader-text " for = " widgets-search " >< ? php _e ( 'Search Widgets' ); ?> </label>
< input type = " search " id = " widgets-search " placeholder = " <?php esc_attr_e( 'Search widgets…' ) ?> " />
2014-03-05 15:41:14 -05:00
</ div >
2014-03-28 10:07:14 -04:00
< ? php foreach ( $this -> get_available_widgets () as $available_widget ) : ?>
2014-03-05 15:41:14 -05:00
< div id = " widget-tpl-<?php echo esc_attr( $available_widget['id'] ) ?> " data - widget - id = " <?php echo esc_attr( $available_widget['id'] ) ?> " class = " widget-tpl <?php echo esc_attr( $available_widget['id'] ) ?> " tabindex = " 0 " >
2014-04-07 05:04:14 -04:00
< ? php echo $available_widget [ 'control_tpl' ]; ?>
2014-03-05 15:41:14 -05:00
</ div >
< ? php endforeach ; ?>
</ div ><!-- #available-widgets -->
</ div ><!-- #widgets-left -->
< ? php
}
2014-04-02 13:04:14 -04:00
/**
* Call admin_print_footer_scripts and admin_print_scripts hooks to
* allow custom scripts from plugins .
*
* @ since 3.9 . 0
* @ access public
*/
public function print_footer_scripts () {
/** This action is documented in wp-admin/admin-footer.php */
do_action ( 'admin_print_footer_scripts' );
/** This action is documented in wp-admin/admin-footer.php */
do_action ( 'admin_footer-widgets.php' );
}
2014-03-05 15:41:14 -05:00
/**
2014-04-02 01:45:16 -04:00
* Get common arguments to supply when constructing a Customizer setting .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param string $id Widget setting ID .
* @ param array $overrides Array of setting overrides .
* @ return array Possibly modified setting arguments .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function get_setting_args ( $id , $overrides = array () ) {
2014-03-05 15:41:14 -05:00
$args = array (
2014-04-02 02:12:16 -04:00
'type' => 'option' ,
2014-03-05 15:41:14 -05:00
'capability' => 'edit_theme_options' ,
2014-04-02 02:12:16 -04:00
'transport' => 'refresh' ,
'default' => array (),
2014-03-05 15:41:14 -05:00
);
$args = array_merge ( $args , $overrides );
2014-04-02 01:45:16 -04:00
/**
* Filter the common arguments supplied when constructing a Customizer setting .
*
* @ since 3.9 . 0
*
* @ see WP_Customize_Setting
*
* @ param array $args Array of Customizer setting arguments .
* @ param string $id Widget setting ID .
*/
return apply_filters ( 'widget_customizer_setting_args' , $args , $id );
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* Make sure that sidebar widget arrays only ever contain widget IDS .
*
* Used as the 'sanitize_callback' for each $sidebars_widgets setting .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param array $widget_ids Array of widget IDs .
* @ return array Array of sanitized widget IDs .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function sanitize_sidebar_widgets ( $widget_ids ) {
2014-03-05 15:41:14 -05:00
global $wp_registered_widgets ;
2014-04-02 02:12:16 -04:00
$widget_ids = array_map ( 'strval' , ( array ) $widget_ids );
2014-03-05 15:41:14 -05:00
$sanitized_widget_ids = array ();
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
foreach ( $widget_ids as $widget_id ) {
if ( array_key_exists ( $widget_id , $wp_registered_widgets ) ) {
$sanitized_widget_ids [] = $widget_id ;
}
}
return $sanitized_widget_ids ;
}
/**
2014-03-26 18:29:15 -04:00
* Build up an index of all available widgets for use in Backbone models .
*
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*
* @ see wp_list_widgets ()
2014-04-02 01:45:16 -04:00
*
* @ return array List of available widgets .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function get_available_widgets () {
2014-03-05 15:41:14 -05:00
static $available_widgets = array ();
if ( ! empty ( $available_widgets ) ) {
return $available_widgets ;
}
global $wp_registered_widgets , $wp_registered_widget_controls ;
require_once ABSPATH . '/wp-admin/includes/widgets.php' ; // for next_widget_id_number()
$sort = $wp_registered_widgets ;
2014-03-28 10:07:14 -04:00
usort ( $sort , array ( $this , '_sort_name_callback' ) );
2014-03-05 15:41:14 -05:00
$done = array ();
foreach ( $sort as $widget ) {
if ( in_array ( $widget [ 'callback' ], $done , true ) ) { // We already showed this multi-widget
continue ;
}
$sidebar = is_active_widget ( $widget [ 'callback' ], $widget [ 'id' ], false , false );
$done [] = $widget [ 'callback' ];
if ( ! isset ( $widget [ 'params' ][ 0 ] ) ) {
$widget [ 'params' ][ 0 ] = array ();
}
$available_widget = $widget ;
unset ( $available_widget [ 'callback' ] ); // not serializable to JSON
$args = array (
2014-04-02 02:12:16 -04:00
'widget_id' => $widget [ 'id' ],
2014-03-05 15:41:14 -05:00
'widget_name' => $widget [ 'name' ],
2014-04-02 02:12:16 -04:00
'_display' => 'template' ,
2014-03-05 15:41:14 -05:00
);
$is_disabled = false ;
2014-04-02 02:12:16 -04:00
$is_multi_widget = ( isset ( $wp_registered_widget_controls [ $widget [ 'id' ]][ 'id_base' ] ) && isset ( $widget [ 'params' ][ 0 ][ 'number' ] ) );
2014-03-05 15:41:14 -05:00
if ( $is_multi_widget ) {
2014-04-02 02:12:16 -04:00
$id_base = $wp_registered_widget_controls [ $widget [ 'id' ]][ 'id_base' ];
2014-03-05 15:41:14 -05:00
$args [ '_temp_id' ] = " $id_base -__i__ " ;
$args [ '_multi_num' ] = next_widget_id_number ( $id_base );
$args [ '_add' ] = 'multi' ;
} else {
$args [ '_add' ] = 'single' ;
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
if ( $sidebar && 'wp_inactive_widgets' !== $sidebar ) {
$is_disabled = true ;
}
$id_base = $widget [ 'id' ];
}
$list_widget_controls_args = wp_list_widget_controls_dynamic_sidebar ( array ( 0 => $args , 1 => $widget [ 'params' ][ 0 ] ) );
2014-03-28 10:07:14 -04:00
$control_tpl = $this -> get_widget_control ( $list_widget_controls_args );
2014-03-05 15:41:14 -05:00
2014-04-02 01:45:16 -04:00
// The properties here are mapped to the Backbone Widget model.
2014-04-02 02:12:16 -04:00
$available_widget = array_merge ( $available_widget , array (
'temp_id' => isset ( $args [ '_temp_id' ] ) ? $args [ '_temp_id' ] : null ,
'is_multi' => $is_multi_widget ,
'control_tpl' => $control_tpl ,
'multi_number' => ( $args [ '_add' ] === 'multi' ) ? $args [ '_multi_num' ] : false ,
'is_disabled' => $is_disabled ,
'id_base' => $id_base ,
'transport' => 'refresh' ,
'width' => $wp_registered_widget_controls [ $widget [ 'id' ]][ 'width' ],
'height' => $wp_registered_widget_controls [ $widget [ 'id' ]][ 'height' ],
'is_wide' => $this -> is_wide_widget ( $widget [ 'id' ] ),
) );
2014-03-05 15:41:14 -05:00
$available_widgets [] = $available_widget ;
}
2014-04-07 05:04:14 -04:00
2014-03-05 15:41:14 -05:00
return $available_widgets ;
}
/**
2014-03-26 18:29:15 -04:00
* Naturally order available widgets by name .
*
* @ since 3.9 . 0
* @ static
2014-03-28 10:07:14 -04:00
* @ access protected
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ param array $widget_a The first widget to compare .
* @ param array $widget_b The second widget to compare .
* @ return int Reorder position for the current widget comparison .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
protected function _sort_name_callback ( $widget_a , $widget_b ) {
2014-03-26 18:29:15 -04:00
return strnatcasecmp ( $widget_a [ 'name' ], $widget_b [ 'name' ] );
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* Get the widget control markup .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param array $args Widget control arguments .
* @ return string Widget control form HTML markup .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function get_widget_control ( $args ) {
2014-03-05 15:41:14 -05:00
ob_start ();
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
call_user_func_array ( 'wp_widget_control' , $args );
$replacements = array (
'<form action="" method="post">' => '<div class="form">' ,
'</form>' => '</div><!-- .form -->' ,
);
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
$control_tpl = ob_get_clean ();
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
$control_tpl = str_replace ( array_keys ( $replacements ), array_values ( $replacements ), $control_tpl );
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
return $control_tpl ;
}
/**
2014-10-15 13:21:19 -04:00
* Add hooks for the Customizer preview .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function customize_preview_init () {
add_filter ( 'sidebars_widgets' , array ( $this , 'preview_sidebars_widgets' ), 1 );
add_action ( 'wp_enqueue_scripts' , array ( $this , 'customize_preview_enqueue' ) );
2014-04-06 14:54:14 -04:00
add_action ( 'wp_print_styles' , array ( $this , 'print_preview_css' ), 1 );
2014-03-28 10:07:14 -04:00
add_action ( 'wp_footer' , array ( $this , 'export_preview_data' ), 20 );
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* When previewing , make sure the proper previewing widgets are used .
2014-03-26 18:29:15 -04:00
*
2014-04-02 01:45:16 -04:00
* Because wp_get_sidebars_widgets () gets called early at init
* ( via wp_convert_widget_settings ()) and can set global variable
* $_wp_sidebars_widgets to the value of get_option ( 'sidebars_widgets' )
2014-10-15 13:21:19 -04:00
* before the Customizer preview filter is added , we have to reset
2014-04-02 01:45:16 -04:00
* it after the filter has been added .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param array $sidebars_widgets List of widgets for the current sidebar .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function preview_sidebars_widgets ( $sidebars_widgets ) {
2014-03-05 15:41:14 -05:00
$sidebars_widgets = get_option ( 'sidebars_widgets' );
2014-04-02 01:45:16 -04:00
2014-03-05 15:41:14 -05:00
unset ( $sidebars_widgets [ 'array_version' ] );
return $sidebars_widgets ;
}
/**
2014-04-02 01:45:16 -04:00
* Enqueue scripts for the Customizer preview .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function customize_preview_enqueue () {
2014-03-18 11:31:16 -04:00
wp_enqueue_script ( 'customize-preview-widgets' );
2014-03-28 10:07:14 -04:00
}
2014-03-05 15:41:14 -05:00
2014-03-18 11:21:15 -04:00
/**
* Insert default style for highlighted widget at early point so theme
* stylesheet can override .
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
2014-03-18 11:21:15 -04:00
* @ action wp_print_styles
*/
2014-04-06 14:54:14 -04:00
public function print_preview_css () {
2014-03-18 11:21:15 -04:00
?>
< style >
. widget - customizer - highlighted - widget {
outline : none ;
2014-03-28 09:33:14 -04:00
- webkit - box - shadow : 0 0 2 px rgba ( 30 , 140 , 190 , 0.8 );
box - shadow : 0 0 2 px rgba ( 30 , 140 , 190 , 0.8 );
2014-03-25 07:48:14 -04:00
position : relative ;
z - index : 1 ;
2014-03-18 11:21:15 -04:00
}
</ style >
< ? php
}
2014-03-05 15:41:14 -05:00
/**
2014-04-02 01:45:16 -04:00
* At the very end of the page , at the very end of the wp_footer ,
* communicate the sidebars that appeared on the page .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function export_preview_data () {
2014-04-02 02:12:16 -04:00
2014-12-01 19:31:22 -05:00
// Prepare Customizer settings to pass to JavaScript.
2014-03-22 17:04:15 -04:00
$settings = array (
2014-03-28 10:07:14 -04:00
'renderedSidebars' => array_fill_keys ( array_unique ( $this -> rendered_sidebars ), true ),
'renderedWidgets' => array_fill_keys ( array_keys ( $this -> rendered_widgets ), true ),
2014-03-22 17:04:15 -04:00
'registeredSidebars' => array_values ( $GLOBALS [ 'wp_registered_sidebars' ] ),
'registeredWidgets' => $GLOBALS [ 'wp_registered_widgets' ],
'l10n' => array (
2014-04-15 20:01:14 -04:00
'widgetTooltip' => __ ( 'Shift-click to edit this widget.' ),
2014-03-22 17:04:15 -04:00
),
);
foreach ( $settings [ 'registeredWidgets' ] as & $registered_widget ) {
unset ( $registered_widget [ 'callback' ] ); // may not be JSON-serializeable
}
2014-03-05 15:41:14 -05:00
?>
2014-03-22 17:04:15 -04:00
< script type = " text/javascript " >
2014-10-28 14:35:19 -04:00
var _wpWidgetCustomizerPreviewSettings = < ? php echo wp_json_encode ( $settings ); ?> ;
2014-03-05 15:41:14 -05:00
</ script >
< ? php
}
/**
2014-04-02 01:45:16 -04:00
* Keep track of the widgets that were rendered .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param array $widget Rendered widget to tally .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function tally_rendered_widgets ( $widget ) {
2014-07-09 19:58:16 -04:00
$this -> rendered_widgets [ $widget [ 'id' ] ] = true ;
}
/**
* Determine if a widget is rendered on the page .
*
* @ since 4.0 . 0
* @ access public
*
2014-07-13 20:42:15 -04:00
* @ param string $widget_id Widget ID to check .
* @ return bool Whether the widget is rendered .
2014-07-09 19:58:16 -04:00
*/
public function is_widget_rendered ( $widget_id ) {
return in_array ( $widget_id , $this -> rendered_widgets );
}
/**
* Determine if a sidebar is rendered on the page .
*
* @ since 4.0 . 0
* @ access public
*
2014-07-13 20:42:15 -04:00
* @ param string $sidebar_id Sidebar ID to check .
* @ return bool Whether the sidebar is rendered .
2014-07-09 19:58:16 -04:00
*/
public function is_sidebar_rendered ( $sidebar_id ) {
return in_array ( $sidebar_id , $this -> rendered_sidebars );
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* Tally the sidebars rendered via is_active_sidebar () .
*
* Keep track of the times that is_active_sidebar () is called
* in the template , and assume that this means that the sidebar
* would be rendered on the template if there were widgets
* populating it .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
2014-07-13 20:42:15 -04:00
* @ param bool $is_active Whether the sidebar is active .
* @ param string $sidebar_id Sidebar ID .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function tally_sidebars_via_is_active_sidebar_calls ( $is_active , $sidebar_id ) {
2014-03-05 15:41:14 -05:00
if ( isset ( $GLOBALS [ 'wp_registered_sidebars' ][ $sidebar_id ] ) ) {
2014-03-28 10:07:14 -04:00
$this -> rendered_sidebars [] = $sidebar_id ;
2014-03-05 15:41:14 -05:00
}
2014-04-02 01:45:16 -04:00
/*
* We may need to force this to true , and also force - true the value
* for 'dynamic_sidebar_has_widgets' if we want to ensure that there
* is an area to drop widgets into , if the sidebar is empty .
*/
2014-03-05 15:41:14 -05:00
return $is_active ;
}
/**
2014-04-02 01:45:16 -04:00
* Tally the sidebars rendered via dynamic_sidebar () .
*
* Keep track of the times that dynamic_sidebar () is called in the template ,
* and assume this means the sidebar would be rendered on the template if
* there were widgets populating it .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param bool $has_widgets Whether the current sidebar has widgets .
* @ param string $sidebar_id Sidebar ID .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function tally_sidebars_via_dynamic_sidebar_calls ( $has_widgets , $sidebar_id ) {
2014-03-05 15:41:14 -05:00
if ( isset ( $GLOBALS [ 'wp_registered_sidebars' ][ $sidebar_id ] ) ) {
2014-03-28 10:07:14 -04:00
$this -> rendered_sidebars [] = $sidebar_id ;
2014-03-05 15:41:14 -05:00
}
2014-04-02 01:45:16 -04:00
2014-03-26 18:29:15 -04:00
/*
2014-04-02 01:45:16 -04:00
* We may need to force this to true , and also force - true the value
* for 'is_active_sidebar' if we want to ensure there is an area to
* drop widgets into , if the sidebar is empty .
2014-03-26 18:29:15 -04:00
*/
2014-03-05 15:41:14 -05:00
return $has_widgets ;
}
/**
2014-08-05 02:50:15 -04:00
* Get MAC for a serialized widget instance string .
2014-03-26 18:29:15 -04:00
*
2014-08-05 02:50:15 -04:00
* Allows values posted back from JS to be rejected if any tampering of the
* data has occurred .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access protected
*
2014-08-05 02:50:15 -04:00
* @ param string $serialized_instance Widget instance .
* @ return string MAC for serialized widget instance .
2014-03-05 15:41:14 -05:00
*/
2014-08-05 02:50:15 -04:00
protected function get_instance_hash_key ( $serialized_instance ) {
return wp_hash ( $serialized_instance );
2014-03-05 15:41:14 -05:00
}
/**
2014-03-26 18:29:15 -04:00
* Sanitize a widget instance .
*
2014-03-05 15:41:14 -05:00
* Unserialize the JS - instance for storing in the options . It ' s important
* that this filter only get applied to an instance once .
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param array $value Widget instance to sanitize .
* @ return array Sanitized widget instance .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function sanitize_widget_instance ( $value ) {
2014-03-05 15:41:14 -05:00
if ( $value === array () ) {
return $value ;
}
2014-04-02 02:12:16 -04:00
if ( empty ( $value [ 'is_widget_customizer_js_value' ] )
|| empty ( $value [ 'instance_hash_key' ] )
|| empty ( $value [ 'encoded_serialized_instance' ] ) )
{
2014-03-05 15:41:14 -05:00
return null ;
}
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
$decoded = base64_decode ( $value [ 'encoded_serialized_instance' ], true );
if ( false === $decoded ) {
return null ;
}
2014-04-02 02:12:16 -04:00
2015-08-04 00:52:35 -04:00
if ( ! hash_equals ( $this -> get_instance_hash_key ( $decoded ), $value [ 'instance_hash_key' ] ) ) {
2014-03-05 15:41:14 -05:00
return null ;
}
2014-08-05 02:50:15 -04:00
$instance = unserialize ( $decoded );
if ( false === $instance ) {
2014-03-05 15:41:14 -05:00
return null ;
}
2014-08-05 02:50:15 -04:00
2014-03-05 15:41:14 -05:00
return $instance ;
}
/**
2014-03-26 18:29:15 -04:00
* Convert widget instance into JSON - representable format .
*
* @ since 3.9 . 0
* @ access public
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ param array $value Widget instance to convert to JSON .
* @ return array JSON - converted widget instance .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function sanitize_widget_js_instance ( $value ) {
2014-03-05 15:41:14 -05:00
if ( empty ( $value [ 'is_widget_customizer_js_value' ] ) ) {
$serialized = serialize ( $value );
2014-04-02 02:12:16 -04:00
2014-03-05 15:41:14 -05:00
$value = array (
2014-04-02 02:12:16 -04:00
'encoded_serialized_instance' => base64_encode ( $serialized ),
'title' => empty ( $value [ 'title' ] ) ? '' : $value [ 'title' ],
2014-03-05 15:41:14 -05:00
'is_widget_customizer_js_value' => true ,
2014-08-05 02:50:15 -04:00
'instance_hash_key' => $this -> get_instance_hash_key ( $serialized ),
2014-03-05 15:41:14 -05:00
);
}
return $value ;
}
/**
2014-04-02 01:45:16 -04:00
* Strip out widget IDs for widgets which are no longer registered .
*
* One example where this might happen is when a plugin orphans a widget
* in a sidebar upon deactivation .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param array $widget_ids List of widget IDs .
* @ return array Parsed list of widget IDs .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function sanitize_sidebar_widgets_js_instance ( $widget_ids ) {
2014-03-05 15:41:14 -05:00
global $wp_registered_widgets ;
$widget_ids = array_values ( array_intersect ( $widget_ids , array_keys ( $wp_registered_widgets ) ) );
return $widget_ids ;
}
/**
2014-03-26 18:29:15 -04:00
* Find and invoke the widget update and control callbacks .
*
* Requires that $_POST be populated with the instance data .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
* @ param string $widget_id Widget ID .
2014-04-02 01:45:16 -04:00
* @ return WP_Error | array Array containing the updated widget information .
* A WP_Error object , otherwise .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function call_widget_update ( $widget_id ) {
2014-03-05 15:41:14 -05:00
global $wp_registered_widget_updates , $wp_registered_widget_controls ;
2014-03-28 10:07:14 -04:00
$this -> start_capturing_option_updates ();
$parsed_id = $this -> parse_widget_id ( $widget_id );
2014-03-22 16:55:18 -04:00
$option_name = 'widget_' . $parsed_id [ 'id_base' ];
2014-03-05 15:41:14 -05:00
2014-03-26 18:29:15 -04:00
/*
2014-03-22 16:55:18 -04:00
* If a previously - sanitized instance is provided , populate the input vars
* with its values so that the widget update callback will read this instance
*/
$added_input_vars = array ();
if ( ! empty ( $_POST [ 'sanitized_widget_setting' ] ) ) {
2014-03-28 10:07:14 -04:00
$sanitized_widget_setting = json_decode ( $this -> get_post_value ( 'sanitized_widget_setting' ), true );
2014-04-08 04:12:15 -04:00
if ( false === $sanitized_widget_setting ) {
2014-03-28 10:07:14 -04:00
$this -> stop_capturing_option_updates ();
2014-03-29 17:44:14 -04:00
return new WP_Error ( 'widget_setting_malformed' );
2014-03-05 15:41:14 -05:00
}
2014-03-28 10:07:14 -04:00
$instance = $this -> sanitize_widget_instance ( $sanitized_widget_setting );
2014-03-22 16:55:18 -04:00
if ( is_null ( $instance ) ) {
2014-03-28 10:07:14 -04:00
$this -> stop_capturing_option_updates ();
2014-03-29 17:44:14 -04:00
return new WP_Error ( 'widget_setting_unsanitized' );
2014-03-05 15:41:14 -05:00
}
2014-03-22 16:55:18 -04:00
if ( ! is_null ( $parsed_id [ 'number' ] ) ) {
$value = array ();
$value [ $parsed_id [ 'number' ]] = $instance ;
$key = 'widget-' . $parsed_id [ 'id_base' ];
$_REQUEST [ $key ] = $_POST [ $key ] = wp_slash ( $value );
$added_input_vars [] = $key ;
} else {
foreach ( $instance as $key => $value ) {
$_REQUEST [ $key ] = $_POST [ $key ] = wp_slash ( $value );
$added_input_vars [] = $key ;
}
2014-03-05 15:41:14 -05:00
}
2014-03-22 16:55:18 -04:00
}
2014-03-05 15:41:14 -05:00
2014-03-26 18:29:15 -04:00
// Invoke the widget update callback.
2014-03-22 16:55:18 -04:00
foreach ( ( array ) $wp_registered_widget_updates as $name => $control ) {
if ( $name === $parsed_id [ 'id_base' ] && is_callable ( $control [ 'callback' ] ) ) {
ob_start ();
call_user_func_array ( $control [ 'callback' ], $control [ 'params' ] );
ob_end_clean ();
break ;
2014-03-05 15:41:14 -05:00
}
2014-03-22 16:55:18 -04:00
}
2014-03-05 15:41:14 -05:00
2014-03-22 16:55:18 -04:00
// Clean up any input vars that were manually added
foreach ( $added_input_vars as $key ) {
unset ( $_POST [ $key ] );
unset ( $_REQUEST [ $key ] );
}
2014-03-26 18:29:15 -04:00
// Make sure the expected option was updated.
2014-03-28 10:07:14 -04:00
if ( 0 !== $this -> count_captured_options () ) {
if ( $this -> count_captured_options () > 1 ) {
$this -> stop_capturing_option_updates ();
2014-03-29 17:44:14 -04:00
return new WP_Error ( 'widget_setting_too_many_options' );
2014-03-05 15:41:14 -05:00
}
2014-03-28 10:07:14 -04:00
$updated_option_name = key ( $this -> get_captured_options () );
2014-03-22 16:55:18 -04:00
if ( $updated_option_name !== $option_name ) {
2014-03-28 10:07:14 -04:00
$this -> stop_capturing_option_updates ();
2014-03-29 17:44:14 -04:00
return new WP_Error ( 'widget_setting_unexpected_option' );
2014-03-05 15:41:14 -05:00
}
2014-03-22 16:55:18 -04:00
}
2014-03-05 15:41:14 -05:00
2014-03-26 18:29:15 -04:00
// Obtain the widget control with the updated instance in place.
2014-03-22 16:55:18 -04:00
ob_start ();
2014-04-02 02:12:16 -04:00
2014-03-22 16:55:18 -04:00
$form = $wp_registered_widget_controls [ $widget_id ];
if ( $form ) {
call_user_func_array ( $form [ 'callback' ], $form [ 'params' ] );
2014-03-05 15:41:14 -05:00
}
2014-04-02 02:12:16 -04:00
2014-03-22 16:55:18 -04:00
$form = ob_get_clean ();
2014-03-26 18:29:15 -04:00
// Obtain the widget instance.
2014-03-22 16:55:18 -04:00
$option = get_option ( $option_name );
2014-04-02 02:12:16 -04:00
2014-03-22 16:55:18 -04:00
if ( null !== $parsed_id [ 'number' ] ) {
$instance = $option [ $parsed_id [ 'number' ]];
} else {
$instance = $option ;
2014-03-05 15:41:14 -05:00
}
2014-03-22 16:55:18 -04:00
2014-03-28 10:07:14 -04:00
$this -> stop_capturing_option_updates ();
2014-04-02 02:12:16 -04:00
2014-03-22 16:55:18 -04:00
return compact ( 'instance' , 'form' );
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* Update widget settings asynchronously .
*
* Allows the Customizer to update a widget using its form , but return the new
2014-03-05 15:41:14 -05:00
* instance info via Ajax instead of saving it to the options table .
2014-04-02 01:45:16 -04:00
*
2014-03-05 15:41:14 -05:00
* Most code here copied from wp_ajax_save_widget ()
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
* @ access public
*
2014-04-02 01:45:16 -04:00
* @ see wp_ajax_save_widget ()
*
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function wp_ajax_update_widget () {
2014-03-05 15:41:14 -05:00
2014-03-22 16:55:18 -04:00
if ( ! is_user_logged_in () ) {
wp_die ( 0 );
}
2014-03-05 15:41:14 -05:00
2014-03-28 11:35:15 -04:00
check_ajax_referer ( 'update-widget' , 'nonce' );
2014-03-22 16:55:18 -04:00
if ( ! current_user_can ( 'edit_theme_options' ) ) {
wp_die ( - 1 );
}
2014-03-05 15:41:14 -05:00
2014-03-22 16:55:18 -04:00
if ( ! isset ( $_POST [ 'widget-id' ] ) ) {
wp_send_json_error ();
}
2014-03-05 15:41:14 -05:00
2014-04-02 01:45:16 -04:00
/** This action is documented in wp-admin/includes/ajax-actions.php */
2014-03-22 16:55:18 -04:00
do_action ( 'load-widgets.php' );
2014-04-02 01:45:16 -04:00
/** This action is documented in wp-admin/includes/ajax-actions.php */
2014-03-22 16:55:18 -04:00
do_action ( 'widgets.php' );
2014-03-28 15:47:15 -04:00
/** This action is documented in wp-admin/widgets.php */
2014-03-22 16:55:18 -04:00
do_action ( 'sidebar_admin_setup' );
2014-03-05 15:41:14 -05:00
2014-03-28 10:07:14 -04:00
$widget_id = $this -> get_post_value ( 'widget-id' );
$parsed_id = $this -> parse_widget_id ( $widget_id );
2014-03-22 16:55:18 -04:00
$id_base = $parsed_id [ 'id_base' ];
2014-03-05 15:41:14 -05:00
2014-03-22 16:55:18 -04:00
if ( isset ( $_POST [ 'widget-' . $id_base ] ) && is_array ( $_POST [ 'widget-' . $id_base ] ) && preg_match ( '/__i__|%i%/' , key ( $_POST [ 'widget-' . $id_base ] ) ) ) {
wp_send_json_error ();
2014-03-05 15:41:14 -05:00
}
2014-03-22 16:55:18 -04:00
2014-03-28 10:07:14 -04:00
$updated_widget = $this -> call_widget_update ( $widget_id ); // => {instance,form}
2014-03-22 16:55:18 -04:00
if ( is_wp_error ( $updated_widget ) ) {
wp_send_json_error ();
2014-03-05 15:41:14 -05:00
}
2014-03-22 16:55:18 -04:00
$form = $updated_widget [ 'form' ];
2014-03-28 10:07:14 -04:00
$instance = $this -> sanitize_widget_js_instance ( $updated_widget [ 'instance' ] );
2014-03-22 16:55:18 -04:00
wp_send_json_success ( compact ( 'form' , 'instance' ) );
2014-03-05 15:41:14 -05:00
}
2014-03-28 10:07:14 -04:00
/***************************************************************************
* Option Update Capturing
***************************************************************************/
2014-03-05 15:41:14 -05:00
/**
2014-04-02 01:45:16 -04:00
* List of captured widget option updates .
*
* @ since 3.9 . 0
* @ access protected
* @ var array $_captured_options Values updated while option capture is happening .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
protected $_captured_options = array ();
2014-03-05 15:41:14 -05:00
/**
2014-04-02 01:45:16 -04:00
* Whether option capture is currently happening .
*
* @ since 3.9 . 0
* @ access protected
* @ var bool $_is_current Whether option capture is currently happening or not .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
protected $_is_capturing_option_updates = false ;
2014-03-05 15:41:14 -05:00
/**
2014-04-02 01:45:16 -04:00
* Determine whether the captured option update should be ignored .
*
* @ since 3.9 . 0
* @ access protected
*
* @ param string $option_name Option name .
* @ return boolean Whether the option capture is ignored .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
protected function is_option_capture_ignored ( $option_name ) {
return ( 0 === strpos ( $option_name , '_transient_' ) );
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* Retrieve captured widget option updates .
*
* @ since 3.9 . 0
* @ access protected
*
* @ return array Array of captured options .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
protected function get_captured_options () {
return $this -> _captured_options ;
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* Get the number of captured widget option updates .
*
* @ since 3.9 . 0
* @ access protected
*
* @ return int Number of updated options .
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
protected function count_captured_options () {
return count ( $this -> _captured_options );
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* Start keeping track of changes to widget options , caching new values .
*
* @ since 3.9 . 0
* @ access protected
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
protected function start_capturing_option_updates () {
if ( $this -> _is_capturing_option_updates ) {
2014-03-05 15:41:14 -05:00
return ;
}
2014-03-28 10:07:14 -04:00
$this -> _is_capturing_option_updates = true ;
2014-04-02 02:12:16 -04:00
2014-04-02 14:31:15 -04:00
add_filter ( 'pre_update_option' , array ( $this , 'capture_filter_pre_update_option' ), 10 , 3 );
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* Pre - filter captured option values before updating .
*
2014-04-02 02:12:16 -04:00
* @ since 3.9 . 0
* @ access public
*
2014-03-28 10:07:14 -04:00
* @ param mixed $new_value
2014-03-05 15:41:14 -05:00
* @ param string $option_name
* @ param mixed $old_value
2014-03-28 10:07:14 -04:00
* @ return mixed
2014-03-05 15:41:14 -05:00
*/
2014-04-02 14:31:15 -04:00
public function capture_filter_pre_update_option ( $new_value , $option_name , $old_value ) {
2014-03-28 10:07:14 -04:00
if ( $this -> is_option_capture_ignored ( $option_name ) ) {
2014-03-05 15:41:14 -05:00
return ;
}
2014-03-28 10:07:14 -04:00
if ( ! isset ( $this -> _captured_options [ $option_name ] ) ) {
2014-04-02 14:31:15 -04:00
add_filter ( " pre_option_ { $option_name } " , array ( $this , 'capture_filter_pre_get_option' ) );
2014-03-28 10:07:14 -04:00
}
$this -> _captured_options [ $option_name ] = $new_value ;
return $old_value ;
}
2014-03-05 15:41:14 -05:00
/**
2014-04-02 01:45:16 -04:00
* Pre - filter captured option values before retrieving .
*
2014-04-02 02:12:16 -04:00
* @ since 3.9 . 0
* @ access public
*
2014-04-02 01:45:16 -04:00
* @ param mixed $value Option
2014-03-28 10:07:14 -04:00
* @ return mixed
2014-03-05 15:41:14 -05:00
*/
2014-04-02 14:31:15 -04:00
public function capture_filter_pre_get_option ( $value ) {
2014-03-28 10:07:14 -04:00
$option_name = preg_replace ( '/^pre_option_/' , '' , current_filter () );
2014-04-02 02:12:16 -04:00
2014-03-28 10:07:14 -04:00
if ( isset ( $this -> _captured_options [ $option_name ] ) ) {
$value = $this -> _captured_options [ $option_name ];
2014-04-14 14:41:17 -04:00
/** This filter is documented in wp-includes/option.php */
2014-03-28 10:07:14 -04:00
$value = apply_filters ( 'option_' . $option_name , $value );
2014-03-05 15:41:14 -05:00
}
2014-03-28 10:07:14 -04:00
return $value ;
2014-03-05 15:41:14 -05:00
}
/**
2014-04-02 01:45:16 -04:00
* Undo any changes to the options since options capture began .
*
* @ since 3.9 . 0
* @ access protected
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
protected function stop_capturing_option_updates () {
if ( ! $this -> _is_capturing_option_updates ) {
2014-03-05 15:41:14 -05:00
return ;
}
2014-04-02 14:31:15 -04:00
remove_filter ( 'pre_update_option' , array ( $this , 'capture_filter_pre_update_option' ), 10 , 3 );
2014-03-28 10:07:14 -04:00
foreach ( array_keys ( $this -> _captured_options ) as $option_name ) {
2014-04-02 14:31:15 -04:00
remove_filter ( " pre_option_ { $option_name } " , array ( $this , 'capture_filter_pre_get_option' ) );
2014-03-05 15:41:14 -05:00
}
2014-03-28 10:07:14 -04:00
$this -> _captured_options = array ();
$this -> _is_capturing_option_updates = false ;
2014-03-05 15:41:14 -05:00
}
}