2014-03-05 15:41:14 -05:00
< ? php
/**
2015-02-25 03:20:26 -05:00
* WordPress Customize Widgets classes
2014-03-26 18:29:15 -04:00
*
* @ package WordPress
* @ subpackage Customize
2014-03-28 10:07:14 -04:00
* @ since 3.9 . 0
2014-03-05 15:41:14 -05:00
*/
2015-02-25 03:20:26 -05:00
/**
* Customize Widgets class .
*
* Implements widget management in the Customizer .
*
* @ since 3.9 . 0
*
* @ see WP_Customize_Manager
*/
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 array
*/
2015-02-08 18:11:25 -05:00
protected $rendered_sidebars = array ();
2014-03-26 18:29:15 -04:00
/**
* @ since 3.9 . 0
* @ access protected
* @ var array
*/
2015-02-08 18:11:25 -05:00
protected $rendered_widgets = array ();
2014-03-26 18:29:15 -04:00
/**
* @ since 3.9 . 0
* @ access protected
* @ var array
*/
2015-02-08 18:11:25 -05:00
protected $old_sidebars_widgets = array ();
2014-03-26 18:29:15 -04:00
2014-04-14 18:46:16 -04:00
/**
2015-02-08 18:11:25 -05:00
* Mapping of setting type to setting ID pattern .
*
* @ since 4.2 . 0
2014-04-14 18:46:16 -04:00
* @ access protected
* @ var array
*/
2015-02-08 18:11:25 -05:00
protected $setting_id_patterns = array (
'widget_instance' => '/^(widget_.+?)(?:\[(\d+)\])?$/' ,
'sidebar_widgets' => '/^sidebars_widgets\[(.+?)\]$/' ,
);
2014-04-14 18:46:16 -04:00
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 ;
2015-02-08 18:11:25 -05:00
add_filter ( 'customize_dynamic_setting_args' , array ( $this , 'filter_customize_dynamic_setting_args' ), 10 , 2 );
add_action ( 'after_setup_theme' , array ( $this , 'register_settings' ) );
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' ) );
2015-04-06 11:10:27 -04:00
add_filter ( 'customize_refresh_nonces' , array ( $this , 'refresh_nonces' ) );
2014-03-28 10:07:14 -04:00
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
}
/**
2015-02-08 18:11:25 -05:00
* Get the widget setting type given a setting ID .
2014-03-26 18:29:15 -04:00
*
2015-02-08 18:11:25 -05:00
* @ since 4.2 . 0
2015-04-05 11:19:28 -04:00
* @ access protected
2014-03-26 18:29:15 -04:00
*
2015-05-29 11:43:29 -04:00
* @ staticvar array $cache
*
2015-04-05 11:19:28 -04:00
* @ param $setting_id Setting ID .
2015-05-24 01:40:25 -04:00
* @ return string | void Setting type .
2014-03-05 15:41:14 -05:00
*/
2015-02-08 18:11:25 -05:00
protected function get_setting_type ( $setting_id ) {
static $cache = array ();
if ( isset ( $cache [ $setting_id ] ) ) {
return $cache [ $setting_id ];
2014-03-05 15:41:14 -05:00
}
2015-02-08 18:11:25 -05:00
foreach ( $this -> setting_id_patterns as $type => $pattern ) {
if ( preg_match ( $pattern , $setting_id ) ) {
$cache [ $setting_id ] = $type ;
return $type ;
}
}
2014-03-05 15:41:14 -05:00
}
/**
2015-02-08 18:11:25 -05:00
* Inspect the incoming customized data for any widget settings , and dynamically add them up - front so widgets will be initialized properly .
2014-03-26 18:29:15 -04:00
*
2015-02-08 18:11:25 -05:00
* @ since 4.2 . 0
2015-04-05 11:36:26 -04:00
* @ access public
2014-03-05 15:41:14 -05:00
*/
2015-02-08 18:11:25 -05:00
public function register_settings () {
$widget_setting_ids = array ();
$incoming_setting_ids = array_keys ( $this -> manager -> unsanitized_post_values () );
foreach ( $incoming_setting_ids as $setting_id ) {
if ( ! is_null ( $this -> get_setting_type ( $setting_id ) ) ) {
$widget_setting_ids [] = $setting_id ;
2014-03-05 15:41:14 -05:00
}
}
2015-02-08 18:11:25 -05:00
if ( $this -> manager -> doing_ajax ( 'update-widget' ) && isset ( $_REQUEST [ 'widget-id' ] ) ) {
$widget_setting_ids [] = $this -> get_setting_id ( wp_unslash ( $_REQUEST [ 'widget-id' ] ) );
}
2014-03-05 15:41:14 -05:00
2015-02-08 18:11:25 -05:00
$settings = $this -> manager -> add_dynamic_settings ( array_unique ( $widget_setting_ids ) );
2014-03-05 15:41:14 -05:00
2015-02-08 18:11:25 -05:00
/*
* Preview settings right away so that widgets and sidebars will get registered properly .
* But don ' t do this if a customize_save because this will cause WP to think there is nothing
* changed that needs to be saved .
*/
if ( ! $this -> manager -> doing_ajax ( 'customize_save' ) ) {
foreach ( $settings as $setting ) {
$setting -> preview ();
2014-03-05 15:41:14 -05:00
}
}
}
/**
2015-02-08 18:11:25 -05:00
* Determine the arguments for a dynamically - created setting .
2014-04-02 01:45:16 -04:00
*
2015-02-08 18:11:25 -05:00
* @ since 4.2 . 0
2015-04-05 11:36:26 -04:00
* @ access public
2014-03-05 15:41:14 -05:00
*
2015-04-05 11:36:26 -04:00
* @ 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']` .
* @ return false | array Setting arguments , false otherwise .
2014-03-05 15:41:14 -05:00
*/
2015-02-08 18:11:25 -05:00
public function filter_customize_dynamic_setting_args ( $args , $setting_id ) {
if ( $this -> get_setting_type ( $setting_id ) ) {
$args = $this -> get_setting_args ( $setting_id );
2014-03-05 15:41:14 -05:00
}
2015-02-08 18:11:25 -05:00
return $args ;
2014-03-05 15:41:14 -05:00
}
/**
2015-02-08 18:11:25 -05:00
* Get an unslashed post value or return a default .
2014-03-05 15:41:14 -05:00
*
2014-03-26 18:29:15 -04:00
* @ since 3.9 . 0
*
2015-02-08 18:11:25 -05:00
* @ access protected
2014-03-05 15:41:14 -05:00
*
2015-02-08 18:11:25 -05: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
*/
2015-02-08 18:11:25 -05:00
protected function get_post_value ( $name , $default = null ) {
if ( ! isset ( $_POST [ $name ] ) ) {
return $default ;
2014-03-05 15:41:14 -05:00
}
2015-02-08 18:11:25 -05:00
return wp_unslash ( $_POST [ $name ] );
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
2015-05-22 01:06:25 -04:00
*
* @ global array $sidebars_widgets
* @ global array $_wp_sidebars_widgets
2014-04-14 18:46:16 -04:00
*/
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 );
2015-05-22 01:06:25 -04:00
// reset global cache var used by wp_get_sidebars_widgets()
unset ( $GLOBALS [ '_wp_sidebars_widgets' ] );
2014-04-14 18:46:16 -04:00
}
/**
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
2015-05-21 18:05:24 -04:00
* @ return array
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
*
2015-05-22 01:06:25 -04:00
* @ global array $sidebars_widgets
*
2014-04-14 18:46:16 -04:00
* @ param array $sidebars_widgets
2015-05-21 18:05:24 -04:00
* @ return array
2014-04-14 18:46:16 -04:00
*/
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 () {
2015-02-08 18:11:25 -05:00
if ( is_admin () ) {
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
2015-05-22 01:06:25 -04:00
*
* @ global array $wp_registered_widgets
* @ global array $wp_registered_widget_controls
* @ global array $wp_registered_sidebars
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 () ),
2015-05-22 01:06:25 -04:00
array_fill_keys ( array_keys ( $wp_registered_sidebars ), array () ),
2014-03-05 15:41:14 -05:00
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 );
2015-02-08 18:11:25 -05:00
if ( ! $this -> manager -> get_setting ( $setting_id ) ) {
$this -> manager -> add_setting ( $setting_id , $setting_args );
}
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' ,
2015-03-10 18:39:28 -04:00
'dirty' => true ,
2014-04-14 18:46:16 -04:00
) );
$this -> manager -> add_setting ( $setting_id , $setting_args );
}
2014-06-26 16:17:15 -04:00
$this -> manager -> add_panel ( 'widgets' , array (
2015-10-16 19:48:25 -04:00
'type' => 'widgets' ,
'title' => __ ( 'Widgets' ),
'description' => __ ( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ),
'priority' => 110 ,
'active_callback' => array ( $this , 'is_panel_active' ),
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
2015-10-12 21:33:25 -04:00
$is_registered_sidebar = is_registered_sidebar ( $sidebar_id );
2014-03-05 15:41:14 -05:00
$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 );
2015-02-08 18:11:25 -05:00
if ( ! $this -> manager -> get_setting ( $setting_id ) ) {
2015-03-10 18:39:28 -04:00
if ( ! $this -> manager -> is_theme_active () ) {
$setting_args [ 'dirty' ] = true ;
}
2015-02-08 18:11:25 -05: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 (
2015-05-22 01:06:25 -04:00
'title' => $wp_registered_sidebars [ $sidebar_id ][ 'name' ],
'description' => $wp_registered_sidebars [ $sidebar_id ][ 'description' ],
2014-06-26 16:17:15 -04:00
'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.
2015-05-22 01:06:25 -04:00
if ( ! $is_active_sidebar || ! isset ( $wp_registered_widgets [ $widget_id ] ) ) {
2014-03-05 15:41:14 -05:00
continue ;
}
2014-04-02 02:12:16 -04:00
2015-05-22 01:06:25 -04:00
$registered_widget = $wp_registered_widgets [ $widget_id ];
2014-04-02 02:12:16 -04:00
$setting_id = $this -> get_setting_id ( $widget_id );
2015-05-22 01:06:25 -04:00
$id_base = $wp_registered_widget_controls [ $widget_id ][ 'id_base' ];
2014-04-02 02:12:16 -04:00
$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
}
}
2015-02-08 18:11:25 -05:00
if ( ! $this -> manager -> doing_ajax ( 'customize_save' ) ) {
2014-03-05 15:41:14 -05:00
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
}
}
2015-02-08 18:11:25 -05:00
add_filter ( 'sidebars_widgets' , array ( $this , 'preview_sidebars_widgets' ), 1 );
2014-03-05 15:41:14 -05:00
}
2015-10-16 19:48:25 -04:00
/**
* Return whether the widgets panel is active , based on whether there are sidebars registered .
*
* @ since 4.4 . 0
* @ access public
*
* @ see WP_Customize_Panel :: $active_callback
*
* @ global array $wp_registered_sidebars
* @ return bool Active .
*/
public function is_panel_active () {
global $wp_registered_sidebars ;
return ! empty ( $wp_registered_sidebars );
}
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
*
2015-05-22 01:06:25 -04:00
* @ global $wp_registered_widget_controls
*
2014-03-26 18:29:15 -04:00
* @ 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
2015-05-22 01:06:25 -04:00
*
* @ global WP_Scripts $wp_scripts
* @ global array $wp_registered_sidebars
* @ global array $wp_registered_widgets
2014-03-05 15:41:14 -05:00
*/
2014-04-02 13:04:14 -04:00
public function enqueue_scripts () {
2015-05-22 01:06:25 -04:00
global $wp_scripts , $wp_registered_sidebars , $wp_registered_widgets ;
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
);
2014-04-07 05:04:14 -04:00
$settings = array (
'nonce' => wp_create_nonce ( 'update-widget' ),
2015-05-22 01:06:25 -04:00
'registeredSidebars' => array_values ( $wp_registered_sidebars ),
'registeredWidgets' => $wp_registered_widgets ,
2014-04-07 05:04:14 -04:00
'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' ),
2015-10-16 19:48:25 -04:00
'noAreasRendered' => __ ( 'There are no widget areas currently rendered in the preview. Navigate in the preview to a template that makes use of a widget area in order to access its widgets here.' ),
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 " >
2015-05-29 09:57:26 -04:00
< div class = " customize-section-title " >
< button class = " customize-section-back " tabindex = " -1 " >
< span class = " screen-reader-text " >< ? php _e ( 'Back' ); ?> </span>
</ button >
< h3 >
< span class = " customize-action " >< ? php
/* translators: ▸ is the unicode right-pointing triangle, and %s is the section title in the Customizer */
echo sprintf ( __ ( 'Customizing ▸ %s' ), esc_html ( $this -> manager -> get_panel ( 'widgets' ) -> title ) );
?> </span>
< ? php _e ( 'Add a Widget' ); ?>
</ h3 >
</ div >
2014-03-05 15:41:14 -05:00
< 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 >
2015-04-21 10:15:26 -04:00
< div id = " available-widgets-list " >
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 ; ?>
2015-04-21 10:15:26 -04:00
</ div ><!-- #available-widgets-list -->
2014-03-05 15:41:14 -05:00
</ 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
);
2015-02-08 18:11:25 -05:00
if ( preg_match ( $this -> setting_id_patterns [ 'sidebar_widgets' ], $id , $matches ) ) {
$args [ 'sanitize_callback' ] = array ( $this , 'sanitize_sidebar_widgets' );
$args [ 'sanitize_js_callback' ] = array ( $this , 'sanitize_sidebar_widgets_js_instance' );
2015-06-19 18:01:25 -04:00
} elseif ( preg_match ( $this -> setting_id_patterns [ 'widget_instance' ], $id , $matches ) ) {
2015-02-08 18:11:25 -05:00
$args [ 'sanitize_callback' ] = array ( $this , 'sanitize_widget_instance' );
$args [ 'sanitize_js_callback' ] = array ( $this , 'sanitize_widget_js_instance' );
}
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 ) {
2015-02-08 18:11:25 -05:00
$widget_ids = array_map ( 'strval' , ( array ) $widget_ids );
2014-03-05 15:41:14 -05:00
$sanitized_widget_ids = array ();
foreach ( $widget_ids as $widget_id ) {
2015-02-08 18:11:25 -05:00
$sanitized_widget_ids [] = preg_replace ( '/[^a-z0-9_\-]/' , '' , $widget_id );
2014-03-05 15:41:14 -05:00
}
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
*
2015-05-22 01:06:25 -04:00
* @ global array $wp_registered_widgets
* @ global array $wp_registered_widget_controls
* @ staticvar array $available_widgets
*
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
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 ) {
2015-09-25 17:02:27 -04:00
$args [ 0 ][ 'before_form' ] = '<div class="form">' ;
$args [ 0 ][ 'after_form' ] = '</div><!-- .form -->' ;
$args [ 0 ][ 'before_widget_content' ] = '<div class="widget-content">' ;
$args [ 0 ][ 'after_widget_content' ] = '</div><!-- .widget-content -->' ;
2014-03-05 15:41:14 -05:00
ob_start ();
call_user_func_array ( 'wp_widget_control' , $args );
$control_tpl = ob_get_clean ();
2015-09-25 17:02:27 -04:00
return $control_tpl ;
}
2014-04-02 02:12:16 -04:00
2015-09-25 17:02:27 -04:00
/**
* Get the widget control markup parts .
*
* @ since 4.4 . 0
* @ access public
*
* @ param array $args Widget control arguments .
* @ return array {
* @ type string $control Markup for widget control wrapping form .
* @ type string $content The contents of the widget form itself .
* }
*/
public function get_widget_control_parts ( $args ) {
$args [ 0 ][ 'before_widget_content' ] = '<div class="widget-content">' ;
$args [ 0 ][ 'after_widget_content' ] = '</div><!-- .widget-content -->' ;
$control_markup = $this -> get_widget_control ( $args );
$content_start_pos = strpos ( $control_markup , $args [ 0 ][ 'before_widget_content' ] );
$content_end_pos = strrpos ( $control_markup , $args [ 0 ][ 'after_widget_content' ] );
$control = substr ( $control_markup , 0 , $content_start_pos + strlen ( $args [ 0 ][ 'before_widget_content' ] ) );
$control .= substr ( $control_markup , $content_end_pos );
$content = trim ( substr (
$control_markup ,
$content_start_pos + strlen ( $args [ 0 ][ 'before_widget_content' ] ),
$content_end_pos - $content_start_pos - strlen ( $args [ 0 ][ 'before_widget_content' ] )
) );
2014-04-02 02:12:16 -04:00
2015-09-25 17:02:27 -04:00
return compact ( 'control' , 'content' );
2014-03-05 15:41:14 -05:00
}
/**
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_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
}
2015-04-06 11:10:27 -04:00
/**
* Refresh nonce for widget updates .
*
* @ since 4.2 . 0
* @ access public
*
* @ param array $nonces Array of nonces .
* @ return array $nonces Array of nonces .
*/
public function refresh_nonces ( $nonces ) {
$nonces [ 'update-widget' ] = wp_create_nonce ( 'update-widget' );
return $nonces ;
}
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 .
2015-05-21 18:05:24 -04:00
* @ return array
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
2015-05-22 01:06:25 -04:00
*
* @ global array $wp_registered_sidebars
* @ global array $wp_registered_widgets
2014-03-05 15:41:14 -05:00
*/
2014-03-28 10:07:14 -04:00
public function export_preview_data () {
2015-05-22 01:06:25 -04:00
global $wp_registered_sidebars , $wp_registered_widgets ;
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 ),
2015-05-22 01:06:25 -04:00
'registeredSidebars' => array_values ( $wp_registered_sidebars ),
'registeredWidgets' => $wp_registered_widgets ,
2014-03-22 17:04:15 -04:00
'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 .
2015-05-21 18:05:24 -04:00
* @ return bool
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 ) {
2015-10-12 21:33:25 -04:00
if ( is_registered_sidebar ( $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 .
2015-05-21 18:05:24 -04:00
* @ return bool
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 ) {
2015-10-12 21:33:25 -04:00
if ( is_registered_sidebar ( $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 .
2015-05-24 01:40:25 -04:00
* @ return array | void 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' ] ) )
{
2015-05-21 18:05:24 -04:00
return ;
2014-03-05 15:41:14 -05:00
}
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 ) {
2015-05-21 18:05:24 -04:00
return ;
2014-03-05 15:41:14 -05:00
}
2014-04-02 02:12:16 -04:00
2015-08-04 00:51:50 -04:00
if ( ! hash_equals ( $this -> get_instance_hash_key ( $decoded ), $value [ 'instance_hash_key' ] ) ) {
2015-05-21 18:05:24 -04:00
return ;
2014-03-05 15:41:14 -05:00
}
2014-08-05 02:50:15 -04:00
$instance = unserialize ( $decoded );
if ( false === $instance ) {
2015-05-21 18:05:24 -04:00
return ;
2014-03-05 15:41:14 -05:00
}
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
*
2015-05-22 01:06:25 -04:00
* @ global array $wp_registered_widgets
*
2014-03-26 18:29:15 -04:00
* @ 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
*
2015-05-22 01:06:25 -04:00
* @ global array $wp_registered_widget_updates
* @ global array $wp_registered_widget_controls
*
2014-03-26 18:29:15 -04:00
* @ 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 ;
2015-07-29 12:03:24 -04:00
$setting_id = $this -> get_setting_id ( $widget_id );
/*
* Make sure that other setting changes have previewed since this widget
* may depend on them ( e . g . Menus being present for Custom Menu widget ) .
*/
if ( ! did_action ( 'customize_preview_init' ) ) {
foreach ( $this -> manager -> settings () as $setting ) {
if ( $setting -> id !== $setting_id ) {
$setting -> preview ();
}
}
}
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 ) {
2015-02-08 18:11:25 -05:00
unset ( $_POST [ $key ] );
unset ( $_REQUEST [ $key ] );
2014-03-22 16:55:18 -04:00
}
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
2015-02-08 18:11:25 -05:00
// Obtain the widget instance.
$option = $this -> get_captured_option ( $option_name );
if ( null !== $parsed_id [ 'number' ] ) {
$instance = $option [ $parsed_id [ 'number' ] ];
} else {
$instance = $option ;
}
/*
* Override the incoming $_POST [ 'customized' ] for a newly - created widget ' s
* setting with the new $instance so that the preview filter currently
* in place from WP_Customize_Setting :: preview () will use this value
* instead of the default widget instance value ( an empty array ) .
*/
$this -> manager -> set_post_value ( $setting_id , $instance );
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 ();
2015-02-08 18:11:25 -05:00
$form = $wp_registered_widget_controls [ $widget_id ];
2014-03-22 16:55:18 -04:00
if ( $form ) {
call_user_func_array ( $form [ 'callback' ], $form [ 'params' ] );
2014-03-05 15:41:14 -05:00
}
2014-03-22 16:55:18 -04:00
$form = ob_get_clean ();
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
2015-02-08 18:11:25 -05:00
if ( empty ( $_POST [ 'widget-id' ] ) ) {
wp_send_json_error ( 'missing_widget-id' );
2014-03-22 16:55:18 -04:00
}
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 );
2015-02-08 18:11:25 -05:00
$id_base = $parsed_id [ 'id_base' ];
$is_updating_widget_template = (
isset ( $_POST [ 'widget-' . $id_base ] )
&&
is_array ( $_POST [ 'widget-' . $id_base ] )
&&
preg_match ( '/__i__|%i%/' , key ( $_POST [ 'widget-' . $id_base ] ) )
);
if ( $is_updating_widget_template ) {
wp_send_json_error ( 'template_widget_not_updatable' );
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 ) ) {
2015-05-25 18:09:25 -04:00
wp_send_json_error ( $updated_widget -> get_error_code () );
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 .
2015-06-26 21:03:25 -04:00
* @ return bool 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
}
2015-02-08 18:11:25 -05:00
/**
* Get the option that was captured from being saved .
*
* @ since 4.2 . 0
* @ access protected
*
* @ param string $option_name Option name .
* @ param mixed $default Optional . Default value to return if the option does not exist .
* @ return mixed Value set for the option .
*/
protected function get_captured_option ( $option_name , $default = false ) {
if ( array_key_exists ( $option_name , $this -> _captured_options ) ) {
$value = $this -> _captured_options [ $option_name ];
} else {
$value = $default ;
}
return $value ;
}
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
*
2015-02-08 18:11:25 -05:00
* @ param mixed $new_value The new option value .
* @ param string $option_name Name of the option .
* @ param mixed $old_value The old option value .
* @ return mixed Filtered option value .
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 ;
}
2015-02-08 18:11:25 -05: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
}
2015-02-08 18:11:25 -05:00
$this -> _captured_options [ $option_name ] = $new_value ;
2014-03-28 10:07:14 -04:00
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
*
2015-02-08 18:11:25 -05:00
* @ param mixed $value Value to return instead of the option value .
* @ return mixed Filtered option value .
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
2015-02-08 18:11:25 -05: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
}
2015-02-08 18:11:25 -05:00
/**
* @ since 3.9 . 0
* @ deprecated 4.2 . 0 Deprecated in favor of customize_dynamic_setting_args filter .
*/
public function setup_widget_addition_previews () {
_deprecated_function ( __METHOD__ , '4.2.0' );
}
/**
* @ since 3.9 . 0
* @ deprecated 4.2 . 0 Deprecated in favor of customize_dynamic_setting_args filter .
*/
public function prepreview_added_sidebars_widgets () {
_deprecated_function ( __METHOD__ , '4.2.0' );
}
/**
* @ since 3.9 . 0
* @ deprecated 4.2 . 0 Deprecated in favor of customize_dynamic_setting_args filter .
*/
public function prepreview_added_widget_instance () {
_deprecated_function ( __METHOD__ , '4.2.0' );
}
/**
* @ since 3.9 . 0
* @ deprecated 4.2 . 0 Deprecated in favor of customize_dynamic_setting_args filter .
*/
public function remove_prepreview_filters () {
_deprecated_function ( __METHOD__ , '4.2.0' );
}
2014-03-05 15:41:14 -05:00
}