From 32b0304361fe7651a4d3c2479e79ea1ecbf160d3 Mon Sep 17 00:00:00 2001 From: epiqueras Date: Fri, 10 Jan 2020 16:06:38 -0500 Subject: [PATCH 01/12] Block Library: Implement Post block. --- packages/block-library/src/editor.scss | 1 + packages/block-library/src/index.js | 2 + packages/block-library/src/post/block.json | 4 ++ packages/block-library/src/post/edit/index.js | 36 +++++++++++ .../src/post/edit/placeholder.js | 63 +++++++++++++++++++ packages/block-library/src/post/editor.scss | 24 +++++++ packages/block-library/src/post/index.js | 18 ++++++ 7 files changed, 148 insertions(+) create mode 100644 packages/block-library/src/post/block.json create mode 100644 packages/block-library/src/post/edit/index.js create mode 100644 packages/block-library/src/post/edit/placeholder.js create mode 100644 packages/block-library/src/post/editor.scss create mode 100644 packages/block-library/src/post/index.js diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index 6dc247b6d744a5..4d952405f3138e 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -28,6 +28,7 @@ @import "./navigation-link/editor.scss"; @import "./nextpage/editor.scss"; @import "./paragraph/editor.scss"; +@import "./post/editor.scss"; @import "./post-excerpt/editor.scss"; @import "./pullquote/editor.scss"; @import "./quote/editor.scss"; diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index 206c705651e9af..ecd760f7ec7925 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -65,6 +65,7 @@ import * as socialLink from './social-link'; // Full Site Editing Blocks import * as siteTitle from './site-title'; import * as templatePart from './template-part'; +import * as post from './post'; import * as postTitle from './post-title'; import * as postContent from './post-content'; import * as postAuthor from './post-author'; @@ -197,6 +198,7 @@ export const __experimentalRegisterExperimentalCoreBlocks = ? [ siteTitle, templatePart, + post, postTitle, postContent, postAuthor, diff --git a/packages/block-library/src/post/block.json b/packages/block-library/src/post/block.json new file mode 100644 index 00000000000000..a3a18677f871b1 --- /dev/null +++ b/packages/block-library/src/post/block.json @@ -0,0 +1,4 @@ +{ + "name": "core/post", + "category": "layout" +} diff --git a/packages/block-library/src/post/edit/index.js b/packages/block-library/src/post/edit/index.js new file mode 100644 index 00000000000000..7aa5a27282dd13 --- /dev/null +++ b/packages/block-library/src/post/edit/index.js @@ -0,0 +1,36 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { EntityProvider } from '@wordpress/core-data'; +import { InnerBlocks } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import PostPlaceholder from './placeholder'; + +export default function PostEdit( { attributes: { postId }, setAttributes } ) { + const loaded = useSelect( + ( select ) => { + if ( ! postId ) { + return false; + } + return Boolean( + select( 'core' ).getEntityRecord( 'postType', 'post', postId ) + ); + }, + [ postId ] + ); + if ( postId ) { + if ( ! loaded ) { + return null; + } + return ( + + + + ); + } + return ; +} diff --git a/packages/block-library/src/post/edit/placeholder.js b/packages/block-library/src/post/edit/placeholder.js new file mode 100644 index 00000000000000..b3cd06b2005158 --- /dev/null +++ b/packages/block-library/src/post/edit/placeholder.js @@ -0,0 +1,63 @@ +/** + * WordPress dependencies + */ +import { useEntityBlockEditor, EntityProvider } from '@wordpress/core-data'; +import { __ } from '@wordpress/i18n'; +import { BlockPreview } from '@wordpress/block-editor'; +import { useState, useCallback } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; +import { Placeholder, TextControl, Button } from '@wordpress/components'; + +function PostPreview() { + const [ blocks ] = useEntityBlockEditor( 'postType', 'post' ); + return ( +
+
+ { __( 'Preview' ) } +
+ +
+ ); +} + +export default function PostPlaceholder( { setAttributes } ) { + const [ postId, setPostId ] = useState(); + const preview = useSelect( + ( select ) => { + if ( ! postId ) { + return null; + } + const post = select( 'core' ).getEntityRecord( 'postType', 'post', postId ); + if ( post ) { + return ( + + + + ); + } + }, + [ postId ] + ); + const choosePostId = useCallback( () => setAttributes( { postId } ), [ postId ] ); + return ( + +
+ +
+ { preview } + +
+ ); +} diff --git a/packages/block-library/src/post/editor.scss b/packages/block-library/src/post/editor.scss new file mode 100644 index 00000000000000..8be69762be5500 --- /dev/null +++ b/packages/block-library/src/post/editor.scss @@ -0,0 +1,24 @@ +.wp-block-post__placeholder-input-container { + display: flex; + flex-wrap: wrap; + width: 100%; +} + +.wp-block-post__placeholder-preview { + margin-bottom: 15px; + width: 100%; + + .block-editor-block-preview__container { + padding: 1px; + } + + .block-editor-block-preview__content { + position: initial; + } +} + +.wp-block-post__placeholder-preview-title { + font-size: 15px; + font-weight: 600; + margin-bottom: 4px; +} diff --git a/packages/block-library/src/post/index.js b/packages/block-library/src/post/index.js new file mode 100644 index 00000000000000..8228b148d34082 --- /dev/null +++ b/packages/block-library/src/post/index.js @@ -0,0 +1,18 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import metadata from './block.json'; +import edit from './edit'; + +const { name } = metadata; +export { metadata, name }; + +export const settings = { + title: __( 'Post' ), + edit, +}; From 69842d63ffbaa04c9ccf0ff2fc24db5a999dd136 Mon Sep 17 00:00:00 2001 From: epiqueras Date: Fri, 10 Jan 2020 16:07:12 -0500 Subject: [PATCH 02/12] Block Library: Implement Post Content block editor. --- .../block-library/src/post-content/edit.js | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/block-library/src/post-content/edit.js b/packages/block-library/src/post-content/edit.js index 3336e0d8199676..1e16bd9e0f9b73 100644 --- a/packages/block-library/src/post-content/edit.js +++ b/packages/block-library/src/post-content/edit.js @@ -1,9 +1,27 @@ -export default function PostContentEdit() { +/** + * WordPress dependencies + */ +import { useEntityBlockEditor, useEntityId } from '@wordpress/core-data'; +import { InnerBlocks } from '@wordpress/block-editor'; + +function PostContentInnerBlocks() { + const [ blocks, onInput, onChange ] = useEntityBlockEditor( + 'postType', + 'post' + ); return ( -

- { - 'Welcome to WordPress and the wonderful world of blocks. This content represents how a post would look when editing block templates.' - } -

+ ); } + +export default function PostContentEdit() { + if ( ! useEntityId( 'postType', 'post' ) ) { + return 'Post Content Placeholder'; + } + + return ; +} From acc41baa51530e913f54fe9987f1297b04ccb2ca Mon Sep 17 00:00:00 2001 From: epiqueras Date: Fri, 10 Jan 2020 16:07:49 -0500 Subject: [PATCH 03/12] Block Library: Implement Post Title block editor. --- packages/block-library/src/post-title/edit.js | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/post-title/edit.js b/packages/block-library/src/post-title/edit.js index aa31586b212ab3..975c1a81efa925 100644 --- a/packages/block-library/src/post-title/edit.js +++ b/packages/block-library/src/post-title/edit.js @@ -1,3 +1,27 @@ +/** + * WordPress dependencies + */ +import { useEntityProp, useEntityId } from '@wordpress/core-data'; +import { RichText } from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; + +function PostTitleInput() { + const [ title, setTitle ] = useEntityProp( 'postType', 'post', 'title' ); + return ( + + ); +} + export default function PostTitleEdit() { - return

{ 'Hello world!' }

; + if ( ! useEntityId( 'postType', 'post' ) ) { + return 'Post Title Placeholder'; + } + + return ; } From 3e575d8f1dfb32df63b00005eb05691a7c475f29 Mon Sep 17 00:00:00 2001 From: epiqueras Date: Fri, 10 Jan 2020 19:47:33 -0500 Subject: [PATCH 04/12] Block Library: Implement Post block save. --- packages/block-library/src/post/index.js | 2 ++ packages/block-library/src/post/save.js | 8 ++++++++ 2 files changed, 10 insertions(+) create mode 100644 packages/block-library/src/post/save.js diff --git a/packages/block-library/src/post/index.js b/packages/block-library/src/post/index.js index 8228b148d34082..3d7ab2f8393b93 100644 --- a/packages/block-library/src/post/index.js +++ b/packages/block-library/src/post/index.js @@ -8,6 +8,7 @@ import { __ } from '@wordpress/i18n'; */ import metadata from './block.json'; import edit from './edit'; +import save from './save'; const { name } = metadata; export { metadata, name }; @@ -15,4 +16,5 @@ export { metadata, name }; export const settings = { title: __( 'Post' ), edit, + save, }; diff --git a/packages/block-library/src/post/save.js b/packages/block-library/src/post/save.js new file mode 100644 index 00000000000000..039b6d8e9efb1f --- /dev/null +++ b/packages/block-library/src/post/save.js @@ -0,0 +1,8 @@ +/** + * WordPress dependencies + */ +import { InnerBlocks } from '@wordpress/block-editor'; + +export default function PostSave() { + return ; +} From 9461576bbbc3c418cb2cbb1ebd89dc6e6364daff Mon Sep 17 00:00:00 2001 From: epiqueras Date: Sun, 19 Jan 2020 08:30:46 -0500 Subject: [PATCH 05/12] Lib: Implement server-side block context. --- lib/compat.php | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/lib/compat.php b/lib/compat.php index 6e68f2134b2cff..72f7ef13c3106c 100644 --- a/lib/compat.php +++ b/lib/compat.php @@ -125,3 +125,75 @@ function gutenberg_get_post_from_context() { } return get_post(); } + +/** + * Shim that hooks into `pre_render_block` so as to override `render_block` + * with a function that passes `render_callback` the block object as an + * argument and adds support for block context attributes. + * + * @param string $pre_render The pre-rendered content. Defaults to null. + * @param array $block The block being rendered. + * @param array $context The block context. + * + * @return string String of rendered HTML. + */ +function gutenberg_provide_render_callback_with_block_object( $pre_render, $block, $context = array() ) { + global $post; + + $source_block = $block; + /** This filter is documented in src/wp-includes/blocks.php */ + $block = apply_filters( 'render_block_data', $block, $source_block ); + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); + $is_dynamic = $block['blockName'] && null !== $block_type && $block_type->is_dynamic(); + $block_content = ''; + $index = 0; + + if ( ! is_array( $block['attrs'] ) ) { + $block['attrs'] = array(); + } + + $block['context'] = array(); + $next_context = $context; + if ( $block_type ) { + if ( isset( $block_type->context ) ) { + foreach ( $block_type->context as $attribute_name => $block_names ) { + $block_names = is_array( $block_names ) ? $block_names : array( $block_names ); + foreach ( $block_names as $block_name ) { + if ( isset( $context[ $block_name ][ $attribute_name ] ) ) { + $block['context'][ $attribute_name ] = $context[ $block_name ][ $attribute_name ]; + } + } + } + } + if ( isset( $block_type->attributes ) ) { + foreach ( $block_type->attributes as $attribute_name => $attribute_config ) { + if ( $attribute_config['context'] && isset( $block['attrs'][ $attribute_name ] ) ) { + if ( ! isset( $next_context[ $block['blockName'] ] ) ) { + $next_context[ $block['blockName'] ] = array(); + } + $next_context[ $block['blockName'] ][ $attribute_name ] = $block['attrs'][ $attribute_name ]; + } + } + } + } + + foreach ( $block['innerContent'] as $chunk ) { + if ( is_string( $chunk ) ) { + $block_content .= $chunk; + } else { + $inner_block = $block['innerBlocks'][ $index++ ]; + $block_content .= gutenberg_provide_render_callback_with_block_object( null, $inner_block, $next_context ); + } + } + + if ( $is_dynamic ) { + $global_post = $post; + + $prepared_attributes = $block_type->prepare_attributes_for_render( $block['attrs'] ); + $block_content = (string) call_user_func( $block_type->render_callback, $prepared_attributes, $block_content, $block ); + $post = $global_post; + } + /** This filter is documented in src/wp-includes/blocks.php */ + return apply_filters( 'render_block', $block_content, $block ); +} +add_filter( 'pre_render_block', 'gutenberg_provide_render_callback_with_block_object', 10, 2 ); From 4b61fb38720add43b3b63c7d24266bdae1ee3638 Mon Sep 17 00:00:00 2001 From: epiqueras Date: Sun, 19 Jan 2020 08:36:39 -0500 Subject: [PATCH 06/12] Block Editor: Implement client-side block context. --- .../components/block-list/block-context.js | 69 +++++++++++++++++++ .../src/components/block-list/block.js | 6 +- .../src/components/block-list/index.js | 5 +- 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 packages/block-editor/src/components/block-list/block-context.js diff --git a/packages/block-editor/src/components/block-list/block-context.js b/packages/block-editor/src/components/block-list/block-context.js new file mode 100644 index 00000000000000..1eb7dd784a4436 --- /dev/null +++ b/packages/block-editor/src/components/block-list/block-context.js @@ -0,0 +1,69 @@ +/** + * External dependencies + */ +import { castArray } from 'lodash'; + +/** + * WordPress dependencies + */ +import { createContext, useContext, useMemo } from '@wordpress/element'; + +const context = {}; +const getContext = ( blockName, attributeName ) => { + if ( ! context[ blockName ] ) { + context[ blockName ] = {}; + } + if ( ! context[ blockName ][ attributeName ] ) { + context[ blockName ][ attributeName ] = createContext(); + } + return context[ blockName ][ attributeName ]; +}; + +function Providers( { blockType, blockAttributes, children } ) { + for ( const [ attributeName, attributeConfig ] of Object.entries( + blockType.attributes + ) ) { + if ( + attributeConfig.context && + blockAttributes[ attributeName ] !== undefined + ) { + const Provider = getContext( blockType.name, attributeName ).Provider; + children = ( + { children } + ); + } + } + return children; +} +function BlockContext( { + blockType, + blockAttributes, + Component, + ...componentProps +} ) { + const blockContext = {}; + if ( blockType.context ) { + for ( const [ attributeName, blockNameOrBlockNames ] of Object.entries( + blockType.context + ) ) { + const blockNames = castArray( blockNameOrBlockNames ); + for ( const blockName of blockNames ) { + // eslint-disable-next-line react-hooks/rules-of-hooks + const contextValue = useContext( getContext( blockName, attributeName ) ); + if ( contextValue !== undefined ) { + blockContext[ attributeName ] = contextValue; + } + } + } + } + return ( + + blockContext, Object.values( blockContext ) ) } + /> + + ); +} +BlockContext.Providers = Providers; +export default BlockContext; diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 448f4b74514565..2bb0abc973cc0b 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -24,6 +24,7 @@ import { compose, pure, ifCondition } from '@wordpress/compose'; /** * Internal dependencies */ +import BlockContext from './block-context'; import BlockEdit from '../block-edit'; import BlockInvalidWarning from './block-invalid-warning'; import BlockCrashWarning from './block-crash-warning'; @@ -130,7 +131,10 @@ function BlockListBlock( { // (InspectorControls, etc.) which are inside `BlockEdit` but not // `BlockHTML`, even in HTML mode. let blockEdit = ( - { +BlockList = forwardRef( ( props, ref ) => { const fallbackRef = useRef(); return ( @@ -137,3 +138,5 @@ export default forwardRef( ( props, ref ) => { ); } ); +BlockList.BlockContext = BlockContext; +export default BlockList; From ed895e43e47f254f0cf6723fe9348841811c600e Mon Sep 17 00:00:00 2001 From: epiqueras Date: Sun, 19 Jan 2020 08:37:51 -0500 Subject: [PATCH 07/12] Editor: Provide root Post block context. --- .../editor/src/components/provider/index.js | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 74c7b2f67cf72d..016988a64447b0 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -15,10 +15,12 @@ import { EntityProvider } from '@wordpress/core-data'; import { BlockEditorProvider, __unstableEditorStyles as EditorStyles, + BlockList, } from '@wordpress/block-editor'; import apiFetch from '@wordpress/api-fetch'; import { addQueryArgs } from '@wordpress/url'; import { decodeEntities } from '@wordpress/html-entities'; +import { getBlockType } from '@wordpress/blocks'; /** * Internal dependencies @@ -193,19 +195,27 @@ class EditorProvider extends Component { type={ post.type } id={ post.id } > - - { children } - - - + + { children } + + + + From 963a64f8e33f726c2b48e3653bbaf1471b2e3222 Mon Sep 17 00:00:00 2001 From: epiqueras Date: Sun, 19 Jan 2020 08:40:20 -0500 Subject: [PATCH 08/12] Core Data: Support passing a specific ID to entity hooks instead of reading from providers. --- packages/core-data/src/entity-provider.js | 52 +++++++++++++++++------ 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/packages/core-data/src/entity-provider.js b/packages/core-data/src/entity-provider.js index d2d0f23569ca4c..8fb8b4b71aa5b2 100644 --- a/packages/core-data/src/entity-provider.js +++ b/packages/core-data/src/entity-provider.js @@ -74,16 +74,25 @@ export function useEntityId( kind, type ) { * specified property of the nearest provided * entity of the specified type. * - * @param {string} kind The entity kind. - * @param {string} type The entity type. - * @param {string} prop The property name. + * You may optionally override the provided ID + * using the last parameter. + * + * @param {string} kind The entity kind. + * @param {string} type The entity type. + * @param {string} prop The property name. + * @param {string} [id=useEntityId( kind, type )] The optional entity ID override. * * @return {[*, Function]} A tuple where the first item is the * property value and the second is the * setter. */ -export function useEntityProp( kind, type, prop ) { - const id = useEntityId( kind, type ); +export function useEntityProp( + kind, + type, + prop, + // eslint-disable-next-line react-hooks/rules-of-hooks + id = useEntityId( kind, type ) +) { const { value, fullValue } = useSelect( ( select ) => { const { getEntityRecord, getEditedEntityRecord } = select( 'core' ); @@ -122,24 +131,38 @@ export function useEntityProp( kind, type, prop ) { * `BlockEditorProvider` and are intended to be used with it, * or similar components or hooks. * - * @param {string} kind The entity kind. - * @param {string} type The entity type. + * You may optionally override the provided ID + * using the last parameter. + * + * @param {string} kind The entity kind. + * @param {string} type The entity type. * @param {Object} options - * @param {Object} [options.initialEdits] Initial edits object for the entity record. - * @param {string} [options.blocksProp='blocks'] The name of the entity prop that holds the blocks array. - * @param {string} [options.contentProp='content'] The name of the entity prop that holds the serialized blocks. + * @param {Object} [options.initialEdits] Initial edits object for the entity record. + * @param {string} [options.blocksProp='blocks'] The name of the entity prop that holds the blocks array. + * @param {string} [options.contentProp='content'] The name of the entity prop that holds the serialized blocks. + * @param {string} [options.id=useEntityId( kind, type )] The optional entity ID override. * * @return {[WPBlock[], Function, Function]} The block array and setters. */ export function useEntityBlockEditor( kind, type, - { initialEdits, blocksProp = 'blocks', contentProp = 'content' } = {} + { + initialEdits, + blocksProp = 'blocks', + contentProp = 'content', + // eslint-disable-next-line react-hooks/rules-of-hooks + id = useEntityId( kind, type ), + } = {} ) { - const [ content, setContent ] = useEntityProp( kind, type, contentProp ); + const [ content, setContent ] = useEntityProp( + kind, + type, + contentProp, + id + ); const { editEntityRecord } = useDispatch( 'core' ); - const id = useEntityId( kind, type ); const initialBlocks = useMemo( () => { if ( initialEdits ) { editEntityRecord( kind, type, id, initialEdits, { @@ -157,7 +180,8 @@ export function useEntityBlockEditor( const [ blocks = initialBlocks, onInput ] = useEntityProp( kind, type, - blocksProp + blocksProp, + id ); const onChange = useCallback( From 2cf7ce444112facc602c33241b32c2c8e815c6ba Mon Sep 17 00:00:00 2001 From: epiqueras Date: Sun, 19 Jan 2020 08:42:50 -0500 Subject: [PATCH 09/12] Block Library: Implement Post blocks context server-side. --- lib/blocks.php | 1 + .../block-library/src/post-content/index.php | 14 ++++++++-- .../block-library/src/post-title/index.php | 12 ++++++-- packages/block-library/src/post/index.php | 28 +++++++++++++++++++ 4 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 packages/block-library/src/post/index.php diff --git a/lib/blocks.php b/lib/blocks.php index c7516568815019..18bee11cad4ed0 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -32,6 +32,7 @@ function gutenberg_reregister_core_block_types() { 'tag-cloud.php' => 'core/tag-cloud', 'site-title.php' => 'core/site-title', 'template-part.php' => 'core/template-part', + 'post.php' => 'core/post', 'post-title.php' => 'core/post-title', 'post-content.php' => 'core/post-content', 'post-author.php' => 'core/post-author', diff --git a/packages/block-library/src/post-content/index.php b/packages/block-library/src/post-content/index.php index 1e6870fd0b3134..87d87a2b382152 100644 --- a/packages/block-library/src/post-content/index.php +++ b/packages/block-library/src/post-content/index.php @@ -8,16 +8,20 @@ /** * Renders the `core/post-content` block on the server. * + * @param array $attributes The block attributes. + * @param array $content The saved content. + * @param array $block The parsed block. + * * @return string Returns the filtered post content of the current post. */ -function render_block_core_post_content() { - $post = gutenberg_get_post_from_context(); +function render_block_core_post_content( $attributes, $content, $block ) { + $post = isset( $block['context']['postId'] ) ? $block['context']['postId'] : gutenberg_get_post_from_context(); if ( ! $post ) { return ''; } return ( '
' . - apply_filters( 'the_content', str_replace( ']]>', ']]>', get_the_content( $post ) ) ) . + apply_filters( 'the_content', str_replace( ']]>', ']]>', get_the_content( null, false, $post ) ) ) . '
' ); } @@ -34,6 +38,10 @@ function register_block_core_post_content() { array_merge( $metadata, array( + 'context' => array( + 'postType' => 'core/post', + 'postId' => 'core/post', + ), 'render_callback' => 'render_block_core_post_content', ) ) diff --git a/packages/block-library/src/post-title/index.php b/packages/block-library/src/post-title/index.php index c635ad2a0f0eb9..2adf9978484013 100644 --- a/packages/block-library/src/post-title/index.php +++ b/packages/block-library/src/post-title/index.php @@ -8,10 +8,14 @@ /** * Renders the `core/post-title` block on the server. * + * @param array $attributes The block attributes. + * @param array $content The saved content. + * @param array $block The parsed block. + * * @return string Returns the filtered post title for the current post wrapped inside "h1" tags. */ -function render_block_core_post_title() { - $post = gutenberg_get_post_from_context(); +function render_block_core_post_title( $attributes, $content, $block ) { + $post = isset( $block['context']['postId'] ) ? $block['context']['postId'] : gutenberg_get_post_from_context(); if ( ! $post ) { return ''; } @@ -30,6 +34,10 @@ function register_block_core_post_title() { array_merge( $metadata, array( + 'context' => array( + 'postType' => 'core/post', + 'postId' => 'core/post', + ), 'render_callback' => 'render_block_core_post_title', ) ) diff --git a/packages/block-library/src/post/index.php b/packages/block-library/src/post/index.php new file mode 100644 index 00000000000000..5d311624ac0874 --- /dev/null +++ b/packages/block-library/src/post/index.php @@ -0,0 +1,28 @@ + array( + 'postType' => array( + 'type' => 'string', + 'context' => true, + ), + 'postId' => array( + 'type' => 'string', + 'context' => true, + ), + ), + ) + ); +} +add_action( 'init', 'register_block_core_post' ); From 3aaff0b0e632a08a450b98d58a468b88c4c2a31f Mon Sep 17 00:00:00 2001 From: epiqueras Date: Sun, 19 Jan 2020 08:46:59 -0500 Subject: [PATCH 10/12] Block Library: Implement Post blocks context client-side. --- lib/compat.php | 2 +- .../components/block-list/block-context.js | 16 +++++-- .../src/components/block-list/block.js | 4 +- .../block-library/src/post-content/block.json | 6 ++- .../block-library/src/post-content/edit.js | 15 ++++--- .../block-library/src/post-title/block.json | 6 ++- packages/block-library/src/post-title/edit.js | 17 ++++--- packages/block-library/src/post/block.json | 12 ++++- packages/block-library/src/post/edit/index.js | 20 ++++----- .../src/post/edit/placeholder.js | 44 +++++++++++++------ packages/block-library/src/post/editor.scss | 4 ++ 11 files changed, 100 insertions(+), 46 deletions(-) diff --git a/lib/compat.php b/lib/compat.php index 72f7ef13c3106c..9d42f3bd7a6b72 100644 --- a/lib/compat.php +++ b/lib/compat.php @@ -167,7 +167,7 @@ function gutenberg_provide_render_callback_with_block_object( $pre_render, $bloc } if ( isset( $block_type->attributes ) ) { foreach ( $block_type->attributes as $attribute_name => $attribute_config ) { - if ( $attribute_config['context'] && isset( $block['attrs'][ $attribute_name ] ) ) { + if ( isset( $attribute_config['context'] ) && $attribute_config['context'] && isset( $block['attrs'][ $attribute_name ] ) ) { if ( ! isset( $next_context[ $block['blockName'] ] ) ) { $next_context[ $block['blockName'] ] = array(); } diff --git a/packages/block-editor/src/components/block-list/block-context.js b/packages/block-editor/src/components/block-list/block-context.js index 1eb7dd784a4436..8e252cfb80709b 100644 --- a/packages/block-editor/src/components/block-list/block-context.js +++ b/packages/block-editor/src/components/block-list/block-context.js @@ -27,9 +27,12 @@ function Providers( { blockType, blockAttributes, children } ) { attributeConfig.context && blockAttributes[ attributeName ] !== undefined ) { - const Provider = getContext( blockType.name, attributeName ).Provider; + const Provider = getContext( blockType.name, attributeName ) + .Provider; children = ( - { children } + + { children } + ); } } @@ -49,7 +52,9 @@ function BlockContext( { const blockNames = castArray( blockNameOrBlockNames ); for ( const blockName of blockNames ) { // eslint-disable-next-line react-hooks/rules-of-hooks - const contextValue = useContext( getContext( blockName, attributeName ) ); + const contextValue = useContext( + getContext( blockName, attributeName ) + ); if ( contextValue !== undefined ) { blockContext[ attributeName ] = contextValue; } @@ -60,7 +65,10 @@ function BlockContext( { blockContext, Object.values( blockContext ) ) } + context={ useMemo( + () => blockContext, + Object.values( blockContext ) + ) } /> ); diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 2bb0abc973cc0b..c928658723f513 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -24,7 +24,7 @@ import { compose, pure, ifCondition } from '@wordpress/compose'; /** * Internal dependencies */ -import BlockContext from './block-context'; +import _BlockContext from './block-context'; import BlockEdit from '../block-edit'; import BlockInvalidWarning from './block-invalid-warning'; import BlockCrashWarning from './block-crash-warning'; @@ -131,7 +131,7 @@ function BlockListBlock( { // (InspectorControls, etc.) which are inside `BlockEdit` but not // `BlockHTML`, even in HTML mode. let blockEdit = ( - ; + return ; } diff --git a/packages/block-library/src/post-title/block.json b/packages/block-library/src/post-title/block.json index b64dbc3740ab49..b3baececd016fe 100644 --- a/packages/block-library/src/post-title/block.json +++ b/packages/block-library/src/post-title/block.json @@ -1,4 +1,8 @@ { "name": "core/post-title", - "category": "layout" + "category": "layout", + "context": { + "postType": "core/post", + "postId": "core/post" + } } diff --git a/packages/block-library/src/post-title/edit.js b/packages/block-library/src/post-title/edit.js index 975c1a81efa925..e7a45a39e0dddd 100644 --- a/packages/block-library/src/post-title/edit.js +++ b/packages/block-library/src/post-title/edit.js @@ -1,12 +1,17 @@ /** * WordPress dependencies */ -import { useEntityProp, useEntityId } from '@wordpress/core-data'; +import { useEntityProp } from '@wordpress/core-data'; import { RichText } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; -function PostTitleInput() { - const [ title, setTitle ] = useEntityProp( 'postType', 'post', 'title' ); +function PostTitleInput( { postType, postId } ) { + const [ title, setTitle ] = useEntityProp( + 'postType', + postType, + 'title', + postId + ); return ( ; + return ; } diff --git a/packages/block-library/src/post/block.json b/packages/block-library/src/post/block.json index a3a18677f871b1..484a729d30729c 100644 --- a/packages/block-library/src/post/block.json +++ b/packages/block-library/src/post/block.json @@ -1,4 +1,14 @@ { "name": "core/post", - "category": "layout" + "category": "layout", + "attributes": { + "postType": { + "type": "string", + "context": true + }, + "postId": { + "type": "string", + "context": true + } + } } diff --git a/packages/block-library/src/post/edit/index.js b/packages/block-library/src/post/edit/index.js index 7aa5a27282dd13..e3e132ff54559d 100644 --- a/packages/block-library/src/post/edit/index.js +++ b/packages/block-library/src/post/edit/index.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { EntityProvider } from '@wordpress/core-data'; import { InnerBlocks } from '@wordpress/block-editor'; /** @@ -10,27 +9,26 @@ import { InnerBlocks } from '@wordpress/block-editor'; */ import PostPlaceholder from './placeholder'; -export default function PostEdit( { attributes: { postId }, setAttributes } ) { +export default function PostEdit( { + attributes: { postType, postId }, + setAttributes, +} ) { const loaded = useSelect( ( select ) => { - if ( ! postId ) { + if ( ! postType || ! postId ) { return false; } return Boolean( - select( 'core' ).getEntityRecord( 'postType', 'post', postId ) + select( 'core' ).getEntityRecord( 'postType', postType, postId ) ); }, - [ postId ] + [ postType, postId ] ); - if ( postId ) { + if ( postType && postId ) { if ( ! loaded ) { return null; } - return ( - - - - ); + return ; } return ; } diff --git a/packages/block-library/src/post/edit/placeholder.js b/packages/block-library/src/post/edit/placeholder.js index b3cd06b2005158..bed0b0e1d01610 100644 --- a/packages/block-library/src/post/edit/placeholder.js +++ b/packages/block-library/src/post/edit/placeholder.js @@ -1,15 +1,17 @@ /** * WordPress dependencies */ -import { useEntityBlockEditor, EntityProvider } from '@wordpress/core-data'; +import { useEntityBlockEditor } from '@wordpress/core-data'; import { __ } from '@wordpress/i18n'; import { BlockPreview } from '@wordpress/block-editor'; import { useState, useCallback } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; import { Placeholder, TextControl, Button } from '@wordpress/components'; -function PostPreview() { - const [ blocks ] = useEntityBlockEditor( 'postType', 'post' ); +function PostPreview( { postType, postId } ) { + const [ blocks ] = useEntityBlockEditor( 'postType', postType, { + id: postId, + } ); return (
@@ -21,24 +23,28 @@ function PostPreview() { } export default function PostPlaceholder( { setAttributes } ) { + const [ postType, setPostType ] = useState( 'post' ); const [ postId, setPostId ] = useState(); const preview = useSelect( ( select ) => { - if ( ! postId ) { + if ( ! postType || ! postId ) { return null; } - const post = select( 'core' ).getEntityRecord( 'postType', 'post', postId ); + const post = select( 'core' ).getEntityRecord( + 'postType', + postType, + postId + ); if ( post ) { - return ( - - - - ); + return ; } }, - [ postId ] + [ postType, postId ] + ); + const choosePost = useCallback( + () => setAttributes( { postType, postId } ), + [ postType, postId ] ); - const choosePostId = useCallback( () => setAttributes( { postId } ), [ postId ] ); return (
+
{ preview } -
diff --git a/packages/block-library/src/post/editor.scss b/packages/block-library/src/post/editor.scss index 8be69762be5500..45f6744e6ef45d 100644 --- a/packages/block-library/src/post/editor.scss +++ b/packages/block-library/src/post/editor.scss @@ -4,6 +4,10 @@ width: 100%; } +.wp-block-post__placeholder-input { + margin: 5px; +} + .wp-block-post__placeholder-preview { margin-bottom: 15px; width: 100%; From 56eec8327ee92d8b661434133c912603b7c4f4c8 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Wed, 25 Mar 2020 09:05:21 -0400 Subject: [PATCH 11/12] Block Editor: Resolve error if block type for context provider undefined e.g. Full-site editing experiment disabled, so "post" block not available --- .../components/block-list/block-context.js | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block-context.js b/packages/block-editor/src/components/block-list/block-context.js index 8e252cfb80709b..ae3e79f2981d69 100644 --- a/packages/block-editor/src/components/block-list/block-context.js +++ b/packages/block-editor/src/components/block-list/block-context.js @@ -20,24 +20,28 @@ const getContext = ( blockName, attributeName ) => { }; function Providers( { blockType, blockAttributes, children } ) { - for ( const [ attributeName, attributeConfig ] of Object.entries( - blockType.attributes - ) ) { - if ( - attributeConfig.context && - blockAttributes[ attributeName ] !== undefined - ) { - const Provider = getContext( blockType.name, attributeName ) - .Provider; - children = ( - - { children } - - ); + if ( blockType ) { + for ( const [ attributeName, attributeConfig ] of Object.entries( + blockType.attributes + ) ) { + if ( + attributeConfig.context && + blockAttributes[ attributeName ] !== undefined + ) { + const Provider = getContext( blockType.name, attributeName ) + .Provider; + children = ( + + { children } + + ); + } } } + return children; } + function BlockContext( { blockType, blockAttributes, From 4fa693601b85190fcd5e01e6f1771008dbd19cc3 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Wed, 25 Mar 2020 09:09:59 -0400 Subject: [PATCH 12/12] Block Library: Post: Register from metadata --- packages/block-library/src/post/index.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/block-library/src/post/index.php b/packages/block-library/src/post/index.php index 5d311624ac0874..458d334ed3e827 100644 --- a/packages/block-library/src/post/index.php +++ b/packages/block-library/src/post/index.php @@ -9,20 +9,11 @@ * Registers the `core/post` block on the server. */ function register_block_core_post() { + $path = __DIR__ . '/post/block.json'; + $metadata = json_decode( file_get_contents( $path ), true ); register_block_type( - 'core/post', - array( - 'attributes' => array( - 'postType' => array( - 'type' => 'string', - 'context' => true, - ), - 'postId' => array( - 'type' => 'string', - 'context' => true, - ), - ), - ) + $metadata['name'], + $metadata ); } add_action( 'init', 'register_block_core_post' );