From b2c4a00b5b92718e5fd5eca0103b4782e5601665 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Mon, 30 Aug 2021 12:24:33 +0200 Subject: [PATCH 1/2] Make Test_Widget compatible with WP_Widget (#34355) * Make Test_Widget compatible with WP_Widget * Move the isset($instance['title']) from update() to form() where it's needed * Explain why codingStandardsIgnoreStart --- packages/e2e-tests/plugins/class-test-widget.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/e2e-tests/plugins/class-test-widget.php b/packages/e2e-tests/plugins/class-test-widget.php index a3ae60658c0d14..11ce978257fe46 100644 --- a/packages/e2e-tests/plugins/class-test-widget.php +++ b/packages/e2e-tests/plugins/class-test-widget.php @@ -48,7 +48,7 @@ public function form( $instance ) { ?>

- +

Date: Mon, 30 Aug 2021 12:58:55 +0200 Subject: [PATCH 2/2] Fix metabox reordering (#30617) --- .../data/data-core-edit-post.md | 16 +++ packages/edit-post/README.md | 5 +- .../src/components/meta-boxes/index.js | 54 ++++++-- packages/edit-post/src/index.js | 7 +- packages/edit-post/src/store/actions.js | 116 ++++++++++-------- packages/edit-post/src/store/reducer.js | 17 +++ packages/edit-post/src/store/selectors.js | 11 ++ 7 files changed, 155 insertions(+), 71 deletions(-) diff --git a/docs/reference-guides/data/data-core-edit-post.md b/docs/reference-guides/data/data-core-edit-post.md index e8dd31780a3ad6..72a76d56fad15f 100644 --- a/docs/reference-guides/data/data-core-edit-post.md +++ b/docs/reference-guides/data/data-core-edit-post.md @@ -6,6 +6,18 @@ Namespace: `core/edit-post`. +### areMetaBoxesInitialized + +Returns true if meta boxes are initialized. + +_Parameters_ + +- _state_ `Object`: Global application state. + +_Returns_ + +- `boolean`: Whether meta boxes are initialized. + ### getActiveGeneralSidebarName Returns the current active general sidebar name, or null if there is no @@ -351,6 +363,10 @@ _Returns_ - `Object`: Action object. +### initializeMetaBoxes + +Initializes WordPress `postboxes` script and the logic for saving meta boxes. + ### metaBoxUpdatesFailure Returns an action object used to signal a failed meta box update. diff --git a/packages/edit-post/README.md b/packages/edit-post/README.md index 9768fe6b6fd211..677e0c8257aa05 100644 --- a/packages/edit-post/README.md +++ b/packages/edit-post/README.md @@ -31,13 +31,10 @@ They can be found in the global variable `wp.editPost` when defining `wp-edit-po Initializes and returns an instance of Editor. -The return value of this function is not necessary if we change where we -call initializeEditor(). This is due to metaBox timing. - _Parameters_ - _id_ `string`: Unique identifier for editor instance. -- _postType_ `Object`: Post type of the post to edit. +- _postType_ `string`: Post type of the post to edit. - _postId_ `Object`: ID of the post to edit. - _settings_ `?Object`: Editor settings object. - _initialEdits_ `Object`: Programmatic edits to apply initially, to be considered as non-user-initiated (bypass for unsaved changes prompt). diff --git a/packages/edit-post/src/components/meta-boxes/index.js b/packages/edit-post/src/components/meta-boxes/index.js index e5e3e2ac2066df..15851ae5247873 100644 --- a/packages/edit-post/src/components/meta-boxes/index.js +++ b/packages/edit-post/src/components/meta-boxes/index.js @@ -6,7 +6,9 @@ import { map } from 'lodash'; /** * WordPress dependencies */ -import { withSelect } from '@wordpress/data'; +import { useSelect, useRegistry } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; +import { store as editorStore } from '@wordpress/editor'; /** * Internal dependencies @@ -15,7 +17,44 @@ import MetaBoxesArea from './meta-boxes-area'; import MetaBoxVisibility from './meta-box-visibility'; import { store as editPostStore } from '../../store'; -function MetaBoxes( { location, isVisible, metaBoxes } ) { +export default function MetaBoxes( { location } ) { + const registry = useRegistry(); + const { + metaBoxes, + isVisible, + areMetaBoxesInitialized, + isEditorReady, + } = useSelect( + ( select ) => { + const { __unstableIsEditorReady } = select( editorStore ); + const { + isMetaBoxLocationVisible, + getMetaBoxesPerLocation, + areMetaBoxesInitialized: _areMetaBoxesInitialized, + } = select( editPostStore ); + return { + metaBoxes: getMetaBoxesPerLocation( location ), + isVisible: isMetaBoxLocationVisible( location ), + areMetaBoxesInitialized: _areMetaBoxesInitialized(), + isEditorReady: __unstableIsEditorReady(), + }; + }, + [ location ] + ); + + // When editor is ready, initialize postboxes (wp core script) and metabox + // saving. This initializes all meta box locations, not just this specific + // one. + useEffect( () => { + if ( isEditorReady && ! areMetaBoxesInitialized ) { + registry.dispatch( editPostStore ).initializeMetaBoxes(); + } + }, [ isEditorReady, areMetaBoxesInitialized ] ); + + if ( ! areMetaBoxesInitialized ) { + return null; + } + return ( <> { map( metaBoxes, ( { id } ) => ( @@ -25,14 +64,3 @@ function MetaBoxes( { location, isVisible, metaBoxes } ) { ); } - -export default withSelect( ( select, { location } ) => { - const { isMetaBoxLocationVisible, getMetaBoxesPerLocation } = select( - editPostStore - ); - - return { - metaBoxes: getMetaBoxesPerLocation( location ), - isVisible: isMetaBoxLocationVisible( location ), - }; -} )( MetaBoxes ); diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 81b5f6a706c2c9..c20cff1441222b 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -14,7 +14,6 @@ import { store as interfaceStore } from '@wordpress/interface'; */ import './hooks'; import './plugins'; -export { store } from './store'; import Editor from './editor'; /** @@ -63,11 +62,8 @@ export function reinitializeEditor( /** * Initializes and returns an instance of Editor. * - * The return value of this function is not necessary if we change where we - * call initializeEditor(). This is due to metaBox timing. - * * @param {string} id Unique identifier for editor instance. - * @param {Object} postType Post type of the post to edit. + * @param {string} postType Post type of the post to edit. * @param {Object} postId ID of the post to edit. * @param {?Object} settings Editor settings object. * @param {Object} initialEdits Programmatic edits to apply initially, to be @@ -170,3 +166,4 @@ export { default as PluginSidebar } from './components/sidebar/plugin-sidebar'; export { default as PluginSidebarMoreMenuItem } from './components/header/plugin-sidebar-more-menu-item'; export { default as __experimentalFullscreenModeClose } from './components/header/fullscreen-mode-close'; export { default as __experimentalMainDashboardButton } from './components/header/main-dashboard-button'; +export { store } from './store'; diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js index d253d55e74efd7..23d7c4613de593 100644 --- a/packages/edit-post/src/store/actions.js +++ b/packages/edit-post/src/store/actions.js @@ -9,7 +9,7 @@ import { castArray, reduce } from 'lodash'; import { __ } from '@wordpress/i18n'; import { apiFetch } from '@wordpress/data-controls'; import { store as interfaceStore } from '@wordpress/interface'; -import { controls, dispatch, select, subscribe } from '@wordpress/data'; +import { controls, select, subscribe, dispatch } from '@wordpress/data'; import { speak } from '@wordpress/a11y'; import { store as noticesStore } from '@wordpress/notices'; import { store as coreStore } from '@wordpress/core-data'; @@ -265,8 +265,6 @@ export function showBlockTypes( blockNames ) { }; } -let saveMetaboxUnsubscribe; - /** * Returns an action object used in signaling * what Meta boxes are available in which location. @@ -280,52 +278,6 @@ export function* setAvailableMetaBoxesPerLocation( metaBoxesPerLocation ) { type: 'SET_META_BOXES_PER_LOCATIONS', metaBoxesPerLocation, }; - - const postType = yield controls.select( editorStore, 'getCurrentPostType' ); - if ( window.postboxes.page !== postType ) { - window.postboxes.add_postbox_toggles( postType ); - } - - let wasSavingPost = yield controls.select( editorStore, 'isSavingPost' ); - let wasAutosavingPost = yield controls.select( - editorStore, - 'isAutosavingPost' - ); - - // Meta boxes are initialized once at page load. It is not necessary to - // account for updates on each state change. - // - // See: https://github.com/WordPress/WordPress/blob/5.1.1/wp-admin/includes/post.php#L2307-L2309 - const hasActiveMetaBoxes = yield controls.select( - editPostStore, - 'hasMetaBoxes' - ); - - // First remove any existing subscription in order to prevent multiple saves - if ( !! saveMetaboxUnsubscribe ) { - saveMetaboxUnsubscribe(); - } - - // Save metaboxes when performing a full save on the post. - saveMetaboxUnsubscribe = subscribe( () => { - const isSavingPost = select( editorStore ).isSavingPost(); - const isAutosavingPost = select( editorStore ).isAutosavingPost(); - - // Save metaboxes on save completion, except for autosaves that are not a post preview. - const shouldTriggerMetaboxesSave = - hasActiveMetaBoxes && - wasSavingPost && - ! isSavingPost && - ! wasAutosavingPost; - - // Save current state for next inspection. - wasSavingPost = isSavingPost; - wasAutosavingPost = isAutosavingPost; - - if ( shouldTriggerMetaboxesSave ) { - dispatch( editPostStore ).requestMetaBoxUpdates(); - } - } ); } /** @@ -531,3 +483,69 @@ export function* __unstableCreateTemplate( template ) { } ); } + +let metaBoxesInitialized = false; + +/** + * Initializes WordPress `postboxes` script and the logic for saving meta boxes. + */ +export function* initializeMetaBoxes() { + const isEditorReady = yield controls.select( + editorStore, + '__unstableIsEditorReady' + ); + + if ( ! isEditorReady ) { + return; + } + + const postType = yield controls.select( editorStore, 'getCurrentPostType' ); + + // Only initialize once. + if ( metaBoxesInitialized ) { + return; + } + + if ( window.postboxes.page !== postType ) { + window.postboxes.add_postbox_toggles( postType ); + } + + metaBoxesInitialized = true; + + let wasSavingPost = yield controls.select( editorStore, 'isSavingPost' ); + let wasAutosavingPost = yield controls.select( + editorStore, + 'isAutosavingPost' + ); + const hasMetaBoxes = yield controls.select( editPostStore, 'hasMetaBoxes' ); + + // Save metaboxes when performing a full save on the post. + subscribe( () => { + const isSavingPost = select( editorStore ).isSavingPost(); + const isAutosavingPost = select( editorStore ).isAutosavingPost(); + + // Save metaboxes on save completion, except for autosaves that are not a post preview. + // + // Meta boxes are initialized once at page load. It is not necessary to + // account for updates on each state change. + // + // See: https://github.com/WordPress/WordPress/blob/5.1.1/wp-admin/includes/post.php#L2307-L2309 + const shouldTriggerMetaboxesSave = + hasMetaBoxes && + wasSavingPost && + ! isSavingPost && + ! wasAutosavingPost; + + // Save current state for next inspection. + wasSavingPost = isSavingPost; + wasAutosavingPost = isAutosavingPost; + + if ( shouldTriggerMetaboxesSave ) { + dispatch( editPostStore ).requestMetaBoxUpdates(); + } + } ); + + return { + type: 'META_BOXES_INITIALIZED', + }; +} diff --git a/packages/edit-post/src/store/reducer.js b/packages/edit-post/src/store/reducer.js index 3441c613f5f619..d3eaa38fac7c06 100644 --- a/packages/edit-post/src/store/reducer.js +++ b/packages/edit-post/src/store/reducer.js @@ -281,9 +281,26 @@ function isEditingTemplate( state = false, action ) { return state; } +/** + * Reducer tracking whether meta boxes are initialized. + * + * @param {boolean} state + * @param {Object} action + * + * @return {boolean} Updated state. + */ +function metaBoxesInitialized( state = false, action ) { + switch ( action.type ) { + case 'META_BOXES_INITIALIZED': + return true; + } + return state; +} + const metaBoxes = combineReducers( { isSaving: isSavingMetaBoxes, locations: metaBoxLocations, + initialized: metaBoxesInitialized, } ); export default combineReducers( { diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js index 2d40810a3cf569..e127f6294210a8 100644 --- a/packages/edit-post/src/store/selectors.js +++ b/packages/edit-post/src/store/selectors.js @@ -367,6 +367,17 @@ export function isEditingTemplate( state ) { return state.isEditingTemplate; } +/** + * Returns true if meta boxes are initialized. + * + * @param {Object} state Global application state. + * + * @return {boolean} Whether meta boxes are initialized. + */ +export function areMetaBoxesInitialized( state ) { + return state.metaBoxes.initialized; +} + /** * Retrieves the template of the currently edited post. *