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

Add backports for 5.7 RC 1 #29191

Merged
merged 4 commits into from
Feb 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2,157 changes: 2,157 additions & 0 deletions 5.7-changes-2.diff

Large diffs are not rendered by default.

11,328 changes: 11,328 additions & 0 deletions 5.7-changes.diff

Large diffs are not rendered by default.

87 changes: 84 additions & 3 deletions lib/class-wp-widget-block.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class WP_Widget_Block extends WP_Widget {
*/
public function __construct() {
$widget_ops = array(
'classname' => 'widget_block',
'classname' => '%s', // Set dynamically in widget().
'description' => __( 'Gutenberg block.', 'gutenberg' ),
'customize_selective_refresh' => true,
);
Expand All @@ -53,8 +53,8 @@ public function __construct() {
* @global WP_Post $post Global post object.
*/
public function widget( $args, $instance ) {
echo $args['before_widget'];
$content = do_blocks( $instance['content'] );
echo sprintf( $args['before_widget'], $this->get_dynamic_classname( $instance ) );
echo do_blocks( $instance['content'] );

// Handle embeds for block widgets.
//
Expand All @@ -68,6 +68,87 @@ public function widget( $args, $instance ) {
echo $args['after_widget'];
}

/**
* Calculates the classname to use in the block widget's container HTML.
*
* Usually this is set to $this->widget_options['classname'] by
* dynamic_sidebar(). In this case, however, we want to set the classname
* dynamically depending on the block conatined by this block widget.
*
* If a block widget contains a block that has an equivelant legacy widget,
* we display that legacy widget's class name. This helps with theme
* backwards compatibility.
*
* @since 9.3.0
*
* @param array $instance Settings for the current block widget instance.
*
* @return string The classname to use in the block widget's container HTML.
*/
private function get_dynamic_classname( $instance ) {
$blocks = parse_blocks( $instance['content'] );

$block_name = isset( $blocks[0] ) ? $blocks[0]['blockName'] : null;

switch ( $block_name ) {
case 'core/paragraph':
$classname = 'widget_block widget_text';
break;
case 'core/calendar':
$classname = 'widget_block widget_calendar';
break;
case 'core/search':
$classname = 'widget_block widget_search';
break;
case 'core/html':
$classname = 'widget_block widget_custom_html';
break;
case 'core/archives':
$classname = 'widget_block widget_archive';
break;
case 'core/latest-posts':
$classname = 'widget_block widget_recent_entries';
break;
case 'core/latest-comments':
$classname = 'widget_block widget_recent_comments';
break;
case 'core/tag-cloud':
$classname = 'widget_block widget_tag_cloud';
break;
case 'core/categories':
$classname = 'widget_block widget_categories';
break;
case 'core/audio':
$classname = 'widget_block widget_media_audio';
break;
case 'core/video':
$classname = 'widget_block widget_media_video';
break;
case 'core/image':
$classname = 'widget_block widget_media_image';
break;
case 'core/gallery':
$classname = 'widget_block widget_media_gallery';
break;
case 'core/rss':
$classname = 'widget_block widget_rss';
break;
default:
$classname = 'widget_block';
}

/**
* The classname used in the block widget's container HTML.
*
* This can be set according to the name of the block contained by the
* block widget.
*
* @param string $classname The classname to be used in the block widget's container HTML, e.g. 'widget_block widget_text'.
* @param string $block_name The name of the block contained by the block widget, e.g. 'core/paragraph'.
*/
return apply_filters( 'widget_block_dynamic_classname', $classname, $block_name );
}

/**
* Handles updating settings for the current Block widget instance.
*
Expand Down
5 changes: 4 additions & 1 deletion packages/block-editor/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { castArray, findKey, first, last, some } from 'lodash';
*/
import {
cloneBlock,
__experimentalCloneSanitizedBlock,
createBlock,
doBlocksMatchTemplate,
getBlockType,
Expand Down Expand Up @@ -1223,7 +1224,9 @@ export function* duplicateBlocks( clientIds, updateSelection = true ) {
last( castArray( clientIds ) ),
rootClientId
);
const clonedBlocks = blocks.map( ( block ) => cloneBlock( block ) );
const clonedBlocks = blocks.map( ( block ) =>
__experimentalCloneSanitizedBlock( block )
);
yield insertBlocks(
clonedBlocks,
lastSelectedIndex + 1,
Expand Down
4 changes: 4 additions & 0 deletions packages/blocks/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Change

- Reverted `cloneBlock` back to its original logic that doesn't sanitize block's attributes. [#28379](https://github.com/WordPress/gutenberg/pull/29111)

## 7.0.0 (2021-02-01)

### Breaking Change
Expand Down
4 changes: 2 additions & 2 deletions packages/blocks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ In the random image block above, we've given the `alt` attribute of the image a

<a name="cloneBlock" href="#cloneBlock">#</a> **cloneBlock**

Given a block object, returns a copy of the block object, optionally merging
new attributes and/or replacing its inner blocks.
Given a block object, returns a copy of the block object,
optionally merging new attributes and/or replacing its inner blocks.

_Parameters_

Expand Down
38 changes: 35 additions & 3 deletions packages/blocks/src/api/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,20 @@ export function createBlocksFromInnerBlocksTemplate(
}

/**
* Given a block object, returns a copy of the block object, optionally merging
* new attributes and/or replacing its inner blocks.
* Given a block object, returns a copy of the block object while sanitizing its attributes,
* optionally merging new attributes and/or replacing its inner blocks.
*
* @param {Object} block Block instance.
* @param {Object} mergeAttributes Block attributes.
* @param {?Array} newInnerBlocks Nested blocks.
*
* @return {Object} A cloned block.
*/
export function cloneBlock( block, mergeAttributes = {}, newInnerBlocks ) {
export function __experimentalCloneSanitizedBlock(
block,
mergeAttributes = {},
newInnerBlocks
) {
const clientId = uuid();

const sanitizedAttributes = sanitizeBlockAttributes( block.name, {
Expand All @@ -109,6 +113,34 @@ export function cloneBlock( block, mergeAttributes = {}, newInnerBlocks ) {
...block,
clientId,
attributes: sanitizedAttributes,
innerBlocks:
newInnerBlocks ||
block.innerBlocks.map( ( innerBlock ) =>
__experimentalCloneSanitizedBlock( innerBlock )
),
};
}

/**
* Given a block object, returns a copy of the block object,
* optionally merging new attributes and/or replacing its inner blocks.
*
* @param {Object} block Block instance.
* @param {Object} mergeAttributes Block attributes.
* @param {?Array} newInnerBlocks Nested blocks.
*
* @return {Object} A cloned block.
*/
export function cloneBlock( block, mergeAttributes = {}, newInnerBlocks ) {
const clientId = uuid();

return {
...block,
clientId,
attributes: {
...block.attributes,
...mergeAttributes,
},
innerBlocks:
newInnerBlocks ||
block.innerBlocks.map( ( innerBlock ) => cloneBlock( innerBlock ) ),
Expand Down
1 change: 1 addition & 0 deletions packages/blocks/src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export {
createBlock,
createBlocksFromInnerBlocksTemplate,
cloneBlock,
__experimentalCloneSanitizedBlock,
getPossibleBlockTransformations,
switchToBlockType,
getBlockTransforms,
Expand Down
5 changes: 4 additions & 1 deletion packages/blocks/src/api/test/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
createBlock,
createBlocksFromInnerBlocksTemplate,
cloneBlock,
__experimentalCloneSanitizedBlock,
getPossibleBlockTransformations,
switchToBlockType,
getBlockTransforms,
Expand Down Expand Up @@ -424,7 +425,9 @@ describe( 'block factory', () => {
block.innerBlocks[ 1 ].attributes
);
} );
} );

describe( '__experimentalCloneSanitizedBlock', () => {
it( 'should sanitize attributes not defined in the block type', () => {
registerBlockType( 'core/test-block', {
...defaultBlockSettings,
Expand All @@ -439,7 +442,7 @@ describe( 'block factory', () => {
notDefined: 'not-defined',
} );

const clonedBlock = cloneBlock( block, {
const clonedBlock = __experimentalCloneSanitizedBlock( block, {
notDefined2: 'not-defined-2',
} );

Expand Down
8 changes: 8 additions & 0 deletions packages/compose/src/hooks/use-focus-return/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ function useFocusReturn( onFocusReturn ) {

focusedBeforeMount.current = node.ownerDocument.activeElement;
} else if ( focusedBeforeMount.current ) {
const isFocused = ref.current.contains(
ref.current.ownerDocument.activeElement
);

if ( ref.current.isConnected && ! isFocused ) {
return;
}

// Defer to the component's own explicit focus return behavior, if
// specified. This allows for support that the `onFocusReturn`
// decides to allow the default behavior to occur under some
Expand Down
Loading