92 /** |
92 /** |
93 * Initial loader. |
93 * Initial loader. |
94 * |
94 * |
95 * @since 3.9.0 |
95 * @since 3.9.0 |
96 * |
96 * |
97 * @param WP_Customize_Manager $manager Customize manager bootstrap instance. |
97 * @param WP_Customize_Manager $manager Customizer bootstrap instance. |
98 */ |
98 */ |
99 public function __construct( $manager ) { |
99 public function __construct( $manager ) { |
100 $this->manager = $manager; |
100 $this->manager = $manager; |
101 |
101 |
102 // See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L420-L449 |
102 // See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L420-L449 |
171 /** |
171 /** |
172 * Retrieves the widget setting type given a setting ID. |
172 * Retrieves the widget setting type given a setting ID. |
173 * |
173 * |
174 * @since 4.2.0 |
174 * @since 4.2.0 |
175 * |
175 * |
176 * @staticvar array $cache |
|
177 * |
|
178 * @param string $setting_id Setting ID. |
176 * @param string $setting_id Setting ID. |
179 * @return string|void Setting type. |
177 * @return string|void Setting type. |
180 */ |
178 */ |
181 protected function get_setting_type( $setting_id ) { |
179 protected function get_setting_type( $setting_id ) { |
182 static $cache = array(); |
180 static $cache = array(); |
223 * |
221 * |
224 * @since 4.2.0 |
222 * @since 4.2.0 |
225 * |
223 * |
226 * @param false|array $args The arguments to the WP_Customize_Setting constructor. |
224 * @param false|array $args The arguments to the WP_Customize_Setting constructor. |
227 * @param string $setting_id ID for dynamic setting, usually coming from `$_POST['customized']`. |
225 * @param string $setting_id ID for dynamic setting, usually coming from `$_POST['customized']`. |
228 * @return false|array Setting arguments, false otherwise. |
226 * @return array|false Setting arguments, false otherwise. |
229 */ |
227 */ |
230 public function filter_customize_dynamic_setting_args( $args, $setting_id ) { |
228 public function filter_customize_dynamic_setting_args( $args, $setting_id ) { |
231 if ( $this->get_setting_type( $setting_id ) ) { |
229 if ( $this->get_setting_type( $setting_id ) ) { |
232 $args = $this->get_setting_args( $setting_id ); |
230 $args = $this->get_setting_args( $setting_id ); |
233 } |
231 } |
274 |
272 |
275 $this->old_sidebars_widgets = wp_get_sidebars_widgets(); |
273 $this->old_sidebars_widgets = wp_get_sidebars_widgets(); |
276 add_filter( 'customize_value_old_sidebars_widgets_data', array( $this, 'filter_customize_value_old_sidebars_widgets_data' ) ); |
274 add_filter( 'customize_value_old_sidebars_widgets_data', array( $this, 'filter_customize_value_old_sidebars_widgets_data' ) ); |
277 $this->manager->set_post_value( 'old_sidebars_widgets_data', $this->old_sidebars_widgets ); // Override any value cached in changeset. |
275 $this->manager->set_post_value( 'old_sidebars_widgets_data', $this->old_sidebars_widgets ); // Override any value cached in changeset. |
278 |
276 |
279 // retrieve_widgets() looks at the global $sidebars_widgets |
277 // retrieve_widgets() looks at the global $sidebars_widgets. |
280 $sidebars_widgets = $this->old_sidebars_widgets; |
278 $sidebars_widgets = $this->old_sidebars_widgets; |
281 $sidebars_widgets = retrieve_widgets( 'customize' ); |
279 $sidebars_widgets = retrieve_widgets( 'customize' ); |
282 add_filter( 'option_sidebars_widgets', array( $this, 'filter_option_sidebars_widgets_for_theme_switch' ), 1 ); |
280 add_filter( 'option_sidebars_widgets', array( $this, 'filter_option_sidebars_widgets_for_theme_switch' ), 1 ); |
283 // reset global cache var used by wp_get_sidebars_widgets() |
281 // Reset global cache var used by wp_get_sidebars_widgets(). |
284 unset( $GLOBALS['_wp_sidebars_widgets'] ); |
282 unset( $GLOBALS['_wp_sidebars_widgets'] ); |
285 } |
283 } |
286 |
284 |
287 /** |
285 /** |
288 * Filters old_sidebars_widgets_data Customizer setting. |
286 * Filters old_sidebars_widgets_data Customizer setting. |
331 * |
329 * |
332 * @since 3.9.0 |
330 * @since 3.9.0 |
333 */ |
331 */ |
334 public function customize_controls_init() { |
332 public function customize_controls_init() { |
335 /** This action is documented in wp-admin/includes/ajax-actions.php */ |
333 /** This action is documented in wp-admin/includes/ajax-actions.php */ |
336 do_action( 'load-widgets.php' ); |
334 do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
337 |
335 |
338 /** This action is documented in wp-admin/includes/ajax-actions.php */ |
336 /** This action is documented in wp-admin/includes/ajax-actions.php */ |
339 do_action( 'widgets.php' ); |
337 do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
340 |
338 |
341 /** This action is documented in wp-admin/widgets.php */ |
339 /** This action is documented in wp-admin/widgets.php */ |
342 do_action( 'sidebar_admin_setup' ); |
340 do_action( 'sidebar_admin_setup' ); |
343 } |
341 } |
344 |
342 |
448 if ( $is_active_sidebar ) { |
446 if ( $is_active_sidebar ) { |
449 |
447 |
450 $section_args = array( |
448 $section_args = array( |
451 'title' => $wp_registered_sidebars[ $sidebar_id ]['name'], |
449 'title' => $wp_registered_sidebars[ $sidebar_id ]['name'], |
452 'description' => $wp_registered_sidebars[ $sidebar_id ]['description'], |
450 'description' => $wp_registered_sidebars[ $sidebar_id ]['description'], |
453 'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ) ), |
451 'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ), true ), |
454 'panel' => 'widgets', |
452 'panel' => 'widgets', |
455 'sidebar_id' => $sidebar_id, |
453 'sidebar_id' => $sidebar_id, |
456 ); |
454 ); |
457 |
455 |
458 /** |
456 /** |
565 * This method will return all Core widgets as being not wide, but this can be |
563 * This method will return all Core widgets as being not wide, but this can be |
566 * overridden with the {@see 'is_wide_widget_in_customizer'} filter. |
564 * overridden with the {@see 'is_wide_widget_in_customizer'} filter. |
567 * |
565 * |
568 * @since 3.9.0 |
566 * @since 3.9.0 |
569 * |
567 * |
570 * @global $wp_registered_widget_controls |
568 * @global array $wp_registered_widget_controls |
571 * |
569 * |
572 * @param string $widget_id Widget ID. |
570 * @param string $widget_id Widget ID. |
573 * @return bool Whether or not the widget is a "wide" widget. |
571 * @return bool Whether or not the widget is a "wide" widget. |
574 */ |
572 */ |
575 public function is_wide_widget( $widget_id ) { |
573 public function is_wide_widget( $widget_id ) { |
576 global $wp_registered_widget_controls; |
574 global $wp_registered_widget_controls; |
577 |
575 |
578 $parsed_widget_id = $this->parse_widget_id( $widget_id ); |
576 $parsed_widget_id = $this->parse_widget_id( $widget_id ); |
579 $width = $wp_registered_widget_controls[ $widget_id ]['width']; |
577 $width = $wp_registered_widget_controls[ $widget_id ]['width']; |
580 $is_core = in_array( $parsed_widget_id['id_base'], $this->core_widget_id_bases ); |
578 $is_core = in_array( $parsed_widget_id['id_base'], $this->core_widget_id_bases, true ); |
581 $is_wide = ( $width > 250 && ! $is_core ); |
579 $is_wide = ( $width > 250 && ! $is_core ); |
582 |
580 |
583 /** |
581 /** |
584 * Filters whether the given widget is considered "wide". |
582 * Filters whether the given widget is considered "wide". |
585 * |
583 * |
607 |
605 |
608 if ( preg_match( '/^(.+)-(\d+)$/', $widget_id, $matches ) ) { |
606 if ( preg_match( '/^(.+)-(\d+)$/', $widget_id, $matches ) ) { |
609 $parsed['id_base'] = $matches[1]; |
607 $parsed['id_base'] = $matches[1]; |
610 $parsed['number'] = intval( $matches[2] ); |
608 $parsed['number'] = intval( $matches[2] ); |
611 } else { |
609 } else { |
612 // likely an old single widget |
610 // Likely an old single widget. |
613 $parsed['id_base'] = $widget_id; |
611 $parsed['id_base'] = $widget_id; |
614 } |
612 } |
615 return $parsed; |
613 return $parsed; |
616 } |
614 } |
617 |
615 |
619 * Converts a widget setting ID (option path) to its id_base and number components. |
617 * Converts a widget setting ID (option path) to its id_base and number components. |
620 * |
618 * |
621 * @since 3.9.0 |
619 * @since 3.9.0 |
622 * |
620 * |
623 * @param string $setting_id Widget setting ID. |
621 * @param string $setting_id Widget setting ID. |
624 * @return WP_Error|array Array containing a widget's id_base and number components, |
622 * @return array|WP_Error Array containing a widget's id_base and number components, |
625 * or a WP_Error object. |
623 * or a WP_Error object. |
626 */ |
624 */ |
627 public function parse_widget_setting_id( $setting_id ) { |
625 public function parse_widget_setting_id( $setting_id ) { |
628 if ( ! preg_match( '/^(widget_(.+?))(?:\[(\d+)\])?$/', $setting_id, $matches ) ) { |
626 if ( ! preg_match( '/^(widget_(.+?))(?:\[(\d+)\])?$/', $setting_id, $matches ) ) { |
629 return new WP_Error( 'widget_setting_invalid_id' ); |
627 return new WP_Error( 'widget_setting_invalid_id' ); |
641 * |
639 * |
642 * @since 3.9.0 |
640 * @since 3.9.0 |
643 */ |
641 */ |
644 public function print_styles() { |
642 public function print_styles() { |
645 /** This action is documented in wp-admin/admin-header.php */ |
643 /** This action is documented in wp-admin/admin-header.php */ |
646 do_action( 'admin_print_styles-widgets.php' ); |
644 do_action( 'admin_print_styles-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
647 |
645 |
648 /** This action is documented in wp-admin/admin-header.php */ |
646 /** This action is documented in wp-admin/admin-header.php */ |
649 do_action( 'admin_print_styles' ); |
647 do_action( 'admin_print_styles' ); |
650 } |
648 } |
651 |
649 |
655 * |
653 * |
656 * @since 3.9.0 |
654 * @since 3.9.0 |
657 */ |
655 */ |
658 public function print_scripts() { |
656 public function print_scripts() { |
659 /** This action is documented in wp-admin/admin-header.php */ |
657 /** This action is documented in wp-admin/admin-header.php */ |
660 do_action( 'admin_print_scripts-widgets.php' ); |
658 do_action( 'admin_print_scripts-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
661 |
659 |
662 /** This action is documented in wp-admin/admin-header.php */ |
660 /** This action is documented in wp-admin/admin-header.php */ |
663 do_action( 'admin_print_scripts' ); |
661 do_action( 'admin_print_scripts' ); |
664 } |
662 } |
665 |
663 |
730 ); |
728 ); |
731 $registered_sidebar_count = count( $wp_registered_sidebars ); |
729 $registered_sidebar_count = count( $wp_registered_sidebars ); |
732 for ( $non_rendered_count = 2; $non_rendered_count < $registered_sidebar_count; $non_rendered_count++ ) { |
730 for ( $non_rendered_count = 2; $non_rendered_count < $registered_sidebar_count; $non_rendered_count++ ) { |
733 $some_non_rendered_areas_messages[ $non_rendered_count ] = html_entity_decode( |
731 $some_non_rendered_areas_messages[ $non_rendered_count ] = html_entity_decode( |
734 sprintf( |
732 sprintf( |
735 /* translators: %s: the number of other widget areas registered but not rendered */ |
733 /* translators: %s: The number of other widget areas registered but not rendered. */ |
736 _n( |
734 _n( |
737 'Your theme has %s other widget area, but this particular page doesn’t display it.', |
735 'Your theme has %s other widget area, but this particular page doesn’t display it.', |
738 'Your theme has %s other widget areas, but this particular page doesn’t display them.', |
736 'Your theme has %s other widget areas, but this particular page doesn’t display them.', |
739 $non_rendered_count |
737 $non_rendered_count |
740 ), |
738 ), |
754 get_bloginfo( 'charset' ) |
752 get_bloginfo( 'charset' ) |
755 ); |
753 ); |
756 } else { |
754 } else { |
757 $no_areas_shown_message = html_entity_decode( |
755 $no_areas_shown_message = html_entity_decode( |
758 sprintf( |
756 sprintf( |
759 /* translators: %s: the total number of widget areas registered */ |
757 /* translators: %s: The total number of widget areas registered. */ |
760 _n( |
758 _n( |
761 'Your theme has %s widget area, but this particular page doesn’t display it.', |
759 'Your theme has %s widget area, but this particular page doesn’t display it.', |
762 'Your theme has %s widget areas, but this particular page doesn’t display them.', |
760 'Your theme has %s widget areas, but this particular page doesn’t display them.', |
763 $registered_sidebar_count |
761 $registered_sidebar_count |
764 ), |
762 ), |
770 } |
768 } |
771 |
769 |
772 $settings = array( |
770 $settings = array( |
773 'registeredSidebars' => array_values( $wp_registered_sidebars ), |
771 'registeredSidebars' => array_values( $wp_registered_sidebars ), |
774 'registeredWidgets' => $wp_registered_widgets, |
772 'registeredWidgets' => $wp_registered_widgets, |
775 'availableWidgets' => $available_widgets, // @todo Merge this with registered_widgets |
773 'availableWidgets' => $available_widgets, // @todo Merge this with registered_widgets. |
776 'l10n' => array( |
774 'l10n' => array( |
777 'saveBtnLabel' => __( 'Apply' ), |
775 'saveBtnLabel' => __( 'Apply' ), |
778 'saveBtnTooltip' => __( 'Save and preview changes before publishing them.' ), |
776 'saveBtnTooltip' => __( 'Save and preview changes before publishing them.' ), |
779 'removeBtnLabel' => __( 'Remove' ), |
777 'removeBtnLabel' => __( 'Remove' ), |
780 'removeBtnTooltip' => __( 'Keep widget settings and move it to the inactive widgets' ), |
778 'removeBtnTooltip' => __( 'Keep widget settings and move it to the inactive widgets' ), |
785 'someAreasShown' => $some_non_rendered_areas_messages, |
783 'someAreasShown' => $some_non_rendered_areas_messages, |
786 'noAreasShown' => $no_areas_shown_message, |
784 'noAreasShown' => $no_areas_shown_message, |
787 'reorderModeOn' => __( 'Reorder mode enabled' ), |
785 'reorderModeOn' => __( 'Reorder mode enabled' ), |
788 'reorderModeOff' => __( 'Reorder mode closed' ), |
786 'reorderModeOff' => __( 'Reorder mode closed' ), |
789 'reorderLabelOn' => esc_attr__( 'Reorder widgets' ), |
787 'reorderLabelOn' => esc_attr__( 'Reorder widgets' ), |
790 /* translators: %d: the number of widgets found */ |
788 /* translators: %d: The number of widgets found. */ |
791 'widgetsFound' => __( 'Number of widgets found: %d' ), |
789 'widgetsFound' => __( 'Number of widgets found: %d' ), |
792 'noWidgetsFound' => __( 'No widgets found.' ), |
790 'noWidgetsFound' => __( 'No widgets found.' ), |
793 ), |
791 ), |
794 'tpl' => array( |
792 'tpl' => array( |
795 'widgetReorderNav' => $widget_reorder_nav_tpl, |
793 'widgetReorderNav' => $widget_reorder_nav_tpl, |
797 ), |
795 ), |
798 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), |
796 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), |
799 ); |
797 ); |
800 |
798 |
801 foreach ( $settings['registeredWidgets'] as &$registered_widget ) { |
799 foreach ( $settings['registeredWidgets'] as &$registered_widget ) { |
802 unset( $registered_widget['callback'] ); // may not be JSON-serializeable |
800 unset( $registered_widget['callback'] ); // May not be JSON-serializeable. |
803 } |
801 } |
804 |
802 |
805 $wp_scripts->add_data( |
803 $wp_scripts->add_data( |
806 'customize-widgets', |
804 'customize-widgets', |
807 'data', |
805 'data', |
823 <span class="screen-reader-text"><?php _e( 'Back' ); ?></span> |
821 <span class="screen-reader-text"><?php _e( 'Back' ); ?></span> |
824 </button> |
822 </button> |
825 <h3> |
823 <h3> |
826 <span class="customize-action"> |
824 <span class="customize-action"> |
827 <?php |
825 <?php |
828 /* translators: ▸ is the unicode right-pointing triangle, and %s is the section title in the Customizer */ |
826 /* translators: ▸ is the unicode right-pointing triangle. %s: Section title in the Customizer. */ |
829 echo sprintf( __( 'Customizing ▸ %s' ), esc_html( $this->manager->get_panel( 'widgets' )->title ) ); |
827 printf( __( 'Customizing ▸ %s' ), esc_html( $this->manager->get_panel( 'widgets' )->title ) ); |
830 ?> |
828 ?> |
831 </span> |
829 </span> |
832 <?php _e( 'Add a Widget' ); ?> |
830 <?php _e( 'Add a Widget' ); ?> |
833 </h3> |
831 </h3> |
834 </div> |
832 </div> |
858 * |
856 * |
859 * @since 3.9.0 |
857 * @since 3.9.0 |
860 */ |
858 */ |
861 public function print_footer_scripts() { |
859 public function print_footer_scripts() { |
862 /** This action is documented in wp-admin/admin-footer.php */ |
860 /** This action is documented in wp-admin/admin-footer.php */ |
863 do_action( 'admin_print_footer_scripts-widgets.php' ); |
861 do_action( 'admin_print_footer_scripts-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
864 |
862 |
865 /** This action is documented in wp-admin/admin-footer.php */ |
863 /** This action is documented in wp-admin/admin-footer.php */ |
866 do_action( 'admin_print_footer_scripts' ); |
864 do_action( 'admin_print_footer_scripts' ); |
867 |
865 |
868 /** This action is documented in wp-admin/admin-footer.php */ |
866 /** This action is documented in wp-admin/admin-footer.php */ |
869 do_action( 'admin_footer-widgets.php' ); |
867 do_action( 'admin_footer-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
870 } |
868 } |
871 |
869 |
872 /** |
870 /** |
873 * Retrieves common arguments to supply when constructing a Customizer setting. |
871 * Retrieves common arguments to supply when constructing a Customizer setting. |
874 * |
872 * |
947 if ( ! empty( $available_widgets ) ) { |
944 if ( ! empty( $available_widgets ) ) { |
948 return $available_widgets; |
945 return $available_widgets; |
949 } |
946 } |
950 |
947 |
951 global $wp_registered_widgets, $wp_registered_widget_controls; |
948 global $wp_registered_widgets, $wp_registered_widget_controls; |
952 require_once ABSPATH . 'wp-admin/includes/widgets.php'; // for next_widget_id_number() |
949 require_once ABSPATH . 'wp-admin/includes/widgets.php'; // For next_widget_id_number(). |
953 |
950 |
954 $sort = $wp_registered_widgets; |
951 $sort = $wp_registered_widgets; |
955 usort( $sort, array( $this, '_sort_name_callback' ) ); |
952 usort( $sort, array( $this, '_sort_name_callback' ) ); |
956 $done = array(); |
953 $done = array(); |
957 |
954 |
958 foreach ( $sort as $widget ) { |
955 foreach ( $sort as $widget ) { |
959 if ( in_array( $widget['callback'], $done, true ) ) { // We already showed this multi-widget |
956 if ( in_array( $widget['callback'], $done, true ) ) { // We already showed this multi-widget. |
960 continue; |
957 continue; |
961 } |
958 } |
962 |
959 |
963 $sidebar = is_active_widget( $widget['callback'], $widget['id'], false, false ); |
960 $sidebar = is_active_widget( $widget['callback'], $widget['id'], false, false ); |
964 $done[] = $widget['callback']; |
961 $done[] = $widget['callback']; |
966 if ( ! isset( $widget['params'][0] ) ) { |
963 if ( ! isset( $widget['params'][0] ) ) { |
967 $widget['params'][0] = array(); |
964 $widget['params'][0] = array(); |
968 } |
965 } |
969 |
966 |
970 $available_widget = $widget; |
967 $available_widget = $widget; |
971 unset( $available_widget['callback'] ); // not serializable to JSON |
968 unset( $available_widget['callback'] ); // Not serializable to JSON. |
972 |
969 |
973 $args = array( |
970 $args = array( |
974 'widget_id' => $widget['id'], |
971 'widget_id' => $widget['id'], |
975 'widget_name' => $widget['name'], |
972 'widget_name' => $widget['name'], |
976 '_display' => 'template', |
973 '_display' => 'template', |
1005 $available_widget, |
1002 $available_widget, |
1006 array( |
1003 array( |
1007 'temp_id' => isset( $args['_temp_id'] ) ? $args['_temp_id'] : null, |
1004 'temp_id' => isset( $args['_temp_id'] ) ? $args['_temp_id'] : null, |
1008 'is_multi' => $is_multi_widget, |
1005 'is_multi' => $is_multi_widget, |
1009 'control_tpl' => $control_tpl, |
1006 'control_tpl' => $control_tpl, |
1010 'multi_number' => ( $args['_add'] === 'multi' ) ? $args['_multi_num'] : false, |
1007 'multi_number' => ( 'multi' === $args['_add'] ) ? $args['_multi_num'] : false, |
1011 'is_disabled' => $is_disabled, |
1008 'is_disabled' => $is_disabled, |
1012 'id_base' => $id_base, |
1009 'id_base' => $id_base, |
1013 'transport' => $this->is_widget_selective_refreshable( $id_base ) ? 'postMessage' : 'refresh', |
1010 'transport' => $this->is_widget_selective_refreshable( $id_base ) ? 'postMessage' : 'refresh', |
1014 'width' => $wp_registered_widget_controls[ $widget['id'] ]['width'], |
1011 'width' => $wp_registered_widget_controls[ $widget['id'] ]['width'], |
1015 'height' => $wp_registered_widget_controls[ $widget['id'] ]['height'], |
1012 'height' => $wp_registered_widget_controls[ $widget['id'] ]['height'], |
1048 $args[0]['before_form'] = '<div class="form">'; |
1045 $args[0]['before_form'] = '<div class="form">'; |
1049 $args[0]['after_form'] = '</div><!-- .form -->'; |
1046 $args[0]['after_form'] = '</div><!-- .form -->'; |
1050 $args[0]['before_widget_content'] = '<div class="widget-content">'; |
1047 $args[0]['before_widget_content'] = '<div class="widget-content">'; |
1051 $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; |
1048 $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; |
1052 ob_start(); |
1049 ob_start(); |
1053 call_user_func_array( 'wp_widget_control', $args ); |
1050 wp_widget_control( ...$args ); |
1054 $control_tpl = ob_get_clean(); |
1051 $control_tpl = ob_get_clean(); |
1055 return $control_tpl; |
1052 return $control_tpl; |
1056 } |
1053 } |
1057 |
1054 |
1058 /** |
1055 /** |
1101 /** |
1098 /** |
1102 * Refreshes the nonce for widget updates. |
1099 * Refreshes the nonce for widget updates. |
1103 * |
1100 * |
1104 * @since 4.2.0 |
1101 * @since 4.2.0 |
1105 * |
1102 * |
1106 * @param array $nonces Array of nonces. |
1103 * @param array $nonces Array of nonces. |
1107 * @return array $nonces Array of nonces. |
1104 * @return array Array of nonces. |
1108 */ |
1105 */ |
1109 public function refresh_nonces( $nonces ) { |
1106 public function refresh_nonces( $nonces ) { |
1110 $nonces['update-widget'] = wp_create_nonce( 'update-widget' ); |
1107 $nonces['update-widget'] = wp_create_nonce( 'update-widget' ); |
1111 return $nonces; |
1108 return $nonces; |
1112 } |
1109 } |
1171 */ |
1168 */ |
1172 public function export_preview_data() { |
1169 public function export_preview_data() { |
1173 global $wp_registered_sidebars, $wp_registered_widgets; |
1170 global $wp_registered_sidebars, $wp_registered_widgets; |
1174 |
1171 |
1175 $switched_locale = switch_to_locale( get_user_locale() ); |
1172 $switched_locale = switch_to_locale( get_user_locale() ); |
1176 $l10n = array( |
1173 |
|
1174 $l10n = array( |
1177 'widgetTooltip' => __( 'Shift-click to edit this widget.' ), |
1175 'widgetTooltip' => __( 'Shift-click to edit this widget.' ), |
1178 ); |
1176 ); |
|
1177 |
1179 if ( $switched_locale ) { |
1178 if ( $switched_locale ) { |
1180 restore_previous_locale(); |
1179 restore_previous_locale(); |
1181 } |
1180 } |
1182 |
1181 |
|
1182 $rendered_sidebars = array_filter( $this->rendered_sidebars ); |
|
1183 $rendered_widgets = array_filter( $this->rendered_widgets ); |
|
1184 |
1183 // Prepare Customizer settings to pass to JavaScript. |
1185 // Prepare Customizer settings to pass to JavaScript. |
1184 $settings = array( |
1186 $settings = array( |
1185 'renderedSidebars' => array_fill_keys( array_unique( $this->rendered_sidebars ), true ), |
1187 'renderedSidebars' => array_fill_keys( array_keys( $rendered_sidebars ), true ), |
1186 'renderedWidgets' => array_fill_keys( array_keys( $this->rendered_widgets ), true ), |
1188 'renderedWidgets' => array_fill_keys( array_keys( $rendered_widgets ), true ), |
1187 'registeredSidebars' => array_values( $wp_registered_sidebars ), |
1189 'registeredSidebars' => array_values( $wp_registered_sidebars ), |
1188 'registeredWidgets' => $wp_registered_widgets, |
1190 'registeredWidgets' => $wp_registered_widgets, |
1189 'l10n' => $l10n, |
1191 'l10n' => $l10n, |
1190 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), |
1192 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), |
1191 ); |
1193 ); |
|
1194 |
1192 foreach ( $settings['registeredWidgets'] as &$registered_widget ) { |
1195 foreach ( $settings['registeredWidgets'] as &$registered_widget ) { |
1193 unset( $registered_widget['callback'] ); // may not be JSON-serializeable |
1196 unset( $registered_widget['callback'] ); // May not be JSON-serializeable. |
1194 } |
1197 } |
1195 |
1198 |
1196 ?> |
1199 ?> |
1197 <script type="text/javascript"> |
1200 <script type="text/javascript"> |
1198 var _wpWidgetCustomizerPreviewSettings = <?php echo wp_json_encode( $settings ); ?>; |
1201 var _wpWidgetCustomizerPreviewSettings = <?php echo wp_json_encode( $settings ); ?>; |
1218 * |
1221 * |
1219 * @param string $widget_id Widget ID to check. |
1222 * @param string $widget_id Widget ID to check. |
1220 * @return bool Whether the widget is rendered. |
1223 * @return bool Whether the widget is rendered. |
1221 */ |
1224 */ |
1222 public function is_widget_rendered( $widget_id ) { |
1225 public function is_widget_rendered( $widget_id ) { |
1223 return in_array( $widget_id, $this->rendered_widgets ); |
1226 return ! empty( $this->rendered_widgets[ $widget_id ] ); |
1224 } |
1227 } |
1225 |
1228 |
1226 /** |
1229 /** |
1227 * Determines if a sidebar is rendered on the page. |
1230 * Determines if a sidebar is rendered on the page. |
1228 * |
1231 * |
1230 * |
1233 * |
1231 * @param string $sidebar_id Sidebar ID to check. |
1234 * @param string $sidebar_id Sidebar ID to check. |
1232 * @return bool Whether the sidebar is rendered. |
1235 * @return bool Whether the sidebar is rendered. |
1233 */ |
1236 */ |
1234 public function is_sidebar_rendered( $sidebar_id ) { |
1237 public function is_sidebar_rendered( $sidebar_id ) { |
1235 return in_array( $sidebar_id, $this->rendered_sidebars ); |
1238 return ! empty( $this->rendered_sidebars[ $sidebar_id ] ); |
1236 } |
1239 } |
1237 |
1240 |
1238 /** |
1241 /** |
1239 * Tallies the sidebars rendered via is_active_sidebar(). |
1242 * Tallies the sidebars rendered via is_active_sidebar(). |
1240 * |
1243 * |
1248 * @param string $sidebar_id Sidebar ID. |
1251 * @param string $sidebar_id Sidebar ID. |
1249 * @return bool Whether the sidebar is active. |
1252 * @return bool Whether the sidebar is active. |
1250 */ |
1253 */ |
1251 public function tally_sidebars_via_is_active_sidebar_calls( $is_active, $sidebar_id ) { |
1254 public function tally_sidebars_via_is_active_sidebar_calls( $is_active, $sidebar_id ) { |
1252 if ( is_registered_sidebar( $sidebar_id ) ) { |
1255 if ( is_registered_sidebar( $sidebar_id ) ) { |
1253 $this->rendered_sidebars[] = $sidebar_id; |
1256 $this->rendered_sidebars[ $sidebar_id ] = true; |
1254 } |
1257 } |
|
1258 |
1255 /* |
1259 /* |
1256 * We may need to force this to true, and also force-true the value |
1260 * We may need to force this to true, and also force-true the value |
1257 * for 'dynamic_sidebar_has_widgets' if we want to ensure that there |
1261 * for 'dynamic_sidebar_has_widgets' if we want to ensure that there |
1258 * is an area to drop widgets into, if the sidebar is empty. |
1262 * is an area to drop widgets into, if the sidebar is empty. |
1259 */ |
1263 */ |
1273 * @param string $sidebar_id Sidebar ID. |
1277 * @param string $sidebar_id Sidebar ID. |
1274 * @return bool Whether the current sidebar has widgets. |
1278 * @return bool Whether the current sidebar has widgets. |
1275 */ |
1279 */ |
1276 public function tally_sidebars_via_dynamic_sidebar_calls( $has_widgets, $sidebar_id ) { |
1280 public function tally_sidebars_via_dynamic_sidebar_calls( $has_widgets, $sidebar_id ) { |
1277 if ( is_registered_sidebar( $sidebar_id ) ) { |
1281 if ( is_registered_sidebar( $sidebar_id ) ) { |
1278 $this->rendered_sidebars[] = $sidebar_id; |
1282 $this->rendered_sidebars[ $sidebar_id ] = true; |
1279 } |
1283 } |
1280 |
1284 |
1281 /* |
1285 /* |
1282 * We may need to force this to true, and also force-true the value |
1286 * We may need to force this to true, and also force-true the value |
1283 * for 'is_active_sidebar' if we want to ensure there is an area to |
1287 * for 'is_active_sidebar' if we want to ensure there is an area to |
1311 * |
1315 * |
1312 * @param array $value Widget instance to sanitize. |
1316 * @param array $value Widget instance to sanitize. |
1313 * @return array|void Sanitized widget instance. |
1317 * @return array|void Sanitized widget instance. |
1314 */ |
1318 */ |
1315 public function sanitize_widget_instance( $value ) { |
1319 public function sanitize_widget_instance( $value ) { |
1316 if ( $value === array() ) { |
1320 if ( array() === $value ) { |
1317 return $value; |
1321 return $value; |
1318 } |
1322 } |
1319 |
1323 |
1320 if ( empty( $value['is_widget_customizer_js_value'] ) |
1324 if ( empty( $value['is_widget_customizer_js_value'] ) |
1321 || empty( $value['instance_hash_key'] ) |
1325 || empty( $value['instance_hash_key'] ) |
1389 * @since 3.9.0 |
1393 * @since 3.9.0 |
1390 * |
1394 * |
1391 * @global array $wp_registered_widget_updates |
1395 * @global array $wp_registered_widget_updates |
1392 * @global array $wp_registered_widget_controls |
1396 * @global array $wp_registered_widget_controls |
1393 * |
1397 * |
1394 * @param string $widget_id Widget ID. |
1398 * @param string $widget_id Widget ID. |
1395 * @return WP_Error|array Array containing the updated widget information. |
1399 * @return array|WP_Error Array containing the updated widget information. |
1396 * A WP_Error object, otherwise. |
1400 * A WP_Error object, otherwise. |
1397 */ |
1401 */ |
1398 public function call_widget_update( $widget_id ) { |
1402 public function call_widget_update( $widget_id ) { |
1399 global $wp_registered_widget_updates, $wp_registered_widget_controls; |
1403 global $wp_registered_widget_updates, $wp_registered_widget_controls; |
1400 |
1404 |
1436 |
1440 |
1437 if ( ! is_null( $parsed_id['number'] ) ) { |
1441 if ( ! is_null( $parsed_id['number'] ) ) { |
1438 $value = array(); |
1442 $value = array(); |
1439 $value[ $parsed_id['number'] ] = $instance; |
1443 $value[ $parsed_id['number'] ] = $instance; |
1440 $key = 'widget-' . $parsed_id['id_base']; |
1444 $key = 'widget-' . $parsed_id['id_base']; |
1441 $_REQUEST[ $key ] = $_POST[ $key ] = wp_slash( $value ); |
1445 $_REQUEST[ $key ] = wp_slash( $value ); |
|
1446 $_POST[ $key ] = $_REQUEST[ $key ]; |
1442 $added_input_vars[] = $key; |
1447 $added_input_vars[] = $key; |
1443 } else { |
1448 } else { |
1444 foreach ( $instance as $key => $value ) { |
1449 foreach ( $instance as $key => $value ) { |
1445 $_REQUEST[ $key ] = $_POST[ $key ] = wp_slash( $value ); |
1450 $_REQUEST[ $key ] = wp_slash( $value ); |
|
1451 $_POST[ $key ] = $_REQUEST[ $key ]; |
1446 $added_input_vars[] = $key; |
1452 $added_input_vars[] = $key; |
1447 } |
1453 } |
1448 } |
1454 } |
1449 } |
1455 } |
1450 |
1456 |
1534 if ( empty( $_POST['widget-id'] ) ) { |
1540 if ( empty( $_POST['widget-id'] ) ) { |
1535 wp_send_json_error( 'missing_widget-id' ); |
1541 wp_send_json_error( 'missing_widget-id' ); |
1536 } |
1542 } |
1537 |
1543 |
1538 /** This action is documented in wp-admin/includes/ajax-actions.php */ |
1544 /** This action is documented in wp-admin/includes/ajax-actions.php */ |
1539 do_action( 'load-widgets.php' ); |
1545 do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
1540 |
1546 |
1541 /** This action is documented in wp-admin/includes/ajax-actions.php */ |
1547 /** This action is documented in wp-admin/includes/ajax-actions.php */ |
1542 do_action( 'widgets.php' ); |
1548 do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores |
1543 |
1549 |
1544 /** This action is documented in wp-admin/widgets.php */ |
1550 /** This action is documented in wp-admin/widgets.php */ |
1545 do_action( 'sidebar_admin_setup' ); |
1551 do_action( 'sidebar_admin_setup' ); |
1546 |
1552 |
1547 $widget_id = $this->get_post_value( 'widget-id' ); |
1553 $widget_id = $this->get_post_value( 'widget-id' ); |
1788 |
1794 |
1789 /** |
1795 /** |
1790 * Current sidebar being rendered. |
1796 * Current sidebar being rendered. |
1791 * |
1797 * |
1792 * @since 4.5.0 |
1798 * @since 4.5.0 |
1793 * @var string |
1799 * @var string|null |
1794 */ |
1800 */ |
1795 protected $rendering_widget_id; |
1801 protected $rendering_widget_id; |
1796 |
1802 |
1797 /** |
1803 /** |
1798 * Current widget being rendered. |
1804 * Current widget being rendered. |
1799 * |
1805 * |
1800 * @since 4.5.0 |
1806 * @since 4.5.0 |
1801 * @var string |
1807 * @var string|null |
1802 */ |
1808 */ |
1803 protected $rendering_sidebar_id; |
1809 protected $rendering_sidebar_id; |
1804 |
1810 |
1805 /** |
1811 /** |
1806 * Filters sidebars_widgets to ensure the currently-rendered widget is the only widget in the current sidebar. |
1812 * Filters sidebars_widgets to ensure the currently-rendered widget is the only widget in the current sidebar. |
1854 $filter_callback = array( $this, 'filter_sidebars_widgets_for_rendering_widget' ); |
1860 $filter_callback = array( $this, 'filter_sidebars_widgets_for_rendering_widget' ); |
1855 add_filter( 'sidebars_widgets', $filter_callback, 1000 ); |
1861 add_filter( 'sidebars_widgets', $filter_callback, 1000 ); |
1856 |
1862 |
1857 // Render the widget. |
1863 // Render the widget. |
1858 ob_start(); |
1864 ob_start(); |
1859 dynamic_sidebar( $this->rendering_sidebar_id = $context['sidebar_id'] ); |
1865 $this->rendering_sidebar_id = $context['sidebar_id']; |
1860 $container = ob_get_clean(); |
1866 dynamic_sidebar( $this->rendering_sidebar_id ); |
|
1867 $container = ob_get_clean(); |
1861 |
1868 |
1862 // Reset variables for next partial render. |
1869 // Reset variables for next partial render. |
1863 remove_filter( 'sidebars_widgets', $filter_callback, 1000 ); |
1870 remove_filter( 'sidebars_widgets', $filter_callback, 1000 ); |
1864 |
1871 |
1865 $this->context_sidebar_instance_number = null; |
1872 $this->context_sidebar_instance_number = null; |
1966 * @param mixed $old_value The old option value. |
1973 * @param mixed $old_value The old option value. |
1967 * @return mixed Filtered option value. |
1974 * @return mixed Filtered option value. |
1968 */ |
1975 */ |
1969 public function capture_filter_pre_update_option( $new_value, $option_name, $old_value ) { |
1976 public function capture_filter_pre_update_option( $new_value, $option_name, $old_value ) { |
1970 if ( $this->is_option_capture_ignored( $option_name ) ) { |
1977 if ( $this->is_option_capture_ignored( $option_name ) ) { |
1971 return; |
1978 return $new_value; |
1972 } |
1979 } |
1973 |
1980 |
1974 if ( ! isset( $this->_captured_options[ $option_name ] ) ) { |
1981 if ( ! isset( $this->_captured_options[ $option_name ] ) ) { |
1975 add_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) ); |
1982 add_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) ); |
1976 } |
1983 } |