-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
i18n: Add pattern block #33217
i18n: Add pattern block #33217
Changes from 28 commits
d9c7863
2f131bc
e27ef10
587d496
fb50aa7
46893b3
f7eafa7
86dd396
1c7e99e
224c108
8979ee4
cae2c3c
25c26b4
3d9ece5
6a9e3ef
20936da
3e602b4
076a4de
82a2450
3e8d7b8
90619bb
4fc64ba
a2adecf
0cb327b
e88bcdf
4497b0e
3843b3e
f1ca663
1f5714b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"apiVersion": 2, | ||
"name": "core/pattern", | ||
"title": "Pattern", | ||
"category": "design", | ||
"description": "Show a block pattern.", | ||
"supports": { | ||
"html": false, | ||
"inserter": false | ||
}, | ||
"textdomain": "default", | ||
"attributes": { | ||
"slug": { | ||
"type": "string" | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useSelect, useDispatch } from '@wordpress/data'; | ||
import { useEffect } from '@wordpress/element'; | ||
import { | ||
store as blockEditorStore, | ||
useBlockProps, | ||
__experimentalUseInnerBlocksProps as useInnerBlocksProps, | ||
} from '@wordpress/block-editor'; | ||
import { createBlock } from '@wordpress/blocks'; | ||
|
||
const PatternEdit = ( { attributes, clientId, isSelected } ) => { | ||
const selectedPattern = useSelect( | ||
( select ) => | ||
select( blockEditorStore ).__experimentalGetParsedPattern( | ||
attributes.slug | ||
), | ||
[ attributes.slug ] | ||
); | ||
|
||
const hasSelection = useSelect( | ||
( select ) => | ||
isSelected || | ||
select( blockEditorStore ).hasSelectedInnerBlock( clientId, true ), | ||
[ isSelected, clientId ] | ||
); | ||
|
||
const { | ||
replaceBlocks, | ||
replaceInnerBlocks, | ||
__unstableMarkNextChangeAsNotPersistent, | ||
} = useDispatch( blockEditorStore ); | ||
|
||
// Run this effect when the block, or any of its InnerBlocks are selected. | ||
// This replaces the Pattern block wrapper with a Group block. | ||
// This ensures the markup structure and alignment are consistent between editor and view. | ||
// This change won't be saved unless further changes are made to the InnerBlocks. | ||
useEffect( () => { | ||
if ( hasSelection && selectedPattern?.blocks ) { | ||
__unstableMarkNextChangeAsNotPersistent(); | ||
replaceBlocks( | ||
clientId, | ||
createBlock( 'core/group', {}, selectedPattern.blocks ) | ||
); | ||
} | ||
}, [ hasSelection, selectedPattern?.blocks ] ); | ||
|
||
// Run this effect when the component loads. | ||
// This adds the Pattern block template as InnerBlocks. | ||
// This change won't be saved. | ||
useEffect( () => { | ||
if ( selectedPattern?.blocks ) { | ||
__unstableMarkNextChangeAsNotPersistent(); | ||
replaceInnerBlocks( clientId, selectedPattern.blocks ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean that in the editor, we kind of "never keep" the patterns block rendered and just it to fetch the pattern initially and replace the block entirely? In which case the "div" wrapper doesn't matter since this block is never actually visible in the editor. And in fact in the frontend, "no div" is better since when replacing the blocks here we're removing the temporary wrapper. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's important is to be consistent There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we wait for the the block to be selected to replace it with its inner blocks? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
IIRC, to avoid dirtying the post. See #33217 (comment). But it might just be better to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reasoning is that if you open the site editor but then you only make modifications to the header or footer but not the pattern itself, you'll still be pulling the pattern from PHP. This means that if the pattern is updated in the future you'll see the newer version, unless you have actively changed it, which is the same behaviour as templates in general. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This seems like the opposite of the explantation here? #33217 (comment) Anyway, if this is the behavior we want, we should always have a div wrapper which means:
The other possibility is to remove the temporary state and remove the divs everywhere. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I tried this in 7620b99. The result is:
|
||
} | ||
}, [ selectedPattern?.blocks ] ); | ||
|
||
const props = useInnerBlocksProps( useBlockProps(), {} ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure if I implemented this correctly — does anything need to be supplied here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think props are optional. |
||
|
||
return <div { ...props } />; | ||
}; | ||
|
||
export default PatternEdit; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import metadata from './block.json'; | ||
import PatternEdit from './edit'; | ||
|
||
const { name } = metadata; | ||
export { metadata, name }; | ||
|
||
export const settings = { | ||
edit: PatternEdit, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php | ||
/** | ||
* Server-side rendering of the `core/pattern` block. | ||
* | ||
* @package WordPress | ||
*/ | ||
|
||
/** | ||
* Registers the `core/pattern` block on the server. | ||
* | ||
* @return void | ||
*/ | ||
function register_block_core_pattern() { | ||
register_block_type_from_metadata( | ||
__DIR__ . '/pattern', | ||
array( | ||
'render_callback' => 'render_block_core_pattern', | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Renders the `core/pattern` block on the server. | ||
* | ||
* @param array $attributes Block attributes. | ||
* | ||
* @return string Returns the output of the pattern. | ||
*/ | ||
function render_block_core_pattern( $attributes ) { | ||
if ( empty( $attributes['slug'] ) ) { | ||
return ''; | ||
} | ||
|
||
$slug = $attributes['slug']; | ||
$registry = WP_Block_Patterns_Registry::get_instance(); | ||
if ( ! $registry->is_registered( $slug ) ) { | ||
return ''; | ||
} | ||
|
||
$pattern = $registry->get_registered( $slug ); | ||
return do_blocks( '<div>' . $pattern['content'] . '</div>' ); | ||
} | ||
|
||
add_action( 'init', 'register_block_core_pattern' ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<!-- wp:pattern {"slug":"core/text-two-columns"} /--> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[ | ||
{ | ||
"clientId": "_clientId_0", | ||
"name": "core/pattern", | ||
"isValid": true, | ||
"attributes": { | ||
"slug": "core/text-two-columns" | ||
}, | ||
"innerBlocks": [], | ||
"originalContent": "" | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[ | ||
{ | ||
"blockName": "core/pattern", | ||
"attrs": { | ||
"slug": "core/text-two-columns" | ||
}, | ||
"innerBlocks": [], | ||
"innerHTML": "", | ||
"innerContent": [] | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<!-- wp:pattern {"slug":"core/text-two-columns"} /--> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the user changes something else in the template outside the pattern block, it will also save a "copy" of the pattern in the template and not reference the pattern anymore, is this intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the way that patterns work in general, so I think yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I misread you here, sorry. I think if the user changes the pattern then we should save a copy, but if they change other things in the template the pattern should still be loaded from the file.