Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First patch of backports/fixes for WordPress 5.8 beta 2 #32653

Merged
merged 20 commits into from
Jun 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a8d2475
Fix block multi selection in nested blocks (#32536)
talldan Jun 10, 2021
11e57ea
Save deleted and restored widgets. (#32534)
tellthemachines Jun 10, 2021
8629186
Widgets editor: Add Breadcrumbs Block (#32498)
ramonjd Jun 10, 2021
beaaf60
Enqueue core and theme colors by using separate structures per origin…
jorgefilipecosta Jun 10, 2021
3436129
Drop indicator: show around dragged block and show above selected blo…
ellatrix Jun 10, 2021
ab5043f
Widgets editor: Fix dirty state after adding new block (#32573)
noisysocks Jun 11, 2021
d26692b
Widget Editor: Fix button spacing in header (#32585)
Mamaduka Jun 11, 2021
0521fb3
Editor Breadcrumb: add a `rootLabelText` prop (#32528)
ramonjd Jun 10, 2021
0f1bec8
[Widgets screen] Don't add undo levels when editing records on save (…
tellthemachines Jun 11, 2021
9921f4e
Move Legacy Widget block to @wordpress/widgets (#32501)
noisysocks Jun 11, 2021
388b7e3
Drop zone: fix horizontal indicator (#32589)
ellatrix Jun 11, 2021
622b612
Fix Safari 13 issue. (#32581)
jasmussen Jun 11, 2021
a68b766
Widgets: Try to fix color inheritance for social links. (#32625)
jasmussen Jun 11, 2021
207ceec
Use button block appender in widget areas (#32580)
kevin940726 Jun 11, 2021
ad119ad
Performance: Remove `is-typing` root class (#32567)
gwwar Jun 11, 2021
6c6a656
Update the template creation modal (#32427)
jameskoster Jun 14, 2021
d7754fc
Only add the content skip link for block templates (#32451)
aristath Jun 14, 2021
5c8ef44
Widgets Editor: add show block bread crumbs feature toggle to more me…
ramonjd Jun 14, 2021
e6d5e95
Update WP_Theme_JSON API so presets are always keyed by origin (#32622)
nosolosw Jun 14, 2021
ac71416
useSelect: silently error (for block zombie children) (#32088)
ellatrix Jun 14, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions docs/how-to-guides/widgets/legacy-widget-block.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,49 @@ function hide_example_widget( $widget_types ) {
}
add_filter( 'widget_types_to_hide_from_legacy_widget_block', 'hide_example_widget' );
```

## Using the Legacy Widget block in other block editors (Advanced)

You may optionally allow the Legacy Widget block in other block editors such as
the WordPress post editor. This is not enabled by default.

First, ensure that any styles and scripts required by the legacy widgets are
loaded onto the page. A convenient way of doing this is to manually perform all
of the hooks that ordinarily run when a user browses to the widgets WP Admin
screen.

```php
add_action( 'admin_print_styles', function() {
if ( get_current_screen()->is_block_editor() ) {
do_action( 'admin_print_styles-widgets.php' );
}
} );
add_action( 'admin_print_scripts', function() {
if ( get_current_screen()->is_block_editor() ) {
do_action( 'load-widgets.php' );
do_action( 'widgets.php' );
do_action( 'sidebar_admin_setup' );
do_action( 'admin_print_scripts-widgets.php' );
}
} );
add_action( 'admin_print_footer_scripts', function() {
if ( get_current_screen()->is_block_editor() ) {
do_action( 'admin_print_footer_scripts-widgets.php' );
}
} );
add_action( 'admin_footer', function() {
if ( get_current_screen()->is_block_editor() ) {
do_action( 'admin_footer-widgets.php' );
}
} );
```

Then, register the Legacy Widget block using `registerLegacyWidgetBlock` which
is defined in the `@wordpress/widgets` package.

```php
add_action( 'enqueue_block_editor_assets', function() {
wp_enqueue_script( 'wp-widgets' );
wp_add_inline_script( 'wp-widgets', 'wp.widgets.registerLegacyWidgetBlock()' );
} );
```
27 changes: 7 additions & 20 deletions lib/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,6 @@
* @package gutenberg
*/

/*
* Fixes the priority of register_block_core_legacy_widget().
*
* This hook was incorrectly added to Core with priority 20. #32300 fixes this
* but causes block registration warnings in the Gutenberg plugin until the
* changes are made in Core.
*
* This temporary fix can be removed after the changes to
* @wordpress/block-library in #32300 have been published to npm and updated in
* Core.
*
* See https://github.com/WordPress/gutenberg/pull/32300.
*/
if ( 20 === has_action( 'init', 'register_block_core_legacy_widget' ) ) {
remove_action( 'init', 'register_block_core_legacy_widget', 20 );
add_action( 'init', 'register_block_core_legacy_widget', 10 );
}

/**
* Substitutes the implementation of a core-registered block type, if exists,
* with the built result from the plugin.
Expand Down Expand Up @@ -74,7 +56,6 @@ function gutenberg_reregister_core_block_types() {
'file.php' => 'core/file',
'latest-comments.php' => 'core/latest-comments',
'latest-posts.php' => 'core/latest-posts',
'legacy-widget.php' => 'core/legacy-widget',
'loginout.php' => 'core/loginout',
'navigation.php' => 'core/navigation',
'navigation-link.php' => 'core/navigation-link',
Expand Down Expand Up @@ -120,8 +101,14 @@ function gutenberg_reregister_core_block_types() {
'block_folders' => array(
'widget-area',
),
'block_names' => array(),
),
__DIR__ . '/../build/widgets/blocks/' => array(
'block_folders' => array(
'legacy-widget',
),
'block_names' => array(
'widget-area.php' => 'core/widget-area',
'legacy-widget.php' => 'core/legacy-widget',
),
),
);
Expand Down
188 changes: 99 additions & 89 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class WP_Theme_JSON_Gutenberg {
*/
const ROOT_BLOCK_SELECTOR = 'body';

const VALID_ORIGINS = array(
'core',
'theme',
'user',
);

const VALID_TOP_LEVEL_KEYS = array(
'customTemplates',
'templateParts',
Expand Down Expand Up @@ -272,9 +278,14 @@ class WP_Theme_JSON_Gutenberg {
/**
* Constructor.
*
* @param array $theme_json A structure that follows the theme.json schema.
* @param array $theme_json A structure that follows the theme.json schema.
* @param string $origin What source of data this object represents. One of core, theme, or user. Default: theme.
*/
public function __construct( $theme_json = array() ) {
public function __construct( $theme_json = array(), $origin = 'theme' ) {
if ( ! in_array( $origin, self::VALID_ORIGINS, true ) ) {
$origin = 'theme';
}

// The old format is not meant to be ported to core.
// We can remove it at that point.
if ( ! isset( $theme_json['version'] ) || 0 === $theme_json['version'] ) {
Expand All @@ -284,6 +295,18 @@ public function __construct( $theme_json = array() ) {
$valid_block_names = array_keys( self::get_blocks_metadata() );
$valid_element_names = array_keys( self::ELEMENTS );
$this->theme_json = self::sanitize( $theme_json, $valid_block_names, $valid_element_names );

// Internally, presets are keyed by origin.
$nodes = self::get_setting_nodes( $this->theme_json );
foreach ( $nodes as $node ) {
foreach ( self::PRESETS_METADATA as $preset ) {
$path = array_merge( $node['path'], $preset['path'] );
$preset = _wp_array_get( $this->theme_json, $path, array() );
if ( ! empty( $preset ) ) {
gutenberg_experimental_set( $this->theme_json, $path, array( $origin => $preset ) );
}
}
}
}

/**
Expand Down Expand Up @@ -641,6 +664,33 @@ private static function append_to_selector( $selector, $to_append ) {
return implode( ',', $new_selectors );
}

/**
* Function that given an array of presets keyed by origin
* and the value key of the preset returns an array where each key is
* the a preset slug and each value is the preset value.
*
* @param array $preset_per_origin Array of presets keyed by origin.
* @param string $value_key The property of the preset that contains its value.
*
* @return array Array of presets where each key is a slug and each value is the preset value.
*/
private static function get_merged_preset_by_slug( $preset_per_origin, $value_key ) {
$result = array();
foreach ( self::VALID_ORIGINS as $origin ) {
if ( ! isset( $preset_per_origin[ $origin ] ) ) {
continue;
}
foreach ( $preset_per_origin[ $origin ] as $preset ) {
// We don't want to use kebabCase here,
// see https://github.com/WordPress/gutenberg/issues/32347
// However, we need to make sure the generated class or css variable
// doesn't contain spaces.
$result[ preg_replace( '/\s+/', '-', $preset['slug'] ) ] = $preset[ $value_key ];
}
}
return $result;
}

/**
* Given a settings array, it returns the generated rulesets
* for the preset classes.
Expand All @@ -659,19 +709,16 @@ private static function compute_preset_classes( $settings, $selector ) {

$stylesheet = '';
foreach ( self::PRESETS_METADATA as $preset ) {
$values = _wp_array_get( $settings, $preset['path'], array() );
foreach ( $values as $value ) {
foreach ( $preset['classes'] as $class ) {
$preset_per_origin = _wp_array_get( $settings, $preset['path'], array() );
$preset_by_slug = self::get_merged_preset_by_slug( $preset_per_origin, $preset['value_key'] );
foreach ( $preset['classes'] as $class ) {
foreach ( $preset_by_slug as $slug => $value ) {
$stylesheet .= self::to_ruleset(
// We don't want to use kebabCase here,
// see https://github.com/WordPress/gutenberg/issues/32347
// However, we need to make sure the generated class
// doesn't contain spaces.
self::append_to_selector( $selector, '.has-' . preg_replace( '/\s+/', '-', $value['slug'] ) . '-' . $class['class_suffix'] ),
self::append_to_selector( $selector, '.has-' . $slug . '-' . $class['class_suffix'] ),
array(
array(
'name' => $class['property_name'],
'value' => $value[ $preset['value_key'] ] . ' !important',
'value' => $value . ' !important',
),
)
);
Expand Down Expand Up @@ -701,11 +748,12 @@ private static function compute_preset_classes( $settings, $selector ) {
private static function compute_preset_vars( $settings ) {
$declarations = array();
foreach ( self::PRESETS_METADATA as $preset ) {
$values = _wp_array_get( $settings, $preset['path'], array() );
foreach ( $values as $value ) {
$preset_per_origin = _wp_array_get( $settings, $preset['path'], array() );
$preset_by_slug = self::get_merged_preset_by_slug( $preset_per_origin, $preset['value_key'] );
foreach ( $preset_by_slug as $slug => $value ) {
$declarations[] = array(
'name' => '--wp--preset--' . $preset['css_var_infix'] . '--' . $value['slug'],
'value' => $value[ $preset['value_key'] ],
'name' => '--wp--preset--' . $preset['css_var_infix'] . '--' . $slug,
'value' => $value,
);
}
}
Expand Down Expand Up @@ -1101,86 +1149,35 @@ public function get_stylesheet( $type = 'all' ) {
/**
* Merge new incoming data.
*
* @param WP_Theme_JSON_Gutenberg $incoming Data to merge.
* @param string $update_or_remove Whether update or remove existing colors
* for which the incoming data has a duplicated slug.
* @param WP_Theme_JSON $incoming Data to merge.
*/
public function merge( $incoming, $update_or_remove = 'remove' ) {
$incoming_data = $incoming->get_raw_data();
$existing_data = $this->theme_json;
public function merge( $incoming ) {
$incoming_data = $incoming->get_raw_data();
$this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data );

// The array_replace_recursive algorithm merges at the leaf level.
// For leaf values that are arrays it will use the numeric indexes for replacement.
$this->theme_json = array_replace_recursive( $this->theme_json, $incoming_data );

// There are a few cases in which we want to merge things differently
// from what array_replace_recursive does.

// Some incoming properties should replace the existing.
// In those cases, we want to replace the existing with the incoming value, if it exists.
$to_replace = array();
$to_replace[] = array( 'custom' );
$to_replace[] = array( 'spacing', 'units' );
$to_replace[] = array( 'typography', 'fontSizes' );
$to_replace[] = array( 'typography', 'fontFamilies' );

// Some others should be appended to the existing.
// If the slug is the same than an existing element,
// the $update_or_remove param is used to decide
// what to do with the existing element:
// either remove it and append the incoming,
// or update it with the incoming.
$to_append = array();
$to_append[] = array( 'color', 'duotone' );
$to_append[] = array( 'color', 'gradients' );
$to_append[] = array( 'color', 'palette' );
$to_replace[] = array( 'color', 'duotone' );
foreach ( self::VALID_ORIGINS as $origin ) {
$to_replace[] = array( 'color', 'palette', $origin );
$to_replace[] = array( 'color', 'gradients', $origin );
$to_replace[] = array( 'typography', 'fontSizes', $origin );
$to_replace[] = array( 'typography', 'fontFamilies', $origin );
}

$nodes = self::get_setting_nodes( $this->theme_json );
foreach ( $nodes as $metadata ) {
foreach ( $to_replace as $path_to_replace ) {
$path = array_merge( $metadata['path'], $path_to_replace );
foreach ( $to_replace as $property_path ) {
$path = array_merge( $metadata['path'], $property_path );
$node = _wp_array_get( $incoming_data, $path, array() );
if ( ! empty( $node ) ) {
gutenberg_experimental_set( $this->theme_json, $path, $node );
}
}
foreach ( $to_append as $path_to_append ) {
$path = array_merge( $metadata['path'], $path_to_append );
$incoming_node = _wp_array_get( $incoming_data, $path, array() );
$existing_node = _wp_array_get( $existing_data, $path, array() );

if ( empty( $incoming_node ) && empty( $existing_node ) ) {
continue;
}

$index_table = array();
$existing_slugs = array();
$merged = array();
foreach ( $existing_node as $key => $value ) {
$index_table[ $value['slug'] ] = $key;
$existing_slugs[] = $value['slug'];
$merged[ $key ] = $value;
}

$to_remove = array();
foreach ( $incoming_node as $value ) {
if ( ! in_array( $value['slug'], $existing_slugs, true ) ) {
$merged[] = $value;
} elseif ( 'update' === $update_or_remove ) {
$merged[ $index_table[ $value['slug'] ] ] = $value;
} else {
$merged[] = $value;
$to_remove[] = $index_table[ $value['slug'] ];
}
}

// Remove the duplicated values and pack the sparsed array.
foreach ( $to_remove as $index ) {
unset( $merged[ $index ] );
}
$merged = array_values( $merged );

gutenberg_experimental_set( $this->theme_json, $path, $merged );
}
}

}
Expand Down Expand Up @@ -1277,14 +1274,26 @@ private static function is_safe_css_declaration( $property_name, $property_value

/**
* Removes insecure data from theme.json.
*
* @param array $theme_json Structure to sanitize.
*
* @return array Sanitized structure.
*/
public function remove_insecure_properties() {
public static function remove_insecure_properties( $theme_json ) {
$sanitized = array();

if ( ! isset( $theme_json['version'] ) || 0 === $theme_json['version'] ) {
$theme_json = WP_Theme_JSON_Schema_V0::parse( $theme_json );
}

$valid_block_names = array_keys( self::get_blocks_metadata() );
$valid_element_names = array_keys( self::ELEMENTS );
$theme_json = self::sanitize( $theme_json, $valid_block_names, $valid_element_names );

$blocks_metadata = self::get_blocks_metadata();
$style_nodes = self::get_style_nodes( $this->theme_json, $blocks_metadata );
$style_nodes = self::get_style_nodes( $theme_json, $blocks_metadata );
foreach ( $style_nodes as $metadata ) {
$input = _wp_array_get( $this->theme_json, $metadata['path'], array() );
$input = _wp_array_get( $theme_json, $metadata['path'], array() );
if ( empty( $input ) ) {
continue;
}
Expand All @@ -1295,9 +1304,9 @@ public function remove_insecure_properties() {
}
}

$setting_nodes = self::get_setting_nodes( $this->theme_json );
$setting_nodes = self::get_setting_nodes( $theme_json );
foreach ( $setting_nodes as $metadata ) {
$input = _wp_array_get( $this->theme_json, $metadata['path'], array() );
$input = _wp_array_get( $theme_json, $metadata['path'], array() );
if ( empty( $input ) ) {
continue;
}
Expand All @@ -1309,17 +1318,18 @@ public function remove_insecure_properties() {
}

if ( empty( $sanitized['styles'] ) ) {
unset( $this->theme_json['styles'] );
unset( $theme_json['styles'] );
} else {
$this->theme_json['styles'] = $sanitized['styles'];
$theme_json['styles'] = $sanitized['styles'];
}

if ( empty( $sanitized['settings'] ) ) {
unset( $this->theme_json['settings'] );
unset( $theme_json['settings'] );
} else {
$this->theme_json['settings'] = $sanitized['settings'];
$theme_json['settings'] = $sanitized['settings'];
}

return $theme_json;
}

/**
Expand Down
Loading