--- a/wp/wp-includes/class-wp-customize-widgets.php Tue Dec 15 15:52:01 2020 +0100
+++ b/wp/wp-includes/class-wp-customize-widgets.php Wed Sep 21 18:19:35 2022 +0200
@@ -118,6 +118,7 @@
add_action( 'customize_controls_print_footer_scripts', array( $this, 'output_widget_control_templates' ) );
add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
add_filter( 'customize_refresh_nonces', array( $this, 'refresh_nonces' ) );
+ add_filter( 'should_load_block_editor_scripts_and_styles', array( $this, 'should_load_block_editor_scripts_and_styles' ) );
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 );
@@ -368,6 +369,8 @@
public function customize_register() {
global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_sidebars;
+ $use_widgets_block_editor = wp_use_widgets_block_editor();
+
add_filter( 'sidebars_widgets', array( $this, 'preview_sidebars_widgets' ), 1 );
$sidebars_widgets = array_merge(
@@ -446,13 +449,18 @@
if ( $is_active_sidebar ) {
$section_args = array(
- 'title' => $wp_registered_sidebars[ $sidebar_id ]['name'],
- 'description' => $wp_registered_sidebars[ $sidebar_id ]['description'],
- 'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ), true ),
- 'panel' => 'widgets',
- 'sidebar_id' => $sidebar_id,
+ 'title' => $wp_registered_sidebars[ $sidebar_id ]['name'],
+ 'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ), true ),
+ 'panel' => 'widgets',
+ 'sidebar_id' => $sidebar_id,
);
+ if ( $use_widgets_block_editor ) {
+ $section_args['description'] = '';
+ } else {
+ $section_args['description'] = $wp_registered_sidebars[ $sidebar_id ]['description'];
+ }
+
/**
* Filters Customizer widget section arguments for a given sidebar.
*
@@ -467,49 +475,65 @@
$section = new WP_Customize_Sidebar_Section( $this->manager, $section_id, $section_args );
$this->manager->add_section( $section );
- $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.
- )
- );
- $new_setting_ids[] = $setting_id;
+ if ( $use_widgets_block_editor ) {
+ $control = new WP_Sidebar_Block_Editor_Control(
+ $this->manager,
+ $setting_id,
+ array(
+ 'section' => $section_id,
+ 'sidebar_id' => $sidebar_id,
+ 'label' => $section_args['title'],
+ 'description' => $section_args['description'],
+ )
+ );
+ } else {
+ $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.
+ )
+ );
+ }
$this->manager->add_control( $control );
+
+ $new_setting_ids[] = $setting_id;
}
}
- // Add a control for each active widget (located in a sidebar).
- foreach ( $sidebar_widget_ids as $i => $widget_id ) {
+ if ( ! $use_widgets_block_editor ) {
+ // Add a control for each active widget (located in a sidebar).
+ foreach ( $sidebar_widget_ids as $i => $widget_id ) {
- // Skip widgets that may have gone away due to a plugin being deactivated.
- if ( ! $is_active_sidebar || ! isset( $wp_registered_widgets[ $widget_id ] ) ) {
- continue;
- }
+ // Skip widgets that may have gone away due to a plugin being deactivated.
+ if ( ! $is_active_sidebar || ! isset( $wp_registered_widgets[ $widget_id ] ) ) {
+ continue;
+ }
- $registered_widget = $wp_registered_widgets[ $widget_id ];
- $setting_id = $this->get_setting_id( $widget_id );
- $id_base = $wp_registered_widget_controls[ $widget_id ]['id_base'];
+ $registered_widget = $wp_registered_widgets[ $widget_id ];
+ $setting_id = $this->get_setting_id( $widget_id );
+ $id_base = $wp_registered_widget_controls[ $widget_id ]['id_base'];
- $control = new WP_Widget_Form_Customize_Control(
- $this->manager,
- $setting_id,
- array(
- 'label' => $registered_widget['name'],
- 'section' => $section_id,
- 'sidebar_id' => $sidebar_id,
- 'widget_id' => $widget_id,
- 'widget_id_base' => $id_base,
- 'priority' => $i,
- 'width' => $wp_registered_widget_controls[ $widget_id ]['width'],
- 'height' => $wp_registered_widget_controls[ $widget_id ]['height'],
- 'is_wide' => $this->is_wide_widget( $widget_id ),
- )
- );
- $this->manager->add_control( $control );
+ $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 ),
+ )
+ );
+ $this->manager->add_control( $control );
+ }
}
}
@@ -605,7 +629,7 @@
if ( preg_match( '/^(.+)-(\d+)$/', $widget_id, $matches ) ) {
$parsed['id_base'] = $matches[1];
- $parsed['number'] = intval( $matches[2] );
+ $parsed['number'] = (int) $matches[2];
} else {
// Likely an old single widget.
$parsed['id_base'] = $widget_id;
@@ -628,7 +652,7 @@
}
$id_base = $matches[2];
- $number = isset( $matches[3] ) ? intval( $matches[3] ) : null;
+ $number = isset( $matches[3] ) ? (int) $matches[3] : null;
return compact( 'id_base', 'number' );
}
@@ -805,6 +829,49 @@
'data',
sprintf( 'var _wpCustomizeWidgetsSettings = %s;', wp_json_encode( $settings ) )
);
+
+ /*
+ * TODO: Update 'wp-customize-widgets' to not rely so much on things in
+ * 'customize-widgets'. This will let us skip most of the above and not
+ * enqueue 'customize-widgets' which saves bytes.
+ */
+
+ if ( wp_use_widgets_block_editor() ) {
+ $block_editor_context = new WP_Block_Editor_Context();
+
+ $editor_settings = get_block_editor_settings(
+ get_legacy_widget_block_editor_settings(),
+ $block_editor_context
+ );
+
+ wp_add_inline_script(
+ 'wp-customize-widgets',
+ sprintf(
+ 'wp.domReady( function() {
+ wp.customizeWidgets.initialize( "widgets-customizer", %s );
+ } );',
+ wp_json_encode( $editor_settings )
+ )
+ );
+
+ // Preload server-registered block schemas.
+ wp_add_inline_script(
+ 'wp-blocks',
+ 'wp.blocks.unstable__bootstrapServerSideBlockDefinitions(' . wp_json_encode( get_block_editor_server_block_settings() ) . ');'
+ );
+
+ wp_add_inline_script(
+ 'wp-blocks',
+ sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( get_block_categories( $block_editor_context ) ) ),
+ 'after'
+ );
+
+ wp_enqueue_script( 'wp-customize-widgets' );
+ wp_enqueue_style( 'wp-customize-widgets' );
+
+ /** This action is documented in edit-form-blocks.php */
+ do_action( 'enqueue_block_editor_assets' );
+ }
}
/**
@@ -888,8 +955,13 @@
$args['sanitize_js_callback'] = array( $this, 'sanitize_sidebar_widgets_js_instance' );
$args['transport'] = current_theme_supports( 'customize-selective-refresh-widgets' ) ? 'postMessage' : 'refresh';
} elseif ( preg_match( $this->setting_id_patterns['widget_instance'], $id, $matches ) ) {
- $args['sanitize_callback'] = array( $this, 'sanitize_widget_instance' );
- $args['sanitize_js_callback'] = array( $this, 'sanitize_widget_js_instance' );
+ $id_base = $matches['id_base'];
+ $args['sanitize_callback'] = function( $value ) use ( $id_base ) {
+ return $this->sanitize_widget_instance( $value, $id_base );
+ };
+ $args['sanitize_js_callback'] = function( $value ) use ( $id_base ) {
+ return $this->sanitize_widget_js_instance( $value, $id_base );
+ };
$args['transport'] = $this->is_widget_selective_refreshable( $matches['id_base'] ) ? 'postMessage' : 'refresh';
}
@@ -1109,6 +1181,23 @@
}
/**
+ * Tells the script loader to load the scripts and styles of custom blocks
+ * if the widgets block editor is enabled.
+ *
+ * @since 5.8.0
+ *
+ * @param bool $is_block_editor_screen Current decision about loading block assets.
+ * @return bool Filtered decision about loading block assets.
+ */
+ public function should_load_block_editor_scripts_and_styles( $is_block_editor_screen ) {
+ if ( wp_use_widgets_block_editor() ) {
+ return true;
+ }
+
+ return $is_block_editor_screen;
+ }
+
+ /**
* When previewing, ensures the proper previewing widgets are used.
*
* Because wp_get_sidebars_widgets() gets called early at {@see 'init' } (via
@@ -1312,18 +1401,42 @@
* only get applied to an instance *once*.
*
* @since 3.9.0
+ * @since 5.8.0 Added the `$id_base` parameter.
*
- * @param array $value Widget instance to sanitize.
+ * @global WP_Widget_Factory $wp_widget_factory
+ *
+ * @param array $value Widget instance to sanitize.
+ * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null.
* @return array|void Sanitized widget instance.
*/
- public function sanitize_widget_instance( $value ) {
+ public function sanitize_widget_instance( $value, $id_base = null ) {
+ global $wp_widget_factory;
+
if ( array() === $value ) {
return $value;
}
- if ( empty( $value['is_widget_customizer_js_value'] )
- || empty( $value['instance_hash_key'] )
- || empty( $value['encoded_serialized_instance'] ) ) {
+ if ( isset( $value['raw_instance'] ) && $id_base && wp_use_widgets_block_editor() ) {
+ $widget_object = $wp_widget_factory->get_widget_object( $id_base );
+ if ( ! empty( $widget_object->widget_options['show_instance_in_rest'] ) ) {
+ if ( 'block' === $id_base && ! current_user_can( 'unfiltered_html' ) ) {
+ /*
+ * The content of the 'block' widget is not filtered on the
+ * fly while editing. Filter the content here to prevent
+ * vulnerabilities.
+ */
+ $value['raw_instance']['content'] = wp_kses_post( $value['raw_instance']['content'] );
+ }
+
+ return $value['raw_instance'];
+ }
+ }
+
+ if (
+ empty( $value['is_widget_customizer_js_value'] ) ||
+ empty( $value['instance_hash_key'] ) ||
+ empty( $value['encoded_serialized_instance'] )
+ ) {
return;
}
@@ -1348,21 +1461,37 @@
* Converts a widget instance into JSON-representable format.
*
* @since 3.9.0
+ * @since 5.8.0 Added the `$id_base` parameter.
*
- * @param array $value Widget instance to convert to JSON.
+ * @global WP_Widget_Factory $wp_widget_factory
+ *
+ * @param array $value Widget instance to convert to JSON.
+ * @param string $id_base Optional. Base of the ID of the widget being sanitized. Default null.
* @return array JSON-converted widget instance.
*/
- public function sanitize_widget_js_instance( $value ) {
+ public function sanitize_widget_js_instance( $value, $id_base = null ) {
+ global $wp_widget_factory;
+
if ( empty( $value['is_widget_customizer_js_value'] ) ) {
$serialized = serialize( $value );
- $value = array(
+ $js_value = array(
'encoded_serialized_instance' => base64_encode( $serialized ),
'title' => empty( $value['title'] ) ? '' : $value['title'],
'is_widget_customizer_js_value' => true,
'instance_hash_key' => $this->get_instance_hash_key( $serialized ),
);
+
+ if ( $id_base && wp_use_widgets_block_editor() ) {
+ $widget_object = $wp_widget_factory->get_widget_object( $id_base );
+ if ( ! empty( $widget_object->widget_options['show_instance_in_rest'] ) ) {
+ $js_value['raw_instance'] = (object) $value;
+ }
+ }
+
+ return $js_value;
}
+
return $value;
}
@@ -1432,7 +1561,7 @@
return new WP_Error( 'widget_setting_malformed' );
}
- $instance = $this->sanitize_widget_instance( $sanitized_widget_setting );
+ $instance = $this->sanitize_widget_instance( $sanitized_widget_setting, $parsed_id['id_base'] );
if ( is_null( $instance ) ) {
$this->stop_capturing_option_updates();
return new WP_Error( 'widget_setting_unsanitized' );
@@ -1498,7 +1627,7 @@
* 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, $this->sanitize_widget_js_instance( $instance ) );
+ $this->manager->set_post_value( $setting_id, $this->sanitize_widget_js_instance( $instance, $parsed_id['id_base'] ) );
// Obtain the widget control with the updated instance in place.
ob_start();
@@ -1571,7 +1700,7 @@
}
$form = $updated_widget['form'];
- $instance = $this->sanitize_widget_js_instance( $updated_widget['instance'] );
+ $instance = $this->sanitize_widget_js_instance( $updated_widget['instance'], $id_base );
wp_send_json_success( compact( 'form', 'instance' ) );
}
@@ -1772,7 +1901,7 @@
}
$this->sidebar_instance_count[ $index ] += 1;
if ( ! $this->manager->selective_refresh->is_render_partials_request() ) {
- printf( "\n<!--dynamic_sidebar_before:%s:%d-->\n", esc_html( $index ), intval( $this->sidebar_instance_count[ $index ] ) );
+ printf( "\n<!--dynamic_sidebar_before:%s:%d-->\n", esc_html( $index ), (int) $this->sidebar_instance_count[ $index ] );
}
}
@@ -1788,7 +1917,7 @@
public function end_dynamic_sidebar( $index ) {
array_shift( $this->current_dynamic_sidebar_id_stack );
if ( ! $this->manager->selective_refresh->is_render_partials_request() ) {
- printf( "\n<!--dynamic_sidebar_after:%s:%d-->\n", esc_html( $index ), intval( $this->sidebar_instance_count[ $index ] ) );
+ printf( "\n<!--dynamic_sidebar_after:%s:%d-->\n", esc_html( $index ), (int) $this->sidebar_instance_count[ $index ] );
}
}
@@ -1851,7 +1980,7 @@
$this->rendering_sidebar_id = $context['sidebar_id'];
if ( isset( $context['sidebar_instance_number'] ) ) {
- $this->context_sidebar_instance_number = intval( $context['sidebar_instance_number'] );
+ $this->context_sidebar_instance_number = (int) $context['sidebar_instance_number'];
}
// Filter sidebars_widgets so that only the queried widget is in the sidebar.