From 71ef9849d3ef250fdf895cc6fd0e36c788152185 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Mon, 24 May 2021 10:11:16 +0100 Subject: [PATCH 01/17] Augment and improve Nav Editor (and block) documentation (#31891) * Document different editor save and render modes * Add code references and correct grammar * Tidy unrequired sentances * Document menu item to block attribute mapping * Bring mappings adjacent to each other. Improve documenting inconsistencies. * Add helpful links * Quick ref to the block * Seperate out the colophon --- packages/edit-navigation/README.md | 104 +++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/packages/edit-navigation/README.md b/packages/edit-navigation/README.md index 08afd5dae7a813..1ee150967f8697 100644 --- a/packages/edit-navigation/README.md +++ b/packages/edit-navigation/README.md @@ -20,6 +20,103 @@ import blockEditorSettings from './block-editor-settings'; initialize( '#navigation-editor-root', blockEditorSettings ); ``` +## Purpose + +By default, the Navigation Editor screen allows users to create and edit complex navigations using a block-based UI. The aim is to supercede [the current Menus screen](https://codex.wordpress.org/WordPress_Menu_User_Guide) by providing a superior experience whilst retaining backwards compatibility. + +The editing experience is provided as a block editor wrapper around the core functionality of the **Navigation _block_**. Features of the block are disabled/enhanced as necessary to provide an experience appropriate to editing a navigation outside of a Full Site Editing context. + +## Modes + +The Navigation Editor has two "modes" for _persistence_ ("saving" navigations) and _rendering_: + +1. **Default** - navigations are saved to the _existing_ (post type powered) Menus system and rendered using standard Walker classes. +2. **Block-based** (opt _in_) - navigations continue to be _saved_ using the existing post type system, but non-link blocks are saved (see technical implementation) and _rendered_ as blocks to provide access to the full power of the Navigation block (with some tradeoffs in terms of backwards compatibility). + +### Default Mode + +In this mode, navigations created in the Navigation Editor are stored using the _existing Menu post type_ (`nav_menu_item`) system. As this method matches that used in the _existing_ Menus screen, there is a smooth upgrade path to using new Navigation Editor screen to edit navigations. + +Moreover, when the navigation is rendered on the front of the site the system continues to use [the classic Navigation "Walker" class](https://developer.wordpress.org/reference/classes/walker_nav_menu/), thereby ensuring the HTML markup remains the same when using a classic Theme. + +### Block-based Mode + +If desired, themes are able to opt into _rendering_ complete block-based menus using the Navigation Editor. This allows for arbitrarily complex navigation block structures to be used in an existing theme whilst still ensuring the navigation data is still _saved_ to the existing (post type powered) Menus system. + +Themes can opt into this behaviour by declaring: + +```php +add_theme_support( 'block-nav-menus' ); +``` + +This unlocks significant additional capabilities in the Navigation Editor. For example, by default, [the Navigation Editor screen only allows _link_ (`core/navigation-link`) blocks to be inserted into a navigation](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/filters/disable-inserting-non-navigation-blocks.js). When a theme opts into `block-nav-menus` however, users are able to add non-link blocks to a navigation using the Navigation Editor screen, including: + +- `core/navigation-link`. +- `core/social`. +- `core/search`. + +#### Technical Implementation details + +By default, `core/navigation-link` items are serialized and persisted as `nav_menu_item` posts. No serialized block HTML is stored for these standard link blocks. + +_Non_-link navigation items however, are [persisted as `nav_menu_items` with a special `type` of `block`](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L159-L166). These items have an [_additional_ `content` field which is used to store the serialized block markup](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/lib/navigation.php#L71-L101). + +When rendered on the front-end, the blocks are [`parse`d from the `content` field](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/lib/navigation.php#L191-L203) and [rendered as blocks](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/lib/navigation.php#L103-L135). + +If the user switches to a theme that does not support block menus, or disables this functionality, non-link blocks are no longer rendered on the frontend. Care is taken, however, to ensure that users can still see their data on the existing Menus screen. + +## Block to Menu Item mapping + +The Navigation Editor needs to be able to map navigation items in two directions: + +1. `nav_menu_item`s to Blocks - when displaying an existing navigation. +2. Blocks to `nav_menu_item`s - when _saving_ an navigation being editing in the Navigation screen. + +The Navigation Editor has two dedicated methods for handling mapping between these two expressions of the data: + +- [`menuItemToBlockAttributes()`](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L261-L313). +- [`blockAttributestoMenuItem()`](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L184-L253) + +To understand these fully, one must appreciate that WordPress maps raw `nav_menu_item` posts to [Menu item _objects_](https://core.trac.wordpress.org/browser/tags/5.7.1/src/wp-includes/nav-menu.php#L786). These have various properties which map as follows: + +| Menu Item object property | Equivalent Block Attribute | Description | +| :------------------------ | :----------------------------------------------------: | :-------------------------------------------------------------------------------------------------------: | +| `ID` | Not mapped. | The term_id if the menu item represents a taxonomy term. | +| `attr_title` | `title` | The title attribute of the link element for this menu item. | +| `classes` | `classNames` | The array of class attribute values for the link element of this menu item. | +| `db_id` | Not mapped. | The DB ID of this item as a nav_menu_item object, if it exists (0 if it doesn't exist). | +| `description` | `description` | The description of this menu item. | +| `menu_item_parent` | Not mapped.[1](#menu_item_menu_item_parent) | The DB ID of the nav_menu_item that is this item's menu parent, if any. 0 otherwise. | +| `object` | `type` | The type of object originally represented, such as 'category', 'post', or 'attachment'. | +| `object_id` | `id` | The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories. | +| `post_parent` | Not mapped. | The DB ID of the original object's parent object, if any (0 otherwise). | +| `post_title` | Not mapped. | A "no title" label if menu item represents a post that lacks a title. | +| `target` | `opensInNewTab`[2](#menu_item_target) | The target attribute of the link element for this menu item. | +| `title` | `label` | The title of this menu item. | +| `type` | `kind` | The family of objects originally represented, such as 'post_type' or 'taxonomy'. | +| `type_label` | Not mapped. | The singular label used to describe this type of menu item. | +| `url` | `url` | The URL to which this menu item points. | +| `xfn` | `rel` | The XFN relationship expressed in the link of this menu item. | +| `\_invalid` | Not mapped. | Whether the menu item represents an object that no longer exists. | + +- [1] - the parent -> child relationship is expressed in block via the `innerBlocks` attribute and is therefore not required as a explicit block attribute. +- [2] - applies only if the value of the `target` field is `_blank`. + +### Inconsistencies + +#### Mapping + +For historical reasons, the following properties display some inconsistency in their mapping from Menu Item Object to Block attribute: + +- `type` -> `kind` - the family of objects is stored as `kind` on the block and so must be mapped accordingly. +- `object` -> `type` - the type of object is stored as `type` on the block and so must be mapped accordingly. +- `object_id` -> `id` - the block stores a reference to the original object's ID as the `id` _attribute_. This should not be confused with the block's `clientId` which is unrelated. +- `attr_title` -> `title` - the HTML `title` attribute is stored as `title` on the block and so must be mapped accordingly. + +#### Object Types + +- Menu Item objects which represent "Tags" are stored in WordPress as `post_tag` but the block expects their `type` attribute to be `tag` (omiting the `post_` suffix). This inconsistency is accounted for in [the mapping utilities methods](https://github.com/WordPress/gutenberg/blob/7fcd57c9a62c232899e287f6d96416477d810d5e/packages/edit-navigation/src/store/utils.js#L279-L281). + ## Hooks `useMenuItems` and `useNavigationBlock` hooks are the central part of this package. They bridge the gap between the API and the block editor interface: @@ -59,6 +156,13 @@ return ( ); ``` +## Glossary + +- **Link block** - the basic `core/navigation-link` block which is the standard block used to add links within navigations. +- **Navigation block** - the root `core/navigation` block which can be used both with the Navigation Editor and outside (eg: Post / Site Editor). +- **Navigation editor / screen** - the new screen provided by Gutenberg to allow the user to edit navigations using a block-based UI. +- **Menus screen** - the current/existing [interface/screen for managing Menus](https://codex.wordpress.org/WordPress_Menu_User_Guide) in WordPress WPAdmin. + _This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for ES2015+ such as IE browsers then using [core-js](https://github.com/zloirock/core-js) will add polyfills for these methods._

Code is Poetry.

From 4edc47f5187e7f58dc1a9618ba8d732b5d072c00 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Mon, 24 May 2021 12:41:23 +0200 Subject: [PATCH 02/17] [RNMobile] Fix ShouldInsertAtTheTop setting calculation (#32110) --- .../src/components/provider/use-block-editor-settings.js | 9 +-------- .../provider/use-block-editor-settings.native.js | 7 +++++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 592da3aaf026b7..158fa8d02f5363 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -33,11 +33,8 @@ function useBlockEditorSettings( settings, hasTemplate ) { reusableBlocks, hasUploadPermissions, canUseUnfilteredHTML, - isTitleSelected, } = useSelect( ( select ) => { - const { canUserUseUnfilteredHTML, isPostTitleSelected } = select( - editorStore - ); + const { canUserUseUnfilteredHTML } = select( editorStore ); const isWeb = Platform.OS === 'web'; const { canUser } = select( coreStore ); @@ -54,8 +51,6 @@ function useBlockEditorSettings( settings, hasTemplate ) { canUser( 'create', 'media' ), true ), - // This selector is only defined on mobile. - isTitleSelected: isPostTitleSelected && isPostTitleSelected(), }; }, [] ); @@ -111,7 +106,6 @@ function useBlockEditorSettings( settings, hasTemplate ) { fetchRemoteUrlData( url ), __experimentalCanUserUseUnfilteredHTML: canUseUnfilteredHTML, __experimentalUndo: undo, - __experimentalShouldInsertAtTheTop: isTitleSelected, outlineMode: hasTemplate, } ), [ @@ -120,7 +114,6 @@ function useBlockEditorSettings( settings, hasTemplate ) { reusableBlocks, canUseUnfilteredHTML, undo, - isTitleSelected, hasTemplate, ] ); diff --git a/packages/editor/src/components/provider/use-block-editor-settings.native.js b/packages/editor/src/components/provider/use-block-editor-settings.native.js index 57bfaf6fd3c08c..8baf2371442b2e 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.native.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.native.js @@ -9,13 +9,14 @@ import { store as coreStore } from '@wordpress/core-data'; * Internal dependencies */ import useBlockEditorSettings from './use-block-editor-settings.js'; +import { store as editorStore } from '../../store'; function useNativeBlockEditorSettings( settings, hasTemplate ) { const capabilities = settings.capabilities ?? {}; const editorSettings = useBlockEditorSettings( settings, hasTemplate ); const supportReusableBlock = capabilities.reusableBlock === true; - const { reusableBlocks } = useSelect( + const { isTitleSelected, reusableBlocks } = useSelect( ( select ) => ( { reusableBlocks: supportReusableBlock ? select( coreStore ).getEntityRecords( @@ -26,6 +27,7 @@ function useNativeBlockEditorSettings( settings, hasTemplate ) { { per_page: 100 } ) : [], + isTitleSelected: select( editorStore ).isPostTitleSelected(), } ), [ supportReusableBlock ] ); @@ -34,8 +36,9 @@ function useNativeBlockEditorSettings( settings, hasTemplate ) { () => ( { ...editorSettings, __experimentalReusableBlocks: reusableBlocks, + __experimentalShouldInsertAtTheTop: isTitleSelected, } ), - [ reusableBlocks ] + [ editorSettings, reusableBlocks, isTitleSelected ] ); } From 6a09db457c0f3f937e214ccfd2a970dab81f24d0 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Mon, 24 May 2021 14:20:42 +0300 Subject: [PATCH 03/17] ignore some eslint rules in react-native folders (#32143) --- .eslintrc.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 6cd1ee9c29e8a9..e96ac58089bdb8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -164,7 +164,11 @@ module.exports = { }, overrides: [ { - files: [ '**/*.@(android|ios|native).js', ...developmentFiles ], + files: [ + '**/*.@(android|ios|native).js', + 'packages/react-native-*/**/*.js', + ...developmentFiles, + ], rules: { 'import/no-extraneous-dependencies': 'off', 'import/no-unresolved': 'off', From c9b638de548bc1cdfbcabcab168493bb4febfd17 Mon Sep 17 00:00:00 2001 From: Jason Crist Date: Mon, 24 May 2021 08:39:10 -0400 Subject: [PATCH 04/17] Allow block attributes passed to block renderer by way of wp_nav_menu. (#31911) --- lib/navigation.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/navigation.php b/lib/navigation.php index b1e7d21b031589..7bfe3416647c6e 100644 --- a/lib/navigation.php +++ b/lib/navigation.php @@ -299,9 +299,14 @@ function gutenberg_output_block_nav_menu( $output, $args ) { $menu_items_by_parent_id[ $menu_item->menu_item_parent ][] = $menu_item; } + $block_attributes = array(); + if ( isset( $args->block_attributes ) ) { + $block_attributes = $args->block_attributes; + } + $navigation_block = array( 'blockName' => 'core/navigation', - 'attrs' => array(), + 'attrs' => $block_attributes, 'innerBlocks' => gutenberg_convert_menu_items_to_blocks( isset( $menu_items_by_parent_id[0] ) ? $menu_items_by_parent_id[0] From 9451339aed3c50036f99ae54c1502d049e68b947 Mon Sep 17 00:00:00 2001 From: sarayourfriend <24264157+sarayourfriend@users.noreply.github.com> Date: Mon, 24 May 2021 07:14:42 -0700 Subject: [PATCH 05/17] components: Add types to Disabled (#32105) --- packages/components/src/disabled/index.js | 42 +++++++++++++++++------ packages/components/tsconfig.json | 2 ++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/packages/components/src/disabled/index.js b/packages/components/src/disabled/index.js index e05bdea2bd19f4..dbe80042c35b51 100644 --- a/packages/components/src/disabled/index.js +++ b/packages/components/src/disabled/index.js @@ -42,10 +42,26 @@ const DISABLED_ELIGIBLE_NODE_NAMES = [ 'TEXTAREA', ]; +/** + * @typedef OwnProps + * @property {string} [className] Classname for the disabled element. + * @property {import('react').ReactNode} children Children to disable. + * @property {boolean} [isDisabled=true] Whether to disable the children. + */ + +/** + * @param {OwnProps & import('react').HTMLAttributes} props + * @return {JSX.Element} Element wrapping the children to disable them when isDisabled is true. + */ function Disabled( { className, children, isDisabled = true, ...props } ) { - const node = useRef(); + /** @type {import('react').RefObject} */ + const node = useRef( null ); const disable = () => { + if ( ! node.current ) { + return; + } + focus.focusable.find( node.current ).forEach( ( focusable ) => { if ( includes( DISABLED_ELIGIBLE_NODE_NAMES, focusable.nodeName ) @@ -54,7 +70,7 @@ function Disabled( { className, children, isDisabled = true, ...props } ) { } if ( focusable.nodeName === 'A' ) { - focusable.setAttribute( 'tabindex', -1 ); + focusable.setAttribute( 'tabindex', '-1' ); } const tabIndex = focusable.getAttribute( 'tabindex' ); @@ -71,7 +87,7 @@ function Disabled( { className, children, isDisabled = true, ...props } ) { // Debounce re-disable since disabling process itself will incur // additional mutations which should be ignored. const debouncedDisable = useCallback( - debounce( disable, { leading: true } ), + debounce( disable, undefined, { leading: true } ), [] ); @@ -82,15 +98,21 @@ function Disabled( { className, children, isDisabled = true, ...props } ) { disable(); - const observer = new window.MutationObserver( debouncedDisable ); - observer.observe( node.current, { - childList: true, - attributes: true, - subtree: true, - } ); + /** @type {MutationObserver | undefined} */ + let observer; + if ( node.current ) { + observer = new window.MutationObserver( debouncedDisable ); + observer.observe( node.current, { + childList: true, + attributes: true, + subtree: true, + } ); + } return () => { - observer.disconnect(); + if ( observer ) { + observer.disconnect(); + } debouncedDisable.cancel(); }; }, [] ); diff --git a/packages/components/tsconfig.json b/packages/components/tsconfig.json index 5e7c69328d8b04..99adcbbb46ce00 100644 --- a/packages/components/tsconfig.json +++ b/packages/components/tsconfig.json @@ -7,6 +7,7 @@ }, "references": [ { "path": "../deprecated" }, + { "path": "../dom" }, { "path": "../element" }, { "path": "../hooks" }, { "path": "../icons" }, @@ -19,6 +20,7 @@ "src/animate/**/*", "src/base-control/**/*", "src/dashicon/**/*", + "src/disabled/**/*", "src/draggable/**/*", "src/elevation/**/*", "src/flex/**/*", From e6e0ea8906c0fb01ea132e3386d5e42172614ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= Date: Mon, 24 May 2021 16:35:53 +0200 Subject: [PATCH 06/17] Components: Mark all experimental components in the handbook (#32147) Inspired by the alert for Global Settings and Styles (theme.json): https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/ --- packages/components/src/box-control/README.md | 4 ++++ packages/components/src/dimension-control/README.md | 4 ++++ packages/components/src/divider/README.md | 4 ++++ packages/components/src/elevation/README.md | 6 +++++- packages/components/src/flex/flex-block/README.md | 4 +++- packages/components/src/flex/flex-item/README.md | 4 +++- packages/components/src/flex/flex/README.md | 4 +++- packages/components/src/grid/README.md | 6 ++++-- packages/components/src/h-stack/README.md | 6 ++++-- packages/components/src/heading/README.md | 4 +++- packages/components/src/input-control/README.md | 4 ++++ packages/components/src/navigation/README.md | 4 ++++ packages/components/src/number-control/README.md | 4 ++++ packages/components/src/radio-group/README.md | 4 ++++ packages/components/src/spacer/README.md | 10 +++++----- packages/components/src/text/README.md | 4 +++- packages/components/src/tree-grid/README.md | 5 ++++- packages/components/src/truncate/README.md | 4 +++- packages/components/src/ui/card/README.md | 4 ++++ packages/components/src/ui/control-group/README.md | 4 ++++ packages/components/src/ui/control-label/README.md | 4 ++++ packages/components/src/ui/form-group/README.md | 4 ++++ packages/components/src/ui/popover/README.md | 4 ++++ packages/components/src/ui/scrollable/README.md | 4 ++++ packages/components/src/ui/spinner/README.md | 4 ++++ packages/components/src/ui/surface/README.md | 4 ++++ packages/components/src/ui/tooltip/README.md | 4 ++++ packages/components/src/ui/visually-hidden/README.md | 4 ++++ packages/components/src/unit-control/README.md | 4 ++++ packages/components/src/v-stack/README.md | 6 ++++-- packages/components/src/view/README.md | 6 ++++-- packages/components/src/z-stack/README.md | 4 +++- 32 files changed, 123 insertions(+), 22 deletions(-) diff --git a/packages/components/src/box-control/README.md b/packages/components/src/box-control/README.md index 80cfce66896421..77543aa0fba68a 100644 --- a/packages/components/src/box-control/README.md +++ b/packages/components/src/box-control/README.md @@ -1,5 +1,9 @@ # BoxControl +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ BoxControl components let users set values for Top, Right, Bottom, and Left. This can be used as an input control for values like `padding` or `margin`. ## Usage diff --git a/packages/components/src/dimension-control/README.md b/packages/components/src/dimension-control/README.md index 6eda6430a488c0..7c627b7fbe2666 100644 --- a/packages/components/src/dimension-control/README.md +++ b/packages/components/src/dimension-control/README.md @@ -1,5 +1,9 @@ # DimensionControl +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `DimensionControl` is a component designed to provide a UI to control spacing and/or dimensions. ## Usage diff --git a/packages/components/src/divider/README.md b/packages/components/src/divider/README.md index a793646650ee1d..ae9b961dad5e54 100644 --- a/packages/components/src/divider/README.md +++ b/packages/components/src/divider/README.md @@ -1,5 +1,9 @@ # Divider +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `Divider` is a layout component that separates groups of related content. ## Usage diff --git a/packages/components/src/elevation/README.md b/packages/components/src/elevation/README.md index 134948c4e801d2..0e61fe7db0a750 100644 --- a/packages/components/src/elevation/README.md +++ b/packages/components/src/elevation/README.md @@ -1,5 +1,9 @@ # Elevation +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `Elevation` is a core component that renders shadow, using the component system's shadow system. ## Usage @@ -10,7 +14,7 @@ The shadow effect is generated using the `value` prop. import { __experimentalElevation as Elevation, __experimentalSurface as Surface, - __experimentalText as Text + __experimentalText as Text, } from '@wordpress/components'; function Example() { diff --git a/packages/components/src/flex/flex-block/README.md b/packages/components/src/flex/flex-block/README.md index b5cbe861f6d669..691f1b0ad33c0e 100644 --- a/packages/components/src/flex/flex-block/README.md +++ b/packages/components/src/flex/flex-block/README.md @@ -1,6 +1,8 @@ # FlexBlock -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
A layout component to contain items of a fixed width within `Flex`. diff --git a/packages/components/src/flex/flex-item/README.md b/packages/components/src/flex/flex-item/README.md index 6a6fc038263270..2aec78afe35c29 100644 --- a/packages/components/src/flex/flex-item/README.md +++ b/packages/components/src/flex/flex-item/README.md @@ -1,6 +1,8 @@ # FlexItem -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
A layout component to contain items of a fixed width within `Flex`. diff --git a/packages/components/src/flex/flex/README.md b/packages/components/src/flex/flex/README.md index 2ca42bb44baa58..55a7b8b15ecc55 100644 --- a/packages/components/src/flex/flex/README.md +++ b/packages/components/src/flex/flex/README.md @@ -1,6 +1,8 @@ # Flex -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
`Flex` is a primitive layout component that adaptively aligns child content horizontally or vertically. `Flex` powers components like `HStack` and `VStack`. diff --git a/packages/components/src/grid/README.md b/packages/components/src/grid/README.md index 6765ff856b3d0d..27695353d54c2a 100644 --- a/packages/components/src/grid/README.md +++ b/packages/components/src/grid/README.md @@ -1,6 +1,8 @@ # Grid -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
`Grid` is a primitive layout component that can arrange content in a grid configuration. @@ -9,7 +11,7 @@ ```jsx import { __experimentalGrid as Grid, - __experimentalText as Text + __experimentalText as Text, } from '@wordpress/components'; function Example() { diff --git a/packages/components/src/h-stack/README.md b/packages/components/src/h-stack/README.md index 99182bb3e7b9ae..a0b63c7521fcb1 100644 --- a/packages/components/src/h-stack/README.md +++ b/packages/components/src/h-stack/README.md @@ -1,6 +1,8 @@ # HStack -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
`HStack` (Horizontal Stack) arranges child elements in a horizontal line. @@ -93,7 +95,7 @@ function Example() { Code - is + is Poetry diff --git a/packages/components/src/heading/README.md b/packages/components/src/heading/README.md index c686ccf49b9715..f96fe871add758 100644 --- a/packages/components/src/heading/README.md +++ b/packages/components/src/heading/README.md @@ -1,6 +1,8 @@ # Heading -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
`Heading` renders headings and titles using the library's typography system. diff --git a/packages/components/src/input-control/README.md b/packages/components/src/input-control/README.md index fef516a7a3f187..63a0c509010144 100644 --- a/packages/components/src/input-control/README.md +++ b/packages/components/src/input-control/README.md @@ -1,5 +1,9 @@ # InputControl +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ InputControl components let users enter and edit text. This is an experimental component intended to (in time) merge with or replace [TextControl](../text-control). ## Usage diff --git a/packages/components/src/navigation/README.md b/packages/components/src/navigation/README.md index b793489d5a0002..1128874463d574 100644 --- a/packages/components/src/navigation/README.md +++ b/packages/components/src/navigation/README.md @@ -1,5 +1,9 @@ # Navigation +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ Render a navigation list with optional groupings and hierarchy. ## Usage diff --git a/packages/components/src/number-control/README.md b/packages/components/src/number-control/README.md index efb77dd18a40a8..b233502f92f6a1 100644 --- a/packages/components/src/number-control/README.md +++ b/packages/components/src/number-control/README.md @@ -1,5 +1,9 @@ # NumberControl +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ NumberControl is an enhanced HTML [`input[type="number]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number) element. ## Usage diff --git a/packages/components/src/radio-group/README.md b/packages/components/src/radio-group/README.md index 6c3b0d84633a26..721ff07d33a9f1 100644 --- a/packages/components/src/radio-group/README.md +++ b/packages/components/src/radio-group/README.md @@ -1,5 +1,9 @@ # RadioGroup +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ Use a RadioGroup component when you want users to select one option from a small set of options. ![RadioGroup component](https://wordpress.org/gutenberg/files/2018/12/s_96EC471FE9C9D91A996770229947AAB54A03351BDE98F444FD3C1BF0CED365EA_1541792995815_ButtonGroup.png) diff --git a/packages/components/src/spacer/README.md b/packages/components/src/spacer/README.md index 1aad9670c082f5..7bc5b01abf42d3 100644 --- a/packages/components/src/spacer/README.md +++ b/packages/components/src/spacer/README.md @@ -1,6 +1,8 @@ # Spacer -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
`Spacer` is a primitive layout component that providers inner (`padding`) or outer (`margin`) space in-between components. It can also be used to adaptively provide space within an `HStack` or `VStack`. @@ -14,7 +16,7 @@ import { __experimentalSpacer as Spacer, __experimentalHeading as Heading, - __experimentalView as View + __experimentalView as View, } from '@wordpress/components'; function Example() { @@ -23,9 +25,7 @@ function Example() { WordPress.org - - Code is Poetry - + Code is Poetry ); } diff --git a/packages/components/src/text/README.md b/packages/components/src/text/README.md index 72a1831a251914..7747ec9cbc7277 100644 --- a/packages/components/src/text/README.md +++ b/packages/components/src/text/README.md @@ -1,6 +1,8 @@ # Text -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
`Text` is a core component that renders text in the library, using the library's typography system. diff --git a/packages/components/src/tree-grid/README.md b/packages/components/src/tree-grid/README.md index eaedacdfe6f55c..3806d7cc66fd34 100644 --- a/packages/components/src/tree-grid/README.md +++ b/packages/components/src/tree-grid/README.md @@ -1,5 +1,8 @@ -# TreeGrid (experimental) +# TreeGrid +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
## Table of contents 1. [Development guidelines](#development-guidelines) diff --git a/packages/components/src/truncate/README.md b/packages/components/src/truncate/README.md index 494c99dd9720cf..f7c72f53f884a1 100644 --- a/packages/components/src/truncate/README.md +++ b/packages/components/src/truncate/README.md @@ -1,6 +1,8 @@ # Truncate -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
`Truncate` is a typography primitive that trims text content. For almost all cases, it is recommended that `Text`, `Heading`, or `Subheading` is used to render text content. However, `Truncate` is available for custom implementations. diff --git a/packages/components/src/ui/card/README.md b/packages/components/src/ui/card/README.md index 447a2b10bfcc42..56c2bef2af5cee 100644 --- a/packages/components/src/ui/card/README.md +++ b/packages/components/src/ui/card/README.md @@ -1,5 +1,9 @@ # Card +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `Card` groups similar concepts and tasks together. `Card`'s background is rendered with a `Surface`. ## Usage diff --git a/packages/components/src/ui/control-group/README.md b/packages/components/src/ui/control-group/README.md index 3e7f9760fb9c9a..122a6a612a32c1 100644 --- a/packages/components/src/ui/control-group/README.md +++ b/packages/components/src/ui/control-group/README.md @@ -1,5 +1,9 @@ # ControlGroup +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `ControlGroup` is a layout-based component for rendering a group of control-based components, such as `Button`, `Select` or `TextInput`. Control components that render within `ControlGroup` automatically have their borders offset and border-radii rounded. ## Usage diff --git a/packages/components/src/ui/control-label/README.md b/packages/components/src/ui/control-label/README.md index ee6dd9a31329d6..d4e31e034dfd80 100644 --- a/packages/components/src/ui/control-label/README.md +++ b/packages/components/src/ui/control-label/README.md @@ -1,5 +1,9 @@ # ControlLabel +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `ControlLabel` is a form component that works with `FormGroup` to provide a label for form elements (e.g. `Switch` or `TextInput`). ## Usage diff --git a/packages/components/src/ui/form-group/README.md b/packages/components/src/ui/form-group/README.md index 69b65aabc638ca..fec4316caf3553 100644 --- a/packages/components/src/ui/form-group/README.md +++ b/packages/components/src/ui/form-group/README.md @@ -1,5 +1,9 @@ # FormGroup +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `FormGroup` is a form component that groups a label with a form element (e.g. `Switch` or `TextInput`). ## Usage diff --git a/packages/components/src/ui/popover/README.md b/packages/components/src/ui/popover/README.md index 294d43a0380d1d..028d093818749d 100644 --- a/packages/components/src/ui/popover/README.md +++ b/packages/components/src/ui/popover/README.md @@ -1,5 +1,9 @@ # Popover +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `Popover` is a component to render a floating content modal. It is similar in purpose to a tooltip, but renders content of any sort, not only simple text. ## Usage diff --git a/packages/components/src/ui/scrollable/README.md b/packages/components/src/ui/scrollable/README.md index a3996eab2dcc05..e098a2683d7c4f 100644 --- a/packages/components/src/ui/scrollable/README.md +++ b/packages/components/src/ui/scrollable/README.md @@ -1,5 +1,9 @@ # Scrollable +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `Scrollable` is a layout component that content in a scrollable container. ## Usage diff --git a/packages/components/src/ui/spinner/README.md b/packages/components/src/ui/spinner/README.md index 7f611ea6c88325..5e25f9992d0c32 100644 --- a/packages/components/src/ui/spinner/README.md +++ b/packages/components/src/ui/spinner/README.md @@ -1,5 +1,9 @@ # Spinner +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `Spinner` is a component that notify users that their action is being processed. ## Usage diff --git a/packages/components/src/ui/surface/README.md b/packages/components/src/ui/surface/README.md index c3481f0ffa9426..3e82138864cf45 100644 --- a/packages/components/src/ui/surface/README.md +++ b/packages/components/src/ui/surface/README.md @@ -1,5 +1,9 @@ # Surface +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `Surface` is a core component that renders a primary background color. ## Usage diff --git a/packages/components/src/ui/tooltip/README.md b/packages/components/src/ui/tooltip/README.md index ac9e3789c84520..424da79828a487 100644 --- a/packages/components/src/ui/tooltip/README.md +++ b/packages/components/src/ui/tooltip/README.md @@ -1,5 +1,9 @@ # Tooltip +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `Tooltip` is a component to render floating help text relative to a node when it receives focus or when the user places the mouse cursor atop it. ## Usage diff --git a/packages/components/src/ui/visually-hidden/README.md b/packages/components/src/ui/visually-hidden/README.md index 6200eed80dacb1..756311c8043cac 100644 --- a/packages/components/src/ui/visually-hidden/README.md +++ b/packages/components/src/ui/visually-hidden/README.md @@ -1,5 +1,9 @@ # VisuallyHidden +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ `VisuallyHidden` is a component used to render text intended to be visually hidden, but will show for alternate devices, for example a screen reader. ## Usage diff --git a/packages/components/src/unit-control/README.md b/packages/components/src/unit-control/README.md index b024e6aaf5e5ee..5c681ff2ca40a8 100644 --- a/packages/components/src/unit-control/README.md +++ b/packages/components/src/unit-control/README.md @@ -1,5 +1,9 @@ # UnitControl +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
+ UnitControl allows the user to set a value as well as a unit (e.g. `px`). ## Usage diff --git a/packages/components/src/v-stack/README.md b/packages/components/src/v-stack/README.md index ba2132804f78f2..e1fbba7f90d165 100644 --- a/packages/components/src/v-stack/README.md +++ b/packages/components/src/v-stack/README.md @@ -1,6 +1,8 @@ # VStack -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
`VStack` (or Vertical Stack) is a layout component that arranges child elements in a vertical line. @@ -93,7 +95,7 @@ function Example() { Code - is + is Poetry diff --git a/packages/components/src/view/README.md b/packages/components/src/view/README.md index f991f2d95c7334..794d7b49a0d386 100644 --- a/packages/components/src/view/README.md +++ b/packages/components/src/view/README.md @@ -1,6 +1,8 @@ # View -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
`View` is a core component that renders everything in the library. It is the principle component in the entire library. @@ -11,7 +13,7 @@ ```jsx import { __experimentalText as Text, - __experimentalView as View + __experimentalView as View, } from '@wordpress/components'; function Example() { diff --git a/packages/components/src/z-stack/README.md b/packages/components/src/z-stack/README.md index 6a4a31fb38b9f9..7f07104b0654fc 100644 --- a/packages/components/src/z-stack/README.md +++ b/packages/components/src/z-stack/README.md @@ -1,6 +1,8 @@ # ZStack -> **Experimental!** +
+This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes. +
## Usage From 1743b38b75d3d353643ba882a807fe2d3ffd5b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Mon, 24 May 2021 19:21:49 +0200 Subject: [PATCH 07/17] Adapt Gutenberg code to work after global styles lands in core (#32059) Co-authored-by: ntsekouras --- .github/CODEOWNERS | 4 +- lib/block-supports/elements.php | 2 +- lib/block-supports/layout.php | 4 +- ....php => class-wp-theme-json-gutenberg.php} | 8 +- ...lass-wp-theme-json-resolver-gutenberg.php} | 34 +++--- lib/class-wp-theme-json-schema-v0.php | 2 +- lib/client-assets.php | 6 +- lib/full-site-editing/block-templates.php | 4 +- lib/full-site-editing/templates.php | 2 +- lib/global-styles.php | 107 +++++++++++------- lib/load.php | 4 +- phpunit/class-elements-test.php | 6 - phpunit/class-gutenberg-utils-test.php | 6 - phpunit/class-wp-theme-json-resolver-test.php | 12 +- .../class-wp-theme-json-schema-v0-test.php | 6 +- phpunit/class-wp-theme-json-test.php | 106 ++++++++--------- 16 files changed, 165 insertions(+), 148 deletions(-) rename lib/{class-wp-theme-json.php => class-wp-theme-json-gutenberg.php} (99%) rename lib/{class-wp-theme-json-resolver.php => class-wp-theme-json-resolver-gutenberg.php} (93%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b10b72b31a9d7f..7d74d423b42530 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -123,8 +123,8 @@ /lib @timothybjacobs @spacedmonkey /lib/global-styles.php @timothybjabocs @spacedmonkey @nosolosw /lib/experimental-default-theme.json @timothybjabocs @spacedmonkey @nosolosw -/lib/class-wp-theme-json.php @timothybjabocs @spacedmonkey @nosolosw -/lib/class-wp-theme-json-resolver.php @timothybjabocs @spacedmonkey @nosolosw +/lib/class-wp-theme-json-gutenberg.php @timothybjabocs @spacedmonkey @nosolosw +/lib/class-wp-theme-json-resolver-gutenberg.php @timothybjabocs @spacedmonkey @nosolosw /phpunit/class-wp-theme-json-test.php @nosolosw # Native (Unowned) diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php index 85a12b582de511..1db810f8a656bf 100644 --- a/lib/block-supports/elements.php +++ b/lib/block-supports/elements.php @@ -18,7 +18,7 @@ function gutenberg_render_elements_support( $block_content, $block ) { /* * For now we only care about link color. * This code in the future when we have a public API - * should take advantage of WP_Theme_JSON::compute_style_properties + * should take advantage of WP_Theme_JSON_Gutenberg::compute_style_properties * and work for any element and style. */ if ( null === $link_color ) { diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 3dae8a70c190c1..1b1eec679c80a0 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -41,7 +41,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { $used_layout = $block['attrs']['layout']; if ( isset( $used_layout['inherit'] ) && $used_layout['inherit'] ) { - $tree = WP_Theme_JSON_Resolver::get_merged_data( array(), 'theme' ); + $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( array(), 'theme' ); $default_layout = _wp_array_get( $tree->get_settings(), array( 'layout' ) ); if ( ! $default_layout ) { return $block_content; @@ -112,7 +112,7 @@ function gutenberg_restore_group_inner_container( $block_content, $block ) { if ( 'core/group' !== $block['blockName'] || - WP_Theme_JSON_Resolver::theme_has_support() || + WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() || 1 === preg_match( $group_with_inner_container_regex, $block_content ) ) { return $block_content; diff --git a/lib/class-wp-theme-json.php b/lib/class-wp-theme-json-gutenberg.php similarity index 99% rename from lib/class-wp-theme-json.php rename to lib/class-wp-theme-json-gutenberg.php index 2b1600a82236bc..5a7765ef62bedb 100644 --- a/lib/class-wp-theme-json.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -9,7 +9,7 @@ * Class that encapsulates the processing of * structures that adhere to the theme.json spec. */ -class WP_Theme_JSON { +class WP_Theme_JSON_Gutenberg { /** * Container of data in theme.json format. @@ -1075,9 +1075,9 @@ public function get_stylesheet( $type = 'all' ) { /** * Merge new incoming data. * - * @param WP_Theme_JSON $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_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. */ public function merge( $incoming, $update_or_remove = 'remove' ) { $incoming_data = $incoming->get_raw_data(); diff --git a/lib/class-wp-theme-json-resolver.php b/lib/class-wp-theme-json-resolver-gutenberg.php similarity index 93% rename from lib/class-wp-theme-json-resolver.php rename to lib/class-wp-theme-json-resolver-gutenberg.php index 96e04f43c80216..987f3e5400fc26 100644 --- a/lib/class-wp-theme-json-resolver.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -10,19 +10,19 @@ * Class that abstracts the processing * of the different data sources. */ -class WP_Theme_JSON_Resolver { +class WP_Theme_JSON_Resolver_Gutenberg { /** * Container for data coming from core. * - * @var WP_Theme_JSON + * @var WP_Theme_JSON_Gutenberg */ private static $core = null; /** * Container for data coming from the theme. * - * @var WP_Theme_JSON + * @var WP_Theme_JSON_Gutenberg */ private static $theme = null; @@ -36,7 +36,7 @@ class WP_Theme_JSON_Resolver { /** * Container for data coming from the user. * - * @var WP_Theme_JSON + * @var WP_Theme_JSON_Gutenberg */ private static $user = null; @@ -241,7 +241,7 @@ private static function translate( $theme_json, $domain = 'default' ) { /** * Return core's origin config. * - * @return WP_Theme_JSON Entity that holds core data. + * @return WP_Theme_JSON_Gutenberg Entity that holds core data. */ public static function get_core_data() { if ( null !== self::$core ) { @@ -250,7 +250,7 @@ public static function get_core_data() { $config = self::read_json_file( __DIR__ . '/experimental-default-theme.json' ); $config = self::translate( $config ); - self::$core = new WP_Theme_JSON( $config ); + self::$core = new WP_Theme_JSON_Gutenberg( $config ); return self::$core; } @@ -268,7 +268,7 @@ public static function get_core_data() { * * @param array $theme_support_data Theme support data in theme.json format. * - * @return WP_Theme_JSON Entity that holds theme data. + * @return WP_Theme_JSON_Gutenberg Entity that holds theme data. */ public static function get_theme_data( $theme_support_data = array() ) { if ( null === self::$theme ) { @@ -278,7 +278,7 @@ public static function get_theme_data( $theme_support_data = array() ) { $theme_json_data = self::read_json_file( self::get_file_path_from_theme( 'experimental-theme.json' ) ); } $theme_json_data = self::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) ); - self::$theme = new WP_Theme_JSON( $theme_json_data ); + self::$theme = new WP_Theme_JSON_Gutenberg( $theme_json_data ); } if ( empty( $theme_support_data ) ) { @@ -289,7 +289,7 @@ public static function get_theme_data( $theme_support_data = array() ) { * We want the presets and settings declared in theme.json * to override the ones declared via add_theme_support. */ - $with_theme_supports = new WP_Theme_JSON( $theme_support_data ); + $with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data ); $with_theme_supports->merge( self::$theme ); return $with_theme_supports; @@ -333,7 +333,7 @@ private static function get_user_data_from_custom_post_type( $should_create_cpt } elseif ( $should_create_cpt ) { $cpt_post_id = wp_insert_post( array( - 'post_content' => '{"version": ' . WP_Theme_JSON::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }', + 'post_content' => '{"version": ' . WP_Theme_JSON_Gutenberg::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }', 'post_status' => 'publish', 'post_title' => __( 'Custom Styles', 'default' ), 'post_type' => $post_type_filter, @@ -353,7 +353,7 @@ private static function get_user_data_from_custom_post_type( $should_create_cpt /** * Returns the user's origin config. * - * @return WP_Theme_JSON Entity that holds user data. + * @return WP_Theme_JSON_Gutenberg Entity that holds user data. */ public static function get_user_data() { if ( null !== self::$user ) { @@ -368,7 +368,7 @@ public static function get_user_data() { $json_decoding_error = json_last_error(); if ( JSON_ERROR_NONE !== $json_decoding_error ) { error_log( 'Error when decoding user schema: ' . json_last_error_msg() ); - return new WP_Theme_JSON( $config ); + return new WP_Theme_JSON_Gutenberg( $config ); } // Very important to verify if the flag isGlobalStylesUserThemeJSON is true. @@ -382,7 +382,7 @@ public static function get_user_data() { $config = $decoded_data; } } - self::$user = new WP_Theme_JSON( $config ); + self::$user = new WP_Theme_JSON_Gutenberg( $config ); return self::$user; } @@ -409,12 +409,12 @@ public static function get_user_data() { * Valid values are 'theme' or 'user'. * Default is 'user'. * - * @return WP_Theme_JSON + * @return WP_Theme_JSON_Gutenberg */ public static function get_merged_data( $settings = array(), $origin = 'user' ) { - $theme_support_data = WP_Theme_JSON::get_from_editor_settings( $settings ); + $theme_support_data = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $settings ); - $result = new WP_Theme_JSON(); + $result = new WP_Theme_JSON_Gutenberg(); $result->merge( self::get_core_data() ); $result->merge( self::get_theme_data( $theme_support_data ) ); @@ -532,4 +532,4 @@ public static function clean_cached_data() { } -add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) ); +add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver_Gutenberg', 'clean_cached_data' ) ); diff --git a/lib/class-wp-theme-json-schema-v0.php b/lib/class-wp-theme-json-schema-v0.php index 5be707d5bc047c..30a0578178c7f5 100644 --- a/lib/class-wp-theme-json-schema-v0.php +++ b/lib/class-wp-theme-json-schema-v0.php @@ -140,7 +140,7 @@ public static function parse( $old ) { $new['styles'] = self::process_styles( $old['styles'] ); } - $new['version'] = WP_Theme_JSON::LATEST_SCHEMA; + $new['version'] = WP_Theme_JSON_Gutenberg::LATEST_SCHEMA; return $new; } diff --git a/lib/client-assets.php b/lib/client-assets.php index 7e7f3800b791b2..c52c5ae04f2b04 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -361,7 +361,7 @@ function gutenberg_register_packages_styles( $styles ) { ); // Only load the default layout and margin styles for themes without theme.json file. - if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( ! WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { $wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles'; } @@ -663,7 +663,7 @@ function gutenberg_extend_block_editor_styles( $settings ) { } // Remove the default font editor styles for FSE themes. - if ( WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { foreach ( $settings['styles'] as $j => $style ) { if ( 0 === strpos( $style['css'], 'body { font-family:' ) ) { unset( $settings['styles'][ $j ] ); @@ -693,7 +693,7 @@ function gutenberg_extend_block_editor_settings_with_fse_theme_flag( $settings ) $settings['supportsTemplateMode'] = gutenberg_supports_block_templates(); // Enable the new layout options for themes with a theme.json file. - $settings['supportsLayout'] = WP_Theme_JSON_Resolver::theme_has_support(); + $settings['supportsLayout'] = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support(); return $settings; } diff --git a/lib/full-site-editing/block-templates.php b/lib/full-site-editing/block-templates.php index e2d157e2540db2..74f18280d138eb 100644 --- a/lib/full-site-editing/block-templates.php +++ b/lib/full-site-editing/block-templates.php @@ -124,8 +124,8 @@ function _gutenberg_get_template_files( $template_type ) { * @return array Template. */ function _gutenberg_add_template_part_area_info( $template_info ) { - if ( WP_Theme_JSON_Resolver::theme_has_support() ) { - $theme_data = WP_Theme_JSON_Resolver::get_theme_data()->get_template_parts(); + if ( WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { + $theme_data = WP_Theme_JSON_Resolver_Gutenberg::get_theme_data()->get_template_parts(); } if ( isset( $theme_data[ $template_info['slug'] ]['area'] ) ) { diff --git a/lib/full-site-editing/templates.php b/lib/full-site-editing/templates.php index 3b15473692680e..ec5ed3ca8deb3f 100644 --- a/lib/full-site-editing/templates.php +++ b/lib/full-site-editing/templates.php @@ -65,7 +65,7 @@ function gutenberg_register_template_post_type() { * Registers block editor 'wp_theme' taxonomy. */ function gutenberg_register_wp_theme_taxonomy() { - if ( ! gutenberg_supports_block_templates() && ! WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( ! gutenberg_supports_block_templates() && ! WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { return; } diff --git a/lib/global-styles.php b/lib/global-styles.php index 331649d5ba5a72..a5243bbdc5cf48 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -9,8 +9,8 @@ * Takes a tree adhering to the theme.json schema and generates * the corresponding stylesheet. * - * @param WP_Theme_JSON $tree Input tree. - * @param string $type Type of stylesheet we want accepts 'all', 'block_styles', and 'css_variables'. + * @param WP_Theme_JSON_Gutenberg $tree Input tree. + * @param string $type Type of stylesheet we want accepts 'all', 'block_styles', and 'css_variables'. * * @return string Stylesheet. */ @@ -50,12 +50,12 @@ function gutenberg_experimental_global_styles_get_stylesheet( $tree, $type = 'al function gutenberg_experimental_global_styles_enqueue_assets() { if ( ! get_theme_support( 'experimental-link-color' ) && // link color support needs the presets CSS variables regardless of the presence of theme.json file. - ! WP_Theme_JSON_Resolver::theme_has_support() ) { + ! WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { return; } $settings = gutenberg_get_default_block_editor_settings(); - $all = WP_Theme_JSON_Resolver::get_merged_data( $settings ); + $all = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $settings ); $stylesheet = gutenberg_experimental_global_styles_get_stylesheet( $all ); if ( empty( $stylesheet ) ) { @@ -68,12 +68,11 @@ function gutenberg_experimental_global_styles_enqueue_assets() { } /** - * Adds the necessary data for the Global Styles client UI to the block settings. - * - * This can be removed when plugin support requires WordPress 5.8.0+. + * Adds the necessary settings for the Global Styles client UI. * * @param array $settings Existing block editor settings. - * @return array New block editor settings + * + * @return array New block editor settings. */ function gutenberg_experimental_global_styles_settings( $settings ) { // Set what is the context for this data request. @@ -82,7 +81,7 @@ function gutenberg_experimental_global_styles_settings( $settings ) { is_callable( 'get_current_screen' ) && function_exists( 'gutenberg_is_edit_site_page' ) && gutenberg_is_edit_site_page( get_current_screen()->id ) && - WP_Theme_JSON_Resolver::theme_has_support() && + WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() && gutenberg_supports_block_templates() ) { $context = 'site-editor'; @@ -93,28 +92,28 @@ function_exists( 'gutenberg_is_edit_site_page' ) && REST_REQUEST && isset( $_GET['context'] ) && 'mobile' === $_GET['context'] && - WP_Theme_JSON_Resolver::theme_has_support() + WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { $context = 'mobile'; } $origin = 'theme'; if ( - WP_Theme_JSON_Resolver::theme_has_support() && + WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() && gutenberg_supports_block_templates() ) { // Only lookup for the user data if we need it. $origin = 'user'; } - $consolidated = WP_Theme_JSON_Resolver::get_merged_data( $settings, $origin ); + $consolidated = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $settings, $origin ); if ( 'mobile' === $context ) { $settings['__experimentalStyles'] = $consolidated->get_raw_data()['styles']; } if ( 'site-editor' === $context ) { - $theme = WP_Theme_JSON_Resolver::get_merged_data( $settings, 'theme' ); - $user_cpt_id = WP_Theme_JSON_Resolver::get_user_custom_post_type_id(); + $theme = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $settings, 'theme' ); + $user_cpt_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_custom_post_type_id(); $settings['__experimentalGlobalStylesUserEntityId'] = $user_cpt_id; $settings['__experimentalGlobalStylesBaseStyles'] = $theme->get_raw_data(); @@ -123,7 +122,7 @@ function_exists( 'gutenberg_is_edit_site_page' ) && if ( 'site-editor' !== $context && 'mobile' !== $context && - ( WP_Theme_JSON_Resolver::theme_has_support() || get_theme_support( 'experimental-link-color' ) ) + ( WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() || get_theme_support( 'experimental-link-color' ) ) ) { $block_styles = array( 'css' => gutenberg_experimental_global_styles_get_stylesheet( $consolidated, 'block_styles' ) ); $css_variables = array( @@ -135,16 +134,48 @@ function_exists( 'gutenberg_is_edit_site_page' ) && $settings['styles'][] = $block_styles; } + // Copied from get_block_editor_settings() at wordpress-develop/block-editor.php. $settings['__experimentalFeatures'] = $consolidated->get_settings(); - unset( $settings['colors'] ); - unset( $settings['disableCustomColors'] ); - unset( $settings['disableCustomFontSizes'] ); - unset( $settings['disableCustomGradients'] ); - unset( $settings['enableCustomLineHeight'] ); - unset( $settings['enableCustomUnits'] ); - unset( $settings['enableCustomSpacing'] ); - unset( $settings['fontSizes'] ); - unset( $settings['gradients'] ); + if ( isset( $settings['__experimentalFeatures']['color']['palette'] ) ) { + $settings['colors'] = $settings['__experimentalFeatures']['color']['palette']; + unset( $settings['__experimentalFeatures']['color']['palette'] ); + } + if ( isset( $settings['__experimentalFeatures']['color']['gradients'] ) ) { + $settings['gradients'] = $settings['__experimentalFeatures']['color']['gradients']; + unset( $settings['__experimentalFeatures']['color']['gradients'] ); + } + if ( isset( $settings['__experimentalFeatures']['color']['custom'] ) ) { + $settings['disableCustomColors'] = $settings['__experimentalFeatures']['color']['custom']; + unset( $settings['__experimentalFeatures']['color']['custom'] ); + } + if ( isset( $settings['__experimentalFeatures']['color']['customGradient'] ) ) { + $settings['disableCustomGradients'] = $settings['__experimentalFeatures']['color']['customGradient']; + unset( $settings['__experimentalFeatures']['color']['customGradient'] ); + } + if ( isset( $settings['__experimentalFeatures']['typography']['fontSizes'] ) ) { + $settings['fontSizes'] = $settings['__experimentalFeatures']['typography']['fontSizes']; + unset( $settings['__experimentalFeatures']['typography']['fontSizes'] ); + } + if ( isset( $settings['__experimentalFeatures']['typography']['customFontSize'] ) ) { + $settings['disableCustomFontSizes'] = $settings['__experimentalFeatures']['typography']['customFontSize']; + unset( $settings['__experimentalFeatures']['typography']['customFontSize'] ); + } + if ( isset( $settings['__experimentalFeatures']['typography']['customLineHeight'] ) ) { + $settings['enableCustomLineHeight'] = $settings['__experimentalFeatures']['typography']['customLineHeight']; + unset( $settings['__experimentalFeatures']['typography']['customLineHeight'] ); + } + if ( isset( $settings['__experimentalFeatures']['spacing']['units'] ) ) { + if ( ! is_array( $settings['__experimentalFeatures']['spacing']['units'] ) ) { + $settings['enableCustomUnits'] = false; + } else { + $settings['enableCustomUnits'] = count( $settings['__experimentalFeatures']['spacing']['units'] ) > 0; + } + unset( $settings['__experimentalFeatures']['spacing']['units'] ); + } + if ( isset( $settings['__experimentalFeatures']['spacing']['customPadding'] ) ) { + $settings['enableCustomSpacing'] = $settings['__experimentalFeatures']['spacing']['customPadding']; + unset( $settings['__experimentalFeatures']['spacing']['customPadding'] ); + } return $settings; } @@ -155,24 +186,13 @@ function_exists( 'gutenberg_is_edit_site_page' ) && * @return array|undefined */ function gutenberg_experimental_global_styles_register_user_cpt() { - if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( ! WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { return; } - WP_Theme_JSON_Resolver::register_user_custom_post_type(); + WP_Theme_JSON_Resolver_Gutenberg::register_user_custom_post_type(); } -add_action( 'init', 'gutenberg_experimental_global_styles_register_user_cpt' ); -// This can be removed when plugin support requires WordPress 5.8.0+. -if ( function_exists( 'get_block_editor_settings' ) ) { - add_filter( 'block_editor_settings_all', 'gutenberg_experimental_global_styles_settings', PHP_INT_MAX ); -} else { - add_filter( 'block_editor_settings', 'gutenberg_experimental_global_styles_settings', PHP_INT_MAX ); - -} -add_action( 'wp_enqueue_scripts', 'gutenberg_experimental_global_styles_enqueue_assets' ); - - /** * Sanitizes global styles user content removing unsafe rules. * @@ -189,7 +209,7 @@ function gutenberg_global_styles_filter_post( $content ) { $decoded_data['isGlobalStylesUserThemeJSON'] ) { unset( $decoded_data['isGlobalStylesUserThemeJSON'] ); - $theme_json = new WP_Theme_JSON( $decoded_data ); + $theme_json = new WP_Theme_JSON_Gutenberg( $decoded_data ); $theme_json->remove_insecure_properties(); $data_to_encode = $theme_json->get_raw_data(); $data_to_encode['isGlobalStylesUserThemeJSON'] = true; @@ -274,10 +294,19 @@ function gutenberg_global_styles_include_support_for_wp_variables( $allow_css, $ return ! ! preg_match( '/^var\(--wp-[a-zA-Z0-9\-]+\)$/', trim( $parts[1] ) ); } +// The else clause can be removed when plugin support requires WordPress 5.8.0+. +if ( function_exists( 'get_block_editor_settings' ) ) { + add_filter( 'block_editor_settings_all', 'gutenberg_experimental_global_styles_settings', PHP_INT_MAX ); +} else { + add_filter( 'block_editor_settings', 'gutenberg_experimental_global_styles_settings', PHP_INT_MAX ); +} +add_action( 'init', 'gutenberg_experimental_global_styles_register_user_cpt' ); +add_action( 'wp_enqueue_scripts', 'gutenberg_experimental_global_styles_enqueue_assets' ); + +// kses actions&filters. add_action( 'init', 'gutenberg_global_styles_kses_init' ); add_action( 'set_current_user', 'gutenberg_global_styles_kses_init' ); add_filter( 'force_filtered_html_on_import', 'gutenberg_global_styles_force_filtered_html_on_import_filter', 999 ); add_filter( 'safecss_filter_attr_allow_css', 'gutenberg_global_styles_include_support_for_wp_variables', 10, 2 ); // This filter needs to be executed last. - diff --git a/lib/load.php b/lib/load.php index 440a1389f5fd99..12f4f4942c7470 100644 --- a/lib/load.php +++ b/lib/load.php @@ -95,8 +95,8 @@ function gutenberg_is_experiment_enabled( $name ) { // as well as global styles. require __DIR__ . '/interface-wp-theme-json-schema.php'; require __DIR__ . '/class-wp-theme-json-schema-v0.php'; -require __DIR__ . '/class-wp-theme-json.php'; -require __DIR__ . '/class-wp-theme-json-resolver.php'; +require __DIR__ . '/class-wp-theme-json-gutenberg.php'; +require __DIR__ . '/class-wp-theme-json-resolver-gutenberg.php'; require __DIR__ . '/full-site-editing/full-site-editing.php'; require __DIR__ . '/full-site-editing/block-templates.php'; diff --git a/phpunit/class-elements-test.php b/phpunit/class-elements-test.php index 229807ab09ad66..c5ecc36fd4e0d2 100644 --- a/phpunit/class-elements-test.php +++ b/phpunit/class-elements-test.php @@ -4,12 +4,6 @@ * * @package Gutenberg */ - -/** - * Test WP_Theme_JSON class. - * - * @package Gutenberg - */ class Gutenberg_Elements_Test extends WP_UnitTestCase { /** * Given a string containing a class prefixed by "wp-elements-" followed by a unique id, diff --git a/phpunit/class-gutenberg-utils-test.php b/phpunit/class-gutenberg-utils-test.php index bac88678ea8263..52a117ef536063 100644 --- a/phpunit/class-gutenberg-utils-test.php +++ b/phpunit/class-gutenberg-utils-test.php @@ -4,12 +4,6 @@ * * @package Gutenberg */ - -/** - * Test WP_Theme_JSON class. - * - * @package Gutenberg - */ class Gutenberg_Utils_Test extends WP_UnitTestCase { /** * Test gutenberg_experimental_set() with simple non subtree path. diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php index 6b0d0704b98a72..9b1c6792a299bf 100644 --- a/phpunit/class-wp-theme-json-resolver-test.php +++ b/phpunit/class-wp-theme-json-resolver-test.php @@ -1,12 +1,12 @@ assertSame( false, $default ); $this->assertSame( true, $fse ); diff --git a/phpunit/class-wp-theme-json-schema-v0-test.php b/phpunit/class-wp-theme-json-schema-v0-test.php index 7e79e598d60e72..aad503dc7c1616 100644 --- a/phpunit/class-wp-theme-json-schema-v0-test.php +++ b/phpunit/class-wp-theme-json-schema-v0-test.php @@ -1,7 +1,7 @@ array( $defaults => array( @@ -336,7 +336,7 @@ function test_get_stylesheet() { $root_name = WP_Theme_JSON_Schema_V0::ROOT_BLOCK_NAME; $all_blocks_name = WP_Theme_JSON_Schema_V0::ALL_BLOCKS_NAME; - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( 'settings' => array( $all_blocks_name => array( diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index be1358dcf35ec3..58260c4b9045a9 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -1,17 +1,17 @@ WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'custom' => false, @@ -57,9 +57,9 @@ function test_get_settings() { } function test_get_stylesheet() { - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'text' => 'value', @@ -175,9 +175,9 @@ function test_get_stylesheet() { } function test_get_stylesheet_preset_rules_come_after_block_rules() { - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'blocks' => array( 'core/group' => array( @@ -215,9 +215,9 @@ function test_get_stylesheet_preset_rules_come_after_block_rules() { } public function test_get_stylesheet_preset_values_are_marked_as_important() { - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -253,7 +253,7 @@ public function test_get_stylesheet_preset_values_are_marked_as_important() { public function test_merge_incoming_data() { $initial = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'custom' => false, @@ -284,7 +284,7 @@ public function test_merge_incoming_data() { ); $add_new_block = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'blocks' => array( 'core/list' => array( @@ -309,7 +309,7 @@ public function test_merge_incoming_data() { ); $add_key_in_settings = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'customGradient' => true, @@ -318,7 +318,7 @@ public function test_merge_incoming_data() { ); $update_key_in_settings = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'custom' => true, @@ -327,7 +327,7 @@ public function test_merge_incoming_data() { ); $add_styles = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'blocks' => array( 'core/group' => array( @@ -342,7 +342,7 @@ public function test_merge_incoming_data() { ); $add_key_in_styles = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'blocks' => array( 'core/group' => array( @@ -357,7 +357,7 @@ public function test_merge_incoming_data() { ); $add_invalid_context = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'blocks' => array( 'core/para' => array( @@ -370,7 +370,7 @@ public function test_merge_incoming_data() { ); $update_presets = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -404,7 +404,7 @@ public function test_merge_incoming_data() { ); $expected = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'custom' => true, @@ -482,23 +482,23 @@ public function test_merge_incoming_data() { ), ); - $theme_json = new WP_Theme_JSON( $initial ); - $theme_json->merge( new WP_Theme_JSON( $add_new_block ) ); - $theme_json->merge( new WP_Theme_JSON( $add_key_in_settings ) ); - $theme_json->merge( new WP_Theme_JSON( $update_key_in_settings ) ); - $theme_json->merge( new WP_Theme_JSON( $add_styles ) ); - $theme_json->merge( new WP_Theme_JSON( $add_key_in_styles ) ); - $theme_json->merge( new WP_Theme_JSON( $add_invalid_context ) ); - $theme_json->merge( new WP_Theme_JSON( $update_presets ) ); + $theme_json = new WP_Theme_JSON_Gutenberg( $initial ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_new_block ) ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_key_in_settings ) ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $update_key_in_settings ) ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_styles ) ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_key_in_styles ) ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $add_invalid_context ) ); + $theme_json->merge( new WP_Theme_JSON_Gutenberg( $update_presets ) ); $actual = $theme_json->get_raw_data(); $this->assertEqualSetsWithIndex( $expected, $actual ); } function test_remove_insecure_properties_removes_unsafe_styles() { - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'color' => array( 'gradient' => 'url(\'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PHNjcmlwdD5hbGVydCgnb2snKTwvc2NyaXB0PjxsaW5lYXJHcmFkaWVudCBpZD0nZ3JhZGllbnQnPjxzdG9wIG9mZnNldD0nMTAlJyBzdG9wLWNvbG9yPScjRjAwJy8+PHN0b3Agb2Zmc2V0PSc5MCUnIHN0b3AtY29sb3I9JyNmY2MnLz4gPC9saW5lYXJHcmFkaWVudD48cmVjdCBmaWxsPSd1cmwoI2dyYWRpZW50KScgeD0nMCcgeT0nMCcgd2lkdGg9JzEwMCUnIGhlaWdodD0nMTAwJScvPjwvc3ZnPg==\')', @@ -539,7 +539,7 @@ function test_remove_insecure_properties_removes_unsafe_styles() { $theme_json->remove_insecure_properties(); $actual = $theme_json->get_raw_data(); $expected = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'color' => array( 'text' => 'var:preset|color|dark-red', @@ -572,9 +572,9 @@ function test_remove_insecure_properties_removes_unsafe_styles() { } function test_remove_insecure_properties_removes_unsafe_styles_sub_properties() { - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'spacing' => array( 'padding' => array( @@ -627,7 +627,7 @@ function test_remove_insecure_properties_removes_unsafe_styles_sub_properties() $theme_json->remove_insecure_properties(); $actual = $theme_json->get_raw_data(); $expected = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'spacing' => array( 'padding' => array( @@ -675,9 +675,9 @@ function test_remove_insecure_properties_removes_unsafe_styles_sub_properties() } function test_remove_insecure_properties_removes_non_preset_settings() { - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'custom' => true, @@ -736,7 +736,7 @@ function test_remove_insecure_properties_removes_non_preset_settings() { $theme_json->remove_insecure_properties(); $result = $theme_json->get_raw_data(); $expected = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -786,9 +786,9 @@ function test_remove_insecure_properties_removes_non_preset_settings() { } function test_remove_insecure_properties_removes_unsafe_preset_settings() { - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -873,7 +873,7 @@ function test_remove_insecure_properties_removes_unsafe_preset_settings() { $theme_json->remove_insecure_properties(); $result = $theme_json->get_raw_data(); $expected = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'palette' => array( @@ -912,9 +912,9 @@ function test_remove_insecure_properties_removes_unsafe_preset_settings() { } function test_remove_insecure_properties_applies_safe_styles() { - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'color' => array( 'text' => '#abcabc ', // Trailing space. @@ -926,7 +926,7 @@ function test_remove_insecure_properties_applies_safe_styles() { $theme_json->remove_insecure_properties(); $result = $theme_json->get_raw_data(); $expected = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'color' => array( 'text' => '#abcabc ', @@ -937,7 +937,7 @@ function test_remove_insecure_properties_applies_safe_styles() { } function test_get_custom_templates() { - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( 'customTemplates' => array( array( @@ -962,7 +962,7 @@ function test_get_custom_templates() { } function test_get_template_parts() { - $theme_json = new WP_Theme_JSON( + $theme_json = new WP_Theme_JSON_Gutenberg( array( 'templateParts' => array( array( @@ -1016,7 +1016,7 @@ function test_get_from_editor_settings() { ); $expected = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'custom' => false, @@ -1053,7 +1053,7 @@ function test_get_from_editor_settings() { ), ); - $actual = WP_Theme_JSON::get_from_editor_settings( $input ); + $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $input ); $this->assertEqualSetsWithIndex( $expected, $actual ); } @@ -1089,7 +1089,7 @@ function test_get_editor_settings_no_theme_support() { ); $expected = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array( 'color' => array( 'custom' => true, @@ -1105,17 +1105,17 @@ function test_get_editor_settings_no_theme_support() { ), ); - $actual = WP_Theme_JSON::get_from_editor_settings( $input ); + $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $input ); $this->assertEqualSetsWithIndex( $expected, $actual ); } function test_get_editor_settings_blank() { $expected = array( - 'version' => WP_Theme_JSON::LATEST_SCHEMA, + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'settings' => array(), ); - $actual = WP_Theme_JSON::get_from_editor_settings( array() ); + $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( array() ); $this->assertEqualSetsWithIndex( $expected, $actual ); } @@ -1129,7 +1129,7 @@ function test_get_editor_settings_custom_units_can_be_disabled() { 'customPadding' => false, ); - $actual = WP_Theme_JSON::get_from_editor_settings( $input ); + $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $input ); $this->assertEqualSetsWithIndex( $expected, $actual['settings']['spacing'] ); } @@ -1143,7 +1143,7 @@ function test_get_editor_settings_custom_units_can_be_enabled() { 'customPadding' => false, ); - $actual = WP_Theme_JSON::get_from_editor_settings( $input ); + $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $input ); $this->assertEqualSetsWithIndex( $expected, $actual['settings']['spacing'] ); } @@ -1157,7 +1157,7 @@ function test_get_editor_settings_custom_units_can_be_filtered() { 'customPadding' => false, ); - $actual = WP_Theme_JSON::get_from_editor_settings( $input ); + $actual = WP_Theme_JSON_Gutenberg::get_from_editor_settings( $input ); $this->assertEqualSetsWithIndex( $expected, $actual['settings']['spacing'] ); } From 48228473cbe6c65e50251fbccc7d9880e434bd99 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Mon, 24 May 2021 22:28:04 +0400 Subject: [PATCH 08/17] Navigation Editor: Skip "Change detection" tests (#32151) --- .../e2e-tests/specs/experiments/navigation-editor.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/e2e-tests/specs/experiments/navigation-editor.test.js b/packages/e2e-tests/specs/experiments/navigation-editor.test.js index ba62b00c98af0c..9e9d0499387263 100644 --- a/packages/e2e-tests/specs/experiments/navigation-editor.test.js +++ b/packages/e2e-tests/specs/experiments/navigation-editor.test.js @@ -546,11 +546,11 @@ describe( 'Navigation editor', () => { } } - it( 'should not prompt to confirm unsaved changes for the newly selected menu', async () => { + it.skip( 'should not prompt to confirm unsaved changes for the newly selected menu', async () => { await assertIsDirty( false ); } ); - it( 'should prompt to confirm unsaved changes when menu name is edited', async () => { + it.skip( 'should prompt to confirm unsaved changes when menu name is edited', async () => { await page.type( '.edit-navigation-name-editor__text-control input', ' Menu' From 1e3d38813831a8aebfe5d50b8fa0c77142db8afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= Date: Mon, 24 May 2021 22:26:36 +0200 Subject: [PATCH 09/17] Plugin: Update block editor settings to work with context (#32159) * Plugin: Update block editor settings to work with context * Update block-editor.php --- ...-rest-block-editor-settings-controller.php | 4 +- .../wordpress-5.8}/block-editor.php | 142 ++++++++++++++---- .../class-wp-block-editor-context.php | 35 +++++ .../index.php} | 6 + lib/load.php | 3 +- lib/widgets-customize.php | 5 +- lib/widgets-page.php | 5 +- ...r-test.php => class-block-editor-test.php} | 103 ++++++++++++- 8 files changed, 257 insertions(+), 46 deletions(-) rename lib/{ => compat/wordpress-5.8}/block-editor.php (62%) create mode 100644 lib/compat/wordpress-5.8/class-wp-block-editor-context.php rename lib/compat/{wordpress-5.8.php => wordpress-5.8/index.php} (93%) rename phpunit/{block-editor-test.php => class-block-editor-test.php} (67%) diff --git a/lib/class-wp-rest-block-editor-settings-controller.php b/lib/class-wp-rest-block-editor-settings-controller.php index 6c7aa8d77d2c48..77f4a5187b4835 100644 --- a/lib/class-wp-rest-block-editor-settings-controller.php +++ b/lib/class-wp-rest-block-editor-settings-controller.php @@ -75,8 +75,8 @@ public function get_items_permissions_check( $request ) {// phpcs:ignore Variabl * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure. */ public function get_items( $request ) { - $context = ! empty( $request['context'] ) ? $request['context'] : 'post-editor'; - $settings = gutenberg_get_block_editor_settings( $context ); + $editor_context = new WP_Block_Editor_Context(); + $settings = gutenberg_get_block_editor_settings( array(), $editor_context ); return rest_ensure_response( $settings ); } diff --git a/lib/block-editor.php b/lib/compat/wordpress-5.8/block-editor.php similarity index 62% rename from lib/block-editor.php rename to lib/compat/wordpress-5.8/block-editor.php index 922dd87ce032db..f7efc7f1ebf6d5 100644 --- a/lib/block-editor.php +++ b/lib/compat/wordpress-5.8/block-editor.php @@ -69,26 +69,30 @@ function gutenberg_get_default_block_categories() { * * @since 10.5.0 * - * @param string|WP_Post $editor_name_or_post The name of the editor (e.g. 'post-editor') - * or the post object. - * + * @param WP_Post|WP_Block_Editor_Context $post_or_block_editor_context The current post object or + * the block editor context. * @return array[] Array of categories for block types. */ -function gutenberg_get_block_categories( $editor_name_or_post ) { - // Assume the post editor when the WP_Post object passed. - $editor_name = is_object( $editor_name_or_post ) ? 'post-editor' : $editor_name_or_post; - $default_categories = gutenberg_get_default_block_categories(); +function gutenberg_get_block_categories( $post_or_block_editor_context ) { + $block_categories = gutenberg_get_default_block_categories(); + $block_editor_context = $post_or_block_editor_context instanceof WP_Post ? + new WP_Block_Editor_Context( + array( + 'post' => $post_or_block_editor_context, + ) + ) : $post_or_block_editor_context; /** * Filters the default array of categories for block types. * * @since 5.8.0 * - * @param array[] $default_categories Array of categories for block types. + * @param array[] $block_categories Array of categories for block types. + * @param WP_Block_Editor_Context $block_editor_context The current block editor context. */ - $block_categories = apply_filters( 'block_categories_all', $default_categories ); - if ( 'post-editor' === $editor_name ) { - $post = is_object( $editor_name_or_post ) ? $editor_name_or_post : get_post(); + $block_categories = apply_filters( 'block_categories_all', $block_categories, $block_editor_context ); + if ( ! empty( $block_editor_context->post ) ) { + $post = $block_editor_context->post; /** * Filters the default array of categories for block types. @@ -115,25 +119,26 @@ function gutenberg_get_block_categories( $editor_name_or_post ) { * * @since 10.5.0 * - * @param string $editor_name The name of the editor (e.g. 'post-editor'). + * @param WP_Block_Editor_Context $block_editor_context The current block editor context. * * @return bool|array Array of block type slugs, or boolean to enable/disable all. */ -function gutenberg_get_allowed_block_types( $editor_name ) { +function gutenberg_get_allowed_block_types( $block_editor_context ) { $allowed_block_types = true; /** - * Filters the allowed block types for the given editor, defaulting to true (all - * registered block types supported). + * Filters the allowed block types for all editor types, defaulting to `true` + * (all registered block types supported). * * @since 5.8.0 * - * @param bool|array $allowed_block_types Array of block type slugs, or - * boolean to enable/disable all. + * @param bool|array $allowed_block_types Array of block type slugs, or + * boolean to enable/disable all. + * @param WP_Block_Editor_Context $block_editor_context The current block editor context. */ - $allowed_block_types = apply_filters( 'allowed_block_types_all', $allowed_block_types ); - if ( 'post-editor' === $editor_name ) { - $post = get_post(); + $allowed_block_types = apply_filters( 'allowed_block_types_all', $allowed_block_types, $block_editor_context ); + if ( ! empty( $block_editor_context->post ) ) { + $post = $block_editor_context->post; /** * Filters the allowed block types for the editor, defaulting to true (all @@ -251,31 +256,32 @@ function gutenberg_get_default_block_editor_settings() { * * @since 10.5.0 * - * @param string $editor_name The name of the editor (e.g. 'post-editor'). - * @param array $custom_settings Optional custom settings to use with the editor type. + * @param array $custom_settings Custom settings to use with the given editor type. + * @param WP_Block_Editor_Context $block_editor_context The current block editor context. * * @return array The contextualized block editor settings. */ -function gutenberg_get_block_editor_settings( $editor_name, $custom_settings = array() ) { +function gutenberg_get_block_editor_settings( $custom_settings, $block_editor_context ) { $editor_settings = array_merge( - gutenberg_get_default_block_editor_settings( $editor_name ), + gutenberg_get_default_block_editor_settings(), array( - 'allowedBlockTypes' => gutenberg_get_allowed_block_types( $editor_name ), - 'blockCategories' => gutenberg_get_block_categories( $editor_name ), + 'allowedBlockTypes' => gutenberg_get_allowed_block_types( $block_editor_context ), + 'blockCategories' => gutenberg_get_block_categories( $block_editor_context ), ), $custom_settings ); /** - * Filters the settings to pass to the block editor for all editor types. + * Filters the settings to pass to the block editor for all editor type. * * @since 5.8.0 * - * @param array $editor_settings Default editor settings. + * @param array $editor_settings Default editor settings. + * @param WP_Block_Editor_Context $block_editor_context The current block editor context. */ - $editor_settings = apply_filters( 'block_editor_settings_all', $editor_settings ); - if ( 'post-editor' === $editor_name ) { - $post = get_post(); + $editor_settings = apply_filters( 'block_editor_settings_all', $editor_settings, $block_editor_context ); + if ( ! empty( $block_editor_context->post ) ) { + $post = $block_editor_context->post; /** * Filters the settings to pass to the block editor. @@ -291,3 +297,77 @@ function gutenberg_get_block_editor_settings( $editor_name, $custom_settings = a return $editor_settings; } + +/** + * Preloads common data used with the block editor by specifying an array of + * REST API paths that will be preloaded for a given block editor context. + * + * @see https://core.trac.wordpress.org/ticket/52920 + * + * @since 10.7.0 + * + * @global WP_Post $post Global post object. + * + * @param array $preload_paths List of paths to preload. + * @param WP_Block_Editor_Context $block_editor_context The current block editor context. + * + * @return void + */ +function gutenberg_block_editor_rest_api_preload( array $preload_paths, $block_editor_context ) { + global $post; + + /** + * Filters the array of REST API paths that will be used to preloaded common data + * to use with the block editor. + * + * @since 5.8.0 + * + * @param string[] $preload_paths Array of paths to preload. + */ + $preload_paths = apply_filters( 'block_editor_rest_api_preload_paths', $preload_paths, $block_editor_context ); + if ( ! empty( $block_editor_context->post ) ) { + $selected_post = $block_editor_context->post; + + /** + * Preload common data by specifying an array of REST API paths that will be preloaded. + * + * Filters the array of paths that will be preloaded. + * + * @since 5.0.0 + * @deprecated 5.8.0 The hook transitioned to support also screens that don't contain $post instance. + * + * @param string[] $preload_paths Array of paths to preload. + * @param WP_Post $selected_post Post being edited. + */ + $preload_paths = apply_filters_deprecated( 'block_editor_preload_paths', array( $preload_paths, $selected_post ), '5.8.0', 'block_editor_rest_api_preload_paths' ); + } + + if ( empty( $preload_paths ) ) { + return; + } + + /* + * Ensure the global $post remains the same after API data is preloaded. + * Because API preloading can call the_content and other filters, plugins + * can unexpectedly modify $post. + */ + $backup_global_post = ! empty( $post ) ? clone $post : $post; + + $preload_data = array_reduce( + $preload_paths, + 'rest_preload_api_request', + array() + ); + + // Restore the global $post as it was before API preloading. + $post = $backup_global_post; + + wp_add_inline_script( + 'wp-api-fetch', + sprintf( + 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );', + wp_json_encode( $preload_data ) + ), + 'after' + ); +} diff --git a/lib/compat/wordpress-5.8/class-wp-block-editor-context.php b/lib/compat/wordpress-5.8/class-wp-block-editor-context.php new file mode 100644 index 00000000000000..9f146c8b86146d --- /dev/null +++ b/lib/compat/wordpress-5.8/class-wp-block-editor-context.php @@ -0,0 +1,35 @@ +post = $settings['post']; + } + } +} diff --git a/lib/compat/wordpress-5.8.php b/lib/compat/wordpress-5.8/index.php similarity index 93% rename from lib/compat/wordpress-5.8.php rename to lib/compat/wordpress-5.8/index.php index 0129fa91c4a7ca..71040f3b190d16 100644 --- a/lib/compat/wordpress-5.8.php +++ b/lib/compat/wordpress-5.8/index.php @@ -7,6 +7,12 @@ * @package gutenberg */ +if ( ! class_exists( 'WP_Block_Editor_Context' ) ) { + require_once __DIR__ . '/class-wp-block-editor-context.php'; +} + +require_once __DIR__ . '/block-editor.php'; + if ( ! function_exists( 'build_query_vars_from_query_block' ) ) { /** * Helper function that constructs a WP_Query args array from diff --git a/lib/load.php b/lib/load.php index 12f4f4942c7470..66b85974f2a7da 100644 --- a/lib/load.php +++ b/lib/load.php @@ -83,7 +83,7 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/widgets-page.php'; require __DIR__ . '/compat.php'; -require __DIR__ . '/compat/wordpress-5.8.php'; +require __DIR__ . '/compat/wordpress-5.8/index.php'; require __DIR__ . '/utils.php'; require __DIR__ . '/editor-settings.php'; @@ -110,7 +110,6 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/full-site-editing/edit-site-export.php'; require __DIR__ . '/blocks.php'; -require __DIR__ . '/block-editor.php'; require __DIR__ . '/block-patterns.php'; require __DIR__ . '/client-assets.php'; require __DIR__ . '/demo.php'; diff --git a/lib/widgets-customize.php b/lib/widgets-customize.php index be8169487b79fe..bb2013f8c65474 100644 --- a/lib/widgets-customize.php +++ b/lib/widgets-customize.php @@ -116,7 +116,8 @@ function gutenberg_customize_widgets_init() { return; } - $settings = array_merge( + $customizer_context = new WP_Block_Editor_Context(); + $settings = array_merge( gutenberg_get_default_block_editor_settings(), gutenberg_get_legacy_widget_settings() ); @@ -137,7 +138,7 @@ function gutenberg_customize_widgets_init() { wp_add_inline_script( 'wp-blocks', - sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( gutenberg_get_block_categories( 'widgets_customizer' ) ) ), + sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( gutenberg_get_block_categories( $customizer_context ) ) ), 'after' ); diff --git a/lib/widgets-page.php b/lib/widgets-page.php index 1ba9d44c9732da..06376c2c71e396 100644 --- a/lib/widgets-page.php +++ b/lib/widgets-page.php @@ -34,7 +34,8 @@ function gutenberg_widgets_init( $hook ) { add_filter( 'admin_body_class', 'gutenberg_widgets_editor_add_admin_body_classes' ); - $settings = array_merge( + $widgets_editor_context = new WP_Block_Editor_Context(); + $settings = array_merge( gutenberg_get_default_block_editor_settings(), gutenberg_get_legacy_widget_settings() ); @@ -60,7 +61,7 @@ function gutenberg_widgets_init( $hook ) { wp_add_inline_script( 'wp-blocks', - sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( gutenberg_get_block_categories( 'widgets_editor' ) ) ), + sprintf( 'wp.blocks.setCategories( %s );', wp_json_encode( gutenberg_get_block_categories( $widgets_editor_context ) ) ), 'after' ); diff --git a/phpunit/block-editor-test.php b/phpunit/class-block-editor-test.php similarity index 67% rename from phpunit/block-editor-test.php rename to phpunit/class-block-editor-test.php index 633f7987ddbf24..3f19167b2bc54e 100644 --- a/phpunit/block-editor-test.php +++ b/phpunit/class-block-editor-test.php @@ -66,6 +66,24 @@ function filter_set_block_editor_settings_post( $editor_settings, $post ) { ); } + /** + * @ticket 52920 + */ + function test_block_editor_context_no_settings() { + $context = new WP_Block_Editor_Context(); + + $this->assertNull( $context->post ); + } + + /** + * @ticket 52920 + */ + function test_block_editor_context_post() { + $context = new WP_Block_Editor_Context( array( 'post' => get_post() ) ); + + $this->assertSame( get_post(), $context->post ); + } + /** * @ticket 52920 * @expectedDeprecated block_categories @@ -96,7 +114,8 @@ function test_get_block_categories_deprecated_filter_post_object() { function test_get_block_categories_deprecated_filter_post_editor() { add_filter( 'block_categories', array( $this, 'filter_set_block_categories_post' ), 10, 2 ); - $block_categories = gutenberg_get_block_categories( 'post-editor' ); + $post_editor_context = new WP_Block_Editor_Context( array( 'post' => get_post() ) ); + $block_categories = gutenberg_get_block_categories( $post_editor_context ); remove_filter( 'block_categories', array( $this, 'filter_set_block_categories_post' ) ); @@ -116,7 +135,8 @@ function test_get_block_categories_deprecated_filter_post_editor() { * @ticket 52920 */ function test_get_allowed_block_types_default() { - $allowed_block_types = gutenberg_get_allowed_block_types( 'post-editor' ); + $post_editor_context = new WP_Block_Editor_Context( array( 'post' => get_post() ) ); + $allowed_block_types = gutenberg_get_allowed_block_types( $post_editor_context ); $this->assertTrue( $allowed_block_types ); } @@ -128,7 +148,8 @@ function test_get_allowed_block_types_default() { function test_get_allowed_block_types_deprecated_filter_post_editor() { add_filter( 'allowed_block_types', array( $this, 'filter_set_allowed_block_types_post' ), 10, 2 ); - $allowed_block_types = gutenberg_get_allowed_block_types( 'post-editor' ); + $post_editor_context = new WP_Block_Editor_Context( array( 'post' => get_post() ) ); + $allowed_block_types = gutenberg_get_allowed_block_types( $post_editor_context ); remove_filter( 'allowed_block_types', array( $this, 'filter_set_allowed_block_types_post' ) ); @@ -265,7 +286,8 @@ function filter_block_editor_settings_my_editor( $editor_settings ) { add_filter( 'block_categories_all', 'filter_block_categories_my_editor', 10, 1 ); add_filter( 'block_editor_settings_all', 'filter_block_editor_settings_my_editor', 10, 1 ); - $settings = gutenberg_get_block_editor_settings( 'my-editor' ); + $my_editor_context = new WP_Block_Editor_Context(); + $settings = gutenberg_get_block_editor_settings( array(), $my_editor_context ); remove_filter( 'allowed_block_types_all', 'filter_allowed_block_types_my_editor' ); remove_filter( 'block_categories_all', 'filter_block_categories_my_editor' ); @@ -290,10 +312,10 @@ function filter_block_editor_settings_my_editor( $editor_settings ) { * @expectedDeprecated block_editor_settings */ function test_get_block_editor_settings_deprecated_filter_post_editor() { - // This filter needs to run last to account for other filters registered in the plugin. - add_filter( 'block_editor_settings', array( $this, 'filter_set_block_editor_settings_post' ), PHP_INT_MAX, 2 ); + add_filter( 'block_editor_settings', array( $this, 'filter_set_block_editor_settings_post' ), 10, 2 ); - $settings = gutenberg_get_block_editor_settings( 'post-editor' ); + $post_editor_context = new WP_Block_Editor_Context( array( 'post' => get_post() ) ); + $settings = gutenberg_get_block_editor_settings( array(), $post_editor_context ); remove_filter( 'block_editor_settings', array( $this, 'filter_set_block_editor_settings_post' ) ); @@ -304,4 +326,71 @@ function test_get_block_editor_settings_deprecated_filter_post_editor() { $settings ); } + + /** + * @ticket 52920 + */ + function test_block_editor_rest_api_preload_no_paths() { + $editor_context = new WP_Block_Editor_Context(); + gutenberg_block_editor_rest_api_preload( array(), $editor_context ); + + $after = implode( '', wp_scripts()->registered['wp-api-fetch']->extra['after'] ); + $this->assertNotContains( 'wp.apiFetch.createPreloadingMiddleware', $after ); + } + + /** + * @ticket 52920 + * @expectedDeprecated block_editor_preload_paths + */ + function test_block_editor_rest_api_preload_deprecated_filter_post_editor() { + function filter_remove_preload_paths( $preload_paths, $post ) { + if ( empty( $post ) ) { + return $preload_paths; + } + return array(); + } + add_filter( 'block_editor_preload_paths', 'filter_remove_preload_paths', 10, 2 ); + + $post_editor_context = new WP_Block_Editor_Context( array( 'post' => get_post() ) ); + gutenberg_block_editor_rest_api_preload( + array( + array( '/wp/v2/blocks', 'OPTIONS' ), + ), + $post_editor_context + ); + + remove_filter( 'block_editor_preload_paths', 'filter_remove_preload_paths' ); + + $after = implode( '', wp_scripts()->registered['wp-api-fetch']->extra['after'] ); + $this->assertNotContains( 'wp.apiFetch.createPreloadingMiddleware', $after ); + } + + /** + * @ticket 52920 + */ + function test_block_editor_rest_api_preload_filter_all() { + function filter_add_preload_paths( $preload_paths, WP_Block_Editor_Context $context ) { + if ( empty( $context->post ) ) { + array_push( $preload_paths, array( '/wp/v2/types', 'OPTIONS' ) ); + } + + return $preload_paths; + } + add_filter( 'block_editor_rest_api_preload_paths', 'filter_add_preload_paths', 10, 2 ); + + $editor_context = new WP_Block_Editor_Context(); + gutenberg_block_editor_rest_api_preload( + array( + array( '/wp/v2/blocks', 'OPTIONS' ), + ), + $editor_context + ); + + remove_filter( 'block_editor_rest_api_preload_paths', 'filter_add_preload_paths' ); + + $after = implode( '', wp_scripts()->registered['wp-api-fetch']->extra['after'] ); + $this->assertContains( 'wp.apiFetch.createPreloadingMiddleware', $after ); + $this->assertContains( '"\/wp\/v2\/blocks"', $after ); + $this->assertContains( '"\/wp\/v2\/types"', $after ); + } } From 195b80d8e57faec21e3473c176fe41cb93c2a1f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=B3=C5=82kowski?= Date: Mon, 24 May 2021 22:27:03 +0200 Subject: [PATCH 10/17] Components: Fix the list of package dependencies (#32167) Fixes #31868. --- package-lock.json | 3 ++- package.json | 1 + packages/components/package.json | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 00d6305169b2df..bcf83300257837 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1611,6 +1611,7 @@ "version": "10.0.27", "resolved": "https://registry.npmjs.org/@emotion/native/-/native-10.0.27.tgz", "integrity": "sha512-3qxR2XFizGfABKKbX9kAYc0PHhKuCEuyxshoq3TaMEbi9asWHdQVChg32ULpblm4XAf9oxaitAU7J9SfdwFxtw==", + "dev": true, "requires": { "@emotion/primitives-core": "10.0.27" } @@ -1619,6 +1620,7 @@ "version": "10.0.27", "resolved": "https://registry.npmjs.org/@emotion/primitives-core/-/primitives-core-10.0.27.tgz", "integrity": "sha512-fRBEDNPSFFOrBJ0OcheuElayrNTNdLF9DzMxtL0sFgsCFvvadlzwJHhJMSwEJuxwARm9GhVLr1p8G8JGkK98lQ==", + "dev": true, "requires": { "css-to-react-native": "^2.2.1" } @@ -13186,7 +13188,6 @@ "@emotion/cache": "^10.0.27", "@emotion/core": "^10.1.1", "@emotion/css": "^10.0.22", - "@emotion/native": "^10.0.22", "@emotion/styled": "^10.0.23", "@wordpress/a11y": "file:packages/a11y", "@wordpress/compose": "file:packages/compose", diff --git a/package.json b/package.json index 629e4822526db6..a3f1a9d769bbca 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "@babel/plugin-syntax-jsx": "7.12.13", "@babel/runtime-corejs3": "7.13.10", "@babel/traverse": "7.13.0", + "@emotion/native": "10.0.27", "@octokit/rest": "16.26.0", "@octokit/webhooks": "7.1.0", "@storybook/addon-a11y": "6.2.5", diff --git a/packages/components/package.json b/packages/components/package.json index d5f1302929500c..900978d185f20f 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -33,7 +33,6 @@ "@emotion/cache": "^10.0.27", "@emotion/core": "^10.1.1", "@emotion/css": "^10.0.22", - "@emotion/native": "^10.0.22", "@emotion/styled": "^10.0.23", "@wordpress/a11y": "file:../a11y", "@wordpress/compose": "file:../compose", From 891c1e9c94f0b01bf6d78a673a1fe4b472954733 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Mon, 24 May 2021 22:38:45 +0200 Subject: [PATCH 11/17] Build: Fix Storybok by updating path to Elevation components --- packages/components/src/z-stack/stories/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/z-stack/stories/index.js b/packages/components/src/z-stack/stories/index.js index c87909e0033b09..49cacc95b9c131 100644 --- a/packages/components/src/z-stack/stories/index.js +++ b/packages/components/src/z-stack/stories/index.js @@ -6,7 +6,7 @@ import { boolean, number } from '@storybook/addon-knobs'; /** * Internal dependencies */ -import { Elevation } from '../../ui/elevation'; +import { Elevation } from '../../elevation'; import { HStack } from '../../h-stack'; import { View } from '../../view'; import { ZStack } from '..'; From b6e3e1c8c43f8f36e80b7352054cb9c46a136112 Mon Sep 17 00:00:00 2001 From: David Calhoun <438664+dcalhoun@users.noreply.github.com> Date: Tue, 25 May 2021 03:56:39 +0700 Subject: [PATCH 12/17] Fix Xcode 12.5 support (#31632) * Fix Xcode 12.5 support There have been a few issue building React Native in Xcode 12.5. This applies a temporary fix via `patch-package` until we are able upgrade to `react-native` >=0.64.1. - [Example Issue](https://git.io/J35zb) - [0.64.1 Release Notes](https://git.io/J35zN) - [Xcode 12.5 Troubleshooting Guide](https://git.io/J35zp) - [Temporary Fix Applied](https://git.io/J35zj) * Install updated pods Changes captured from running `pod install`. --- packages/react-native-editor/ios/Podfile.lock | 6 ++--- patches/react-native+0.61.5.patch | 26 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/react-native-editor/ios/Podfile.lock b/packages/react-native-editor/ios/Podfile.lock index f716ad708b9350..678900507bdce6 100644 --- a/packages/react-native-editor/ios/Podfile.lock +++ b/packages/react-native-editor/ios/Podfile.lock @@ -416,9 +416,9 @@ SPEC CHECKSUMS: react-native-get-random-values: 03edb8dcc2d3f43e55aa67ea13b61b6723bbf047 react-native-keyboard-aware-scroll-view: 6cb84879bf07e4cc1caed18b11fb928e142adac6 react-native-safe-area: c9cf765aa2dd96159476a99633e7d462ce5bb94f - react-native-safe-area-context: c8da723dcddabe15afe95c9d31c56a0cf2b0141c + react-native-safe-area-context: 133d77d86b13cf694e014ab03dc2944ee3125d97 react-native-slider: 2e42dc91e7ab8b35a9c7f2eb3532729a41d0dbe2 - react-native-video: b8767f54061e475ddd38c22375f46f4d93e5fdfd + react-native-video: e5dd0649534076cd6d09a0db51c617fa668d534a React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76 React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360 React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72 @@ -430,7 +430,7 @@ SPEC CHECKSUMS: React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd ReactNativeDarkMode: 6d807bc8373b872472c8541fc3341817d979a6fb - RNCMaskedView: 66caacf33c86eaa7d22b43178dd998257d5c2e4d + RNCMaskedView: dfeba59697c44d36abec79c062aeb1ea343d610d RNGestureHandler: 7a377d0580c9f07df99e590bbcefd616ee0e2626 RNReanimated: f05baf4cd76b6eab2e4d7e2b244424960b968918 RNScreens: 953633729a42e23ad0c93574d676b361e3335e8b diff --git a/patches/react-native+0.61.5.patch b/patches/react-native+0.61.5.patch index 72f668835cf2d4..550653f231b5ea 100644 --- a/patches/react-native+0.61.5.patch +++ b/patches/react-native+0.61.5.patch @@ -35,6 +35,19 @@ index 01aa75f..572572c 100644 if (_currentFrame) { layer.contentsScale = self.animatedImageScale; layer.contents = (__bridge id)_currentFrame.CGImage; +diff --git a/node_modules/react-native/React/CxxBridge/RCTCxxBridge.mm b/node_modules/react-native/React/CxxBridge/RCTCxxBridge.mm +index bd48f44..d243ed0 100644 +--- a/node_modules/react-native/React/CxxBridge/RCTCxxBridge.mm ++++ b/node_modules/react-native/React/CxxBridge/RCTCxxBridge.mm +@@ -767,7 +767,7 @@ - (void)registerExtraLazyModules + #endif + } + +-- (NSArray *)_initializeModules:(NSArray> *)modules ++- (NSArray *)_initializeModules:(NSArray *)modules + withDispatchGroup:(dispatch_group_t)dispatchGroup + lazilyDiscovered:(BOOL)lazilyDiscovered + { diff --git a/node_modules/react-native/React/Views/RCTShadowView.m b/node_modules/react-native/React/Views/RCTShadowView.m index 40c0cda..646f137 100644 --- a/node_modules/react-native/React/Views/RCTShadowView.m @@ -67,3 +80,16 @@ index 40c0cda..646f137 100644 } return ancestor == shadowView; } +diff --git a/node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm b/node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm +index 3cb73b5..e4a14b4 100644 +--- a/node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm ++++ b/node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm +@@ -297,7 +297,7 @@ - (void)notifyAboutTurboModuleSetup:(const char *)name + @"%@ has no setter or ivar for its bridge, which is not " + "permitted. You must either @synthesize the bridge property, " + "or provide your own setter method.", +- RCTBridgeModuleNameForClass(module)); ++ RCTBridgeModuleNameForClass(Class(module))); + } + } + From c13389b8913b65702afb84fce2f01e685f438a0f Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Tue, 25 May 2021 09:39:55 +1000 Subject: [PATCH 13/17] Fix call to undefined __experimentalRegisterExperimentalCoreBlocks (#32138) --- packages/customize-widgets/src/index.js | 4 +++- packages/edit-widgets/src/index.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/customize-widgets/src/index.js b/packages/customize-widgets/src/index.js index 25e99df5391c8a..1b2d02b3c81fd9 100644 --- a/packages/customize-widgets/src/index.js +++ b/packages/customize-widgets/src/index.js @@ -31,7 +31,9 @@ export function initialize( editorName, blockEditorSettings ) { ); registerCoreBlocks( coreBlocks ); - __experimentalRegisterExperimentalCoreBlocks(); + if ( process.env.GUTENBERG_PHASE === 2 ) { + __experimentalRegisterExperimentalCoreBlocks(); + } registerLegacyWidgetVariations( blockEditorSettings ); diff --git a/packages/edit-widgets/src/index.js b/packages/edit-widgets/src/index.js index 4605bb56346f2f..c1582396ddef25 100644 --- a/packages/edit-widgets/src/index.js +++ b/packages/edit-widgets/src/index.js @@ -33,7 +33,9 @@ export function initialize( id, settings ) { ( block ) => ! [ 'core/more' ].includes( block.name ) ); registerCoreBlocks( coreBlocks ); - __experimentalRegisterExperimentalCoreBlocks(); + if ( process.env.GUTENBERG_PHASE === 2 ) { + __experimentalRegisterExperimentalCoreBlocks(); + } registerLegacyWidgetVariations( settings ); registerBlock( widgetArea ); settings.__experimentalFetchLinkSuggestions = ( search, searchOptions ) => From db415b2a87abe3cb5a74d89b81ccb1e924248f0c Mon Sep 17 00:00:00 2001 From: sarayourfriend <24264157+sarayourfriend@users.noreply.github.com> Date: Mon, 24 May 2021 16:42:18 -0700 Subject: [PATCH 14/17] components: Add missing Divider type reference in tsconfig (#32104) --- packages/components/tsconfig.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/components/tsconfig.json b/packages/components/tsconfig.json index 99adcbbb46ce00..ca00ff32d3db98 100644 --- a/packages/components/tsconfig.json +++ b/packages/components/tsconfig.json @@ -21,10 +21,12 @@ "src/base-control/**/*", "src/dashicon/**/*", "src/disabled/**/*", + "src/divider/**/*", "src/draggable/**/*", "src/elevation/**/*", "src/flex/**/*", "src/form-group/**/*", + "src/heading/**/*", "src/scroll-lock/**/*", "src/shortcut/**/*", "src/spinner/**/*", From 0616cf0268a768bd9357a491f2dd3091b70e6240 Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Tue, 25 May 2021 10:22:02 +1000 Subject: [PATCH 15/17] REST API: Use batch endpoint included in Core (#32174) --- lib/class-wp-rest-batch-controller.php | 308 ------------------ lib/load.php | 3 - lib/rest-api.php | 9 - .../core-data/src/batch/default-processor.js | 2 +- .../src/batch/test/default-processor.js | 2 +- phpunit/class-rest-batch-controller-test.php | 232 ------------- 6 files changed, 2 insertions(+), 554 deletions(-) delete mode 100644 lib/class-wp-rest-batch-controller.php delete mode 100644 phpunit/class-rest-batch-controller-test.php diff --git a/lib/class-wp-rest-batch-controller.php b/lib/class-wp-rest-batch-controller.php deleted file mode 100644 index d5e909f8f57533..00000000000000 --- a/lib/class-wp-rest-batch-controller.php +++ /dev/null @@ -1,308 +0,0 @@ - array( $this, 'serve_batch_request' ), - 'permission_callback' => '__return_true', - 'methods' => 'POST', - 'args' => array( - 'validation' => array( - 'type' => 'string', - 'enum' => array( 'require-all-validate', 'normal' ), - 'default' => 'normal', - ), - 'requests' => array( - 'required' => true, - 'type' => 'array', - 'maxItems' => 25, - 'items' => array( - 'type' => 'object', - 'properties' => array( - 'method' => array( - 'type' => 'string', - 'enum' => array( 'POST', 'PUT', 'PATCH', 'DELETE' ), - 'default' => 'POST', - ), - 'path' => array( - 'type' => 'string', - 'required' => true, - ), - 'body' => array( - 'type' => 'object', - 'properties' => array(), - 'additionalProperties' => true, - ), - 'headers' => array( - 'type' => 'object', - 'properties' => array(), - 'additionalProperties' => array( - 'type' => array( 'string', 'array' ), - 'items' => array( - 'type' => 'string', - ), - ), - ), - ), - ), - ), - ), - ) - ); - } - - /** - * Serves the batch request. - * - * @since 9.2.0 - * - * @param WP_REST_Request $batch_request The batch request object. - * @return WP_REST_Response - */ - public function serve_batch_request( WP_REST_Request $batch_request ) { - $requests = array(); - - foreach ( $batch_request['requests'] as $args ) { - $parsed_url = wp_parse_url( $args['path'] ); - - if ( false === $parsed_url ) { - $requests[] = new WP_Error( 'parse_path_failed', __( 'Could not parse the path.', 'gutenberg' ), array( 'status' => 400 ) ); - - continue; - } - - $single_request = new WP_REST_Request( isset( $args['method'] ) ? $args['method'] : 'POST', $parsed_url['path'] ); - - if ( ! empty( $parsed_url['query'] ) ) { - $query_args = null; // Satisfy linter. - wp_parse_str( $parsed_url['query'], $query_args ); - $single_request->set_query_params( $query_args ); - } - - if ( ! empty( $args['body'] ) ) { - $single_request->set_body_params( $args['body'] ); - } - - if ( ! empty( $args['headers'] ) ) { - $single_request->set_headers( $args['headers'] ); - } - - $requests[] = $single_request; - } - - if ( ! is_callable( array( rest_get_server(), 'match_request_to_handler' ) ) ) { - return $this->polyfill_batching( $requests ); - } - - $matches = array(); - $validation = array(); - $has_error = false; - - foreach ( $requests as $single_request ) { - $match = rest_get_server()->match_request_to_handler( $single_request ); - $matches[] = $match; - $error = null; - - if ( is_wp_error( $match ) ) { - $error = $match; - } - - if ( ! $error ) { - list( $route, $handler ) = $match; - - if ( isset( $handler['allow_batch'] ) ) { - $allow_batch = $handler['allow_batch']; - } else { - $route_options = rest_get_server()->get_route_options( $route ); - $allow_batch = isset( $route_options['allow_batch'] ) ? $route_options['allow_batch'] : false; - } - - if ( ! is_array( $allow_batch ) || empty( $allow_batch['v1'] ) ) { - $error = new WP_Error( - 'rest_batch_not_allowed', - __( 'The requested route does not support batch requests.', 'gutenberg' ), - array( 'status' => 400 ) - ); - } - } - - if ( ! $error ) { - $check_required = $single_request->has_valid_params(); - if ( is_wp_error( $check_required ) ) { - $error = $check_required; - } - } - - if ( ! $error ) { - $check_sanitized = $single_request->sanitize_params(); - if ( is_wp_error( $check_sanitized ) ) { - $error = $check_sanitized; - } - } - - if ( $error ) { - $has_error = true; - $validation[] = $error; - } else { - $validation[] = true; - } - } - - $responses = array(); - - if ( $has_error && 'require-all-validate' === $batch_request['validation'] ) { - foreach ( $validation as $valid ) { - if ( is_wp_error( $valid ) ) { - $responses[] = rest_get_server()->envelope_response( $this->error_to_response( $valid ), false )->get_data(); - } else { - $responses[] = null; - } - } - - return new WP_REST_Response( - array( - 'failed' => 'validation', - 'responses' => $responses, - ), - WP_Http::MULTI_STATUS - ); - } - - foreach ( $requests as $i => $single_request ) { - $clean_request = clone $single_request; - $clean_request->set_url_params( array() ); - $clean_request->set_attributes( array() ); - $clean_request->set_default_params( array() ); - - /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ - $result = apply_filters( 'rest_pre_dispatch', null, rest_get_server(), $clean_request ); - - if ( empty( $result ) ) { - $match = $matches[ $i ]; - $error = null; - - if ( is_wp_error( $validation[ $i ] ) ) { - $error = $validation[ $i ]; - } - - if ( is_wp_error( $match ) ) { - $result = $this->error_to_response( $match ); - } else { - list( $route, $handler ) = $match; - - if ( ! $error && ! is_callable( $handler['callback'] ) ) { - $error = new WP_Error( - 'rest_invalid_handler', - __( 'The handler for the route is invalid', 'gutenberg' ), - array( 'status' => 500 ) - ); - } - - $result = rest_get_server()->respond_to_request( $single_request, $route, $handler, $error ); - } - } - - /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ - $result = apply_filters( 'rest_post_dispatch', rest_ensure_response( $result ), rest_get_server(), $single_request ); - - $responses[] = rest_get_server()->envelope_response( $result, false )->get_data(); - } - - return new WP_REST_Response( array( 'responses' => $responses ), WP_Http::MULTI_STATUS ); - } - - /** - * Polyfills a simple form of batching for compatibility for non-trunk installs. - * - * @since 9.2.0 - * - * @param WP_REST_Request[] $requests The list of requests to perform. - * @return WP_REST_Response The response object. - */ - protected function polyfill_batching( $requests ) { - $responses = array(); - - foreach ( $requests as $request ) { - if ( 0 !== strpos( $request->get_route(), '/__experimental' ) && 0 !== strpos( $request->get_route(), '/wp/v2/widgets' ) ) { - $error = new WP_Error( - 'rest_batch_not_allowed', - __( 'The requested route does not support batch requests.', 'gutenberg' ), - array( 'status' => 400 ) - ); - $responses[] = rest_get_server()->envelope_response( $this->error_to_response( $error ), false )->get_data(); - continue; - } - - $result = rest_get_server()->dispatch( $request ); - /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */ - $result = apply_filters( 'rest_post_dispatch', rest_ensure_response( $result ), rest_get_server(), $request ); - - $responses[] = rest_get_server()->envelope_response( $result, false )->get_data(); - } - - return new WP_REST_Response( array( 'responses' => $responses ), WP_Http::MULTI_STATUS ); - } - - /** - * Converts an error to a response object. - * - * @see WP_REST_Server::error_to_response() This is a temporary copy of that method due to visibility. - * - * @since 9.2.0 - * - * @param WP_Error $error WP_Error instance. - * @return WP_REST_Response List of associative arrays with code and message keys. - */ - protected function error_to_response( $error ) { - $error_data = $error->get_error_data(); - - if ( is_array( $error_data ) && isset( $error_data['status'] ) ) { - $status = $error_data['status']; - } else { - $status = 500; - } - - $errors = array(); - - foreach ( (array) $error->errors as $code => $messages ) { - foreach ( (array) $messages as $message ) { - $errors[] = array( - 'code' => $code, - 'message' => $message, - 'data' => $error->get_error_data( $code ), - ); - } - } - - $data = $errors[0]; - if ( count( $errors ) > 1 ) { - // Remove the primary error. - array_shift( $errors ); - $data['additional_errors'] = $errors; - } - - $response = new WP_REST_Response( $data, $status ); - - return $response; - } -} diff --git a/lib/load.php b/lib/load.php index 66b85974f2a7da..941f3d71b5835a 100644 --- a/lib/load.php +++ b/lib/load.php @@ -56,9 +56,6 @@ function gutenberg_is_experiment_enabled( $name ) { if ( ! class_exists( 'WP_Rest_Customizer_Nonces' ) ) { require_once __DIR__ . '/class-wp-rest-customizer-nonces.php'; } - if ( ! class_exists( 'WP_REST_Batch_Controller' ) ) { - require_once __DIR__ . '/class-wp-rest-batch-controller.php'; - } if ( ! class_exists( 'WP_REST_Templates_Controller' ) ) { require_once __DIR__ . '/full-site-editing/class-wp-rest-templates-controller.php'; } diff --git a/lib/rest-api.php b/lib/rest-api.php index f1336d86b33a47..5cdc258c08d5ab 100644 --- a/lib/rest-api.php +++ b/lib/rest-api.php @@ -64,15 +64,6 @@ function gutenberg_register_sidebars_and_widgets_endpoint() { } add_action( 'rest_api_init', 'gutenberg_register_sidebars_and_widgets_endpoint' ); -/** - * Registers the Batch REST API routes. - */ -function gutenberg_register_batch_endpoint() { - $batch = new WP_REST_Batch_Controller(); - $batch->register_routes(); -} -add_action( 'rest_api_init', 'gutenberg_register_batch_endpoint' ); - /** * Registers the Block editor settings REST API routes. */ diff --git a/packages/core-data/src/batch/default-processor.js b/packages/core-data/src/batch/default-processor.js index 1d98d5af1fb8ff..d459923218e129 100644 --- a/packages/core-data/src/batch/default-processor.js +++ b/packages/core-data/src/batch/default-processor.js @@ -14,7 +14,7 @@ import apiFetch from '@wordpress/api-fetch'; */ export default async function defaultProcessor( requests ) { const batchResponse = await apiFetch( { - path: '/v1/batch', + path: '/batch/v1', method: 'POST', data: { validation: 'require-all-validate', diff --git a/packages/core-data/src/batch/test/default-processor.js b/packages/core-data/src/batch/test/default-processor.js index 888ead29e883d2..c6d2515410b826 100644 --- a/packages/core-data/src/batch/test/default-processor.js +++ b/packages/core-data/src/batch/test/default-processor.js @@ -27,7 +27,7 @@ describe( 'defaultProcessor', () => { ]; const expectedFetchOptions = { - path: '/v1/batch', + path: '/batch/v1', method: 'POST', data: { validation: 'require-all-validate', diff --git a/phpunit/class-rest-batch-controller-test.php b/phpunit/class-rest-batch-controller-test.php deleted file mode 100644 index 3226adb7d12e2d..00000000000000 --- a/phpunit/class-rest-batch-controller-test.php +++ /dev/null @@ -1,232 +0,0 @@ -user->create( - array( - 'role' => 'administrator', - ) - ); - } - - /** - * Delete test data after our tests run. - * - * @since 9.2.0 - */ - public static function wpTearDownAfterClass() { - self::delete_user( self::$administrator_id ); - } - - /** - * @since 9.2.0 - */ - public function setUp() { - parent::setUp(); - - $this->tag_id = self::factory()->tag->create(); - $this->menu_id = wp_create_nav_menu( rand_str() ); - $this->menu_item_id = wp_update_nav_menu_item( - $this->menu_id, - 0, - array( - 'menu-item-type' => 'taxonomy', - 'menu-item-object' => 'post_tag', - 'menu-item-object-id' => $this->tag_id, - 'menu-item-status' => 'publish', - ) - ); - - /** @var WP_REST_Server $wp_rest_server */ - global $wp_rest_server; - $wp_rest_server = new Spy_REST_Server; - do_action( 'rest_api_init', $wp_rest_server ); - } - - /** - * @since 9.2.0 - */ - public function tearDown() { - parent::tearDown(); - /** @var WP_REST_Server $wp_rest_server */ - global $wp_rest_server; - $wp_rest_server = null; - } - - /** - * @ticket 50244 - */ - public function test_batch_requires_allow_batch_opt_in() { - register_rest_route( - 'test-ns/v1', - '/test', - array( - 'methods' => 'POST', - 'callback' => static function () { - return new WP_REST_Response( 'data' ); - }, - 'permission_callback' => '__return_true', - ) - ); - - $request = new WP_REST_Request( 'POST', '/v1/batch' ); - $request->set_body_params( - array( - 'requests' => array( - array( - 'path' => '/test-ns/v1/test', - ), - ), - ) - ); - - $response = rest_do_request( $request ); - - $this->assertEquals( 207, $response->get_status() ); - $this->assertEquals( 'rest_batch_not_allowed', $response->get_data()['responses'][0]['body']['code'] ); - } - - /** - * @ticket 50244 - */ - public function test_batch_pre_validation() { - wp_set_current_user( self::$administrator_id ); - - $request = new WP_REST_Request( 'POST', '/v1/batch' ); - $request->set_body_params( - array( - 'validation' => 'require-all-validate', - 'requests' => array( - array( - 'path' => '/__experimental/menu-items', - 'body' => array( - 'title' => 'Hello World', - 'content' => 'From the moon.', - 'type' => 'custom', - 'url' => '#', - 'menus' => $this->menu_id, - ), - ), - array( - 'path' => '/__experimental/menu-items', - 'body' => array( - 'title' => 'Hello Moon', - 'content' => 'From the world.', - 'status' => 'garbage', - 'type' => 'custom', - 'url' => '#', - 'menus' => $this->menu_id, - ), - ), - ), - ) - ); - - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - - $this->assertEquals( 207, $response->get_status() ); - $this->assertArrayHasKey( 'failed', $data ); - $this->assertEquals( 'validation', $data['failed'] ); - $this->assertCount( 2, $data['responses'] ); - $this->assertNull( $data['responses'][0] ); - $this->assertEquals( 400, $data['responses'][1]['status'] ); - } - - /** - * @ticket 50244 - */ - public function test_batch_create() { - wp_set_current_user( self::$administrator_id ); - - $request = new WP_REST_Request( 'POST', '/v1/batch' ); - $request->set_body_params( - array( - 'requests' => array( - array( - 'path' => '/__experimental/menu-items', - 'body' => array( - 'title' => 'Hello World', - 'content' => 'From the moon.', - 'type' => 'custom', - 'url' => '#', - 'menus' => $this->menu_id, - ), - ), - array( - 'path' => '/__experimental/menu-items', - 'body' => array( - 'title' => 'Hello Moon', - 'status' => 'draft', - 'content' => 'From the world.', - 'type' => 'custom', - 'url' => '#', - 'menus' => $this->menu_id, - ), - ), - ), - ) - ); - - $response = rest_get_server()->dispatch( $request ); - $data = $response->get_data(); - - $this->assertEquals( 207, $response->get_status() ); - $this->assertArrayHasKey( 'responses', $data ); - $this->assertCount( 2, $data['responses'] ); - $this->assertEquals( 'Hello World', $data['responses'][0]['body']['title']['rendered'] ); - $this->assertEquals( 'Hello Moon', $data['responses'][1]['body']['title']['rendered'] ); - } -} From 10b6189ced961376aea8dbb27c67180b8c676fae Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Tue, 25 May 2021 07:31:59 +0400 Subject: [PATCH 16/17] Navigation Screen: Hide sidebar menu isn't selected (#32090) * Fix the visual glitch --- .../src/components/layout/index.js | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/edit-navigation/src/components/layout/index.js b/packages/edit-navigation/src/components/layout/index.js index 74acf52d187bca..f0088cf5d5c4a1 100644 --- a/packages/edit-navigation/src/components/layout/index.js +++ b/packages/edit-navigation/src/components/layout/index.js @@ -94,7 +94,7 @@ export default function Layout( { blockEditorSettings } ) { useMenuNotifications( selectedMenuId ); const hasMenus = !! menus?.length; - const hasPermanentSidebar = isLargeViewport && hasMenus; + const hasPermanentSidebar = isLargeViewport && isMenuSelected; const isBlockEditorReady = !! ( hasMenus && @@ -183,14 +183,16 @@ export default function Layout( { blockEditorSettings } ) { ) } /> - + { isMenuSelected && ( + + ) } From cb99ad2f5bf8a2d32d3c15dbfea891fc11b3ab62 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 24 May 2021 16:33:43 +0800 Subject: [PATCH 17/17] Override sticky styles --- packages/customize-widgets/src/controls/style.scss | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/customize-widgets/src/controls/style.scss b/packages/customize-widgets/src/controls/style.scss index 500e3c9afc41e7..57bc56d9fcbbf3 100644 --- a/packages/customize-widgets/src/controls/style.scss +++ b/packages/customize-widgets/src/controls/style.scss @@ -8,4 +8,17 @@ // Make the entire sidebar background white. min-height: 100%; background-color: $white; + + // Override the inline styles added via JS that make the section title + // sticky feature work. The customize widget block-editor disables this + // sticky title. + padding-top: 10px !important; + + .customize-section-title { + // Disable the sticky title. `!important` as this overrides inline + // styles added via JavaScript. + position: static !important; + top: 0 !important; + width: unset !important; + } }