From 8ce4700beaa52eb40753300c2a8da6d483e5df24 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 28 Oct 2021 14:40:28 +0100 Subject: [PATCH 1/7] Improve the initial loading of the site editor --- lib/full-site-editing/edit-site-page.php | 18 +- .../api-fetch/src/middlewares/preloading.js | 10 +- packages/core-data/src/entities.js | 10 +- packages/core-data/src/reducer.js | 21 -- packages/core-data/src/resolvers.js | 42 ++-- packages/core-data/src/selectors.js | 2 +- .../core-data/src/utils/forward-resolver.js | 14 ++ .../core-data/src/utils/if-not-resolved.js | 22 -- packages/core-data/src/utils/index.js | 2 +- packages/data/src/redux-store/index.js | 18 +- .../edit-site/src/components/editor/index.js | 205 +++++++++--------- .../global-styles/global-styles-provider.js | 21 +- .../menus/content-categories.js | 13 +- .../navigation-panel/menus/content-pages.js | 13 +- .../navigation-panel/menus/content-posts.js | 13 +- .../navigation-panel/menus/templates.js | 4 +- packages/edit-site/src/store/selectors.js | 10 +- 17 files changed, 228 insertions(+), 210 deletions(-) create mode 100644 packages/core-data/src/utils/forward-resolver.js delete mode 100644 packages/core-data/src/utils/if-not-resolved.js diff --git a/lib/full-site-editing/edit-site-page.php b/lib/full-site-editing/edit-site-page.php index f532c37e19d7ee..9004274460a203 100644 --- a/lib/full-site-editing/edit-site-page.php +++ b/lib/full-site-editing/edit-site-page.php @@ -98,9 +98,10 @@ function gutenberg_edit_site_init( $hook ) { '__experimentalBlockPatterns' => WP_Block_Patterns_Registry::get_instance()->get_all_registered(), '__experimentalBlockPatternCategories' => WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(), ); - $site_editor_context = new WP_Block_Editor_Context(); - $settings = gutenberg_get_block_editor_settings( $custom_settings, $site_editor_context ); - + $site_editor_context = new WP_Block_Editor_Context(); + $settings = gutenberg_get_block_editor_settings( $custom_settings, $site_editor_context ); + $active_global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_custom_post_type_id(); + $active_theme = wp_get_theme()->get_stylesheet(); gutenberg_initialize_editor( 'edit_site_editor', 'edit-site', @@ -111,7 +112,16 @@ function gutenberg_edit_site_init( $hook ) { '/wp/v2/types?context=edit', '/wp/v2/taxonomies?context=edit', '/wp/v2/pages?context=edit', - '/wp/v2/themes?status=active', + '/wp/v2/categories?context=edit', + '/wp/v2/posts?context=edit', + '/wp/v2/tags?context=edit', + '/wp/v2/templates?context=edit', + '/wp/v2/template-parts?context=edit', + '/wp/v2/settings', + '/wp/v2/themes?context=edit&status=active', + '/wp/v2/global-styles/' . $active_global_styles_id . '?context=edit', + '/wp/v2/global-styles/' . $active_global_styles_id, + '/wp/v2/themes/' . $active_theme . '/global-styles', ), 'initializer_name' => 'initialize', 'editor_settings' => $settings, diff --git a/packages/api-fetch/src/middlewares/preloading.js b/packages/api-fetch/src/middlewares/preloading.js index 16b061f1d1668b..662e0149edb223 100644 --- a/packages/api-fetch/src/middlewares/preloading.js +++ b/packages/api-fetch/src/middlewares/preloading.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { normalizePath } from '@wordpress/url'; +import { getQueryArg, normalizePath } from '@wordpress/url'; /** * @param {Record} preloadedData @@ -15,9 +15,13 @@ function createPreloadingMiddleware( preloadedData ) { return ( options, next ) => { const { parse = true } = options; - if ( typeof options.path === 'string' ) { + let rawPath = options.path; + if ( ! rawPath && options.url ) { + rawPath = getQueryArg( options.url, 'rest_route' ); + } + if ( typeof rawPath === 'string' ) { const method = options.method || 'GET'; - const path = normalizePath( options.path ); + const path = normalizePath( rawPath ); if ( 'GET' === method && cache[ path ] ) { const cacheData = cache[ path ]; diff --git a/packages/core-data/src/entities.js b/packages/core-data/src/entities.js index 4fd73ea2b86912..a2d580ccabb87e 100644 --- a/packages/core-data/src/entities.js +++ b/packages/core-data/src/entities.js @@ -23,7 +23,7 @@ export const defaultEntities = [ label: __( 'Base' ), name: '__unstableBase', kind: 'root', - baseURL: '', + baseURL: '/', }, { label: __( 'Site' ), @@ -136,6 +136,14 @@ export const defaultEntities = [ plural: 'globalStylesVariations', // should be different than name getTitle: ( record ) => record?.title?.rendered || record?.title, }, + { + label: __( 'Themes' ), + name: 'theme', + kind: 'root', + baseURL: '/wp/v2/themes', + baseURLParams: { context: 'edit' }, + key: 'stylesheet', + }, ]; export const kinds = [ diff --git a/packages/core-data/src/reducer.js b/packages/core-data/src/reducer.js index 8404b59a5a59cd..18bc5287e2f84c 100644 --- a/packages/core-data/src/reducer.js +++ b/packages/core-data/src/reducer.js @@ -136,26 +136,6 @@ export function currentGlobalStylesId( state = undefined, action ) { return state; } -/** - * Reducer managing installed themes. - * - * @param {Object} state Current state. - * @param {Object} action Dispatched action. - * - * @return {Object} Updated state. - */ -export function themes( state = {}, action ) { - switch ( action.type ) { - case 'RECEIVE_CURRENT_THEME': - return { - ...state, - [ action.currentTheme.stylesheet ]: action.currentTheme, - }; - } - - return state; -} - /** * Reducer managing theme supports data. * @@ -590,7 +570,6 @@ export default combineReducers( { currentGlobalStylesId, currentUser, taxonomies, - themes, themeSupports, entities, undo, diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 1b66ae40751765..ffc9bf17f191b3 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -14,7 +14,7 @@ import apiFetch from '@wordpress/api-fetch'; */ import { STORE_NAME } from './name'; import { getKindEntities, DEFAULT_ENTITY_KEY } from './entities'; -import { ifNotResolved, getNormalizedCommaSeparable } from './utils'; +import { forwardResolver, getNormalizedCommaSeparable } from './utils'; /** * Requests authors from the REST API. @@ -115,18 +115,12 @@ export const getEntityRecord = ( kind, name, key = '', query ) => async ( { /** * Requests an entity's record from the REST API. */ -export const getRawEntityRecord = ifNotResolved( - getEntityRecord, - 'getEntityRecord' -); +export const getRawEntityRecord = forwardResolver( 'getEntityRecord' ); /** * Requests an entity's record from the REST API. */ -export const getEditedEntityRecord = ifNotResolved( - getRawEntityRecord, - 'getRawEntityRecord' -); +export const getEditedEntityRecord = forwardResolver( 'getEntityRecord' ); /** * Requests the entity's records from the REST API. @@ -224,20 +218,25 @@ getEntityRecords.shouldInvalidate = ( action, kind, name ) => { /** * Requests the current theme. */ -export const getCurrentTheme = () => async ( { dispatch } ) => { - const activeThemes = await apiFetch( { - path: '/wp/v2/themes?status=active', - } ); +export const getCurrentTheme = () => async ( { dispatch, resolveSelect } ) => { + const activeThemes = await resolveSelect.getEntityRecords( + 'root', + 'theme', + { status: 'active' } + ); + dispatch.receiveCurrentTheme( activeThemes[ 0 ] ); }; /** * Requests theme supports data from the index. */ -export const getThemeSupports = () => async ( { dispatch } ) => { - const activeThemes = await apiFetch( { - path: '/wp/v2/themes?status=active', - } ); +export const getThemeSupports = () => async ( { dispatch, resolveSelect } ) => { + const activeThemes = await resolveSelect.getEntityRecords( + 'root', + 'theme', + { status: 'active' } + ); dispatch.receiveThemeSupports( activeThemes[ 0 ].theme_supports ); }; @@ -421,10 +420,13 @@ __experimentalGetTemplateForLink.shouldInvalidate = ( action ) => { export const __experimentalGetCurrentGlobalStylesId = () => async ( { dispatch, + resolveSelect, } ) => { - const activeThemes = await apiFetch( { - path: '/wp/v2/themes?status=active', - } ); + const activeThemes = await resolveSelect.getEntityRecords( + 'root', + 'theme', + { status: 'active' } + ); const globalStylesURL = get( activeThemes, [ 0, '_links', diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index 9b53670ed4dfdc..b4e108ee7a2f50 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -688,7 +688,7 @@ export function hasRedo( state ) { * @return {Object} The current theme. */ export function getCurrentTheme( state ) { - return state.themes[ state.currentTheme ]; + return getEntityRecord( state, 'root', 'theme', state.currentTheme ); } /** diff --git a/packages/core-data/src/utils/forward-resolver.js b/packages/core-data/src/utils/forward-resolver.js new file mode 100644 index 00000000000000..a38ab2b491d2ad --- /dev/null +++ b/packages/core-data/src/utils/forward-resolver.js @@ -0,0 +1,14 @@ +/** + * Higher-order function which forward the resolution to another resolver with the same arguments. + * + * @param {string} resolverName forwarded resolver. + * + * @return {Function} Enhanced resolver. + */ +const forwardResolver = ( resolverName ) => ( ...args ) => async ( { + resolveSelect, +} ) => { + await resolveSelect[ resolverName ]( ...args ); +}; + +export default forwardResolver; diff --git a/packages/core-data/src/utils/if-not-resolved.js b/packages/core-data/src/utils/if-not-resolved.js deleted file mode 100644 index 653827cdfe6c02..00000000000000 --- a/packages/core-data/src/utils/if-not-resolved.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Higher-order function which invokes the given resolver only if it has not - * already been resolved with the arguments passed to the enhanced function. - * - * This only considers resolution state, and notably does not support resolver - * custom `isFulfilled` behavior. - * - * @param {Function} resolver Original resolver. - * @param {string} selectorName Selector name associated with resolver. - * - * @return {Function} Enhanced resolver. - */ -const ifNotResolved = ( resolver, selectorName ) => ( ...args ) => async ( { - select, - dispatch, -} ) => { - if ( ! select.hasStartedResolution( selectorName, args ) ) { - await dispatch( resolver( ...args ) ); - } -}; - -export default ifNotResolved; diff --git a/packages/core-data/src/utils/index.js b/packages/core-data/src/utils/index.js index a4f4bf81373cd6..c17633c6a17d1d 100644 --- a/packages/core-data/src/utils/index.js +++ b/packages/core-data/src/utils/index.js @@ -1,7 +1,7 @@ export { default as conservativeMapItem } from './conservative-map-item'; export { default as getNormalizedCommaSeparable } from './get-normalized-comma-separable'; export { default as ifMatchingAction } from './if-matching-action'; -export { default as ifNotResolved } from './if-not-resolved'; +export { default as forwardResolver } from './forward-resolver'; export { default as onSubKey } from './on-sub-key'; export { default as replaceAction } from './replace-action'; export { default as withWeakMapCache } from './with-weak-map-cache'; diff --git a/packages/data/src/redux-store/index.js b/packages/data/src/redux-store/index.js index d15f60b4cced6e..72f04f6f1766f4 100644 --- a/packages/data/src/redux-store/index.js +++ b/packages/data/src/redux-store/index.js @@ -26,6 +26,15 @@ import * as metadataActions from './metadata/actions'; /** @typedef {import('../types').WPDataStore} WPDataStore */ /** @typedef {import('../types').WPDataReduxStoreConfig} WPDataReduxStoreConfig */ +const trimUndefinedValues = ( array ) => { + for ( let i = array.length - 1; i >= 0; i-- ) { + if ( array[ i ] === undefined ) { + array.splice( i, 1 ); + } + } + return array; +}; + /** * Create a cache to track whether resolvers started running or not. * @@ -35,7 +44,10 @@ function createResolversCache() { const cache = {}; return { isRunning( selectorName, args ) { - return cache[ selectorName ] && cache[ selectorName ].get( args ); + return ( + cache[ selectorName ] && + cache[ selectorName ].get( trimUndefinedValues( args ) ) + ); }, clear( selectorName, args ) { @@ -49,7 +61,7 @@ function createResolversCache() { cache[ selectorName ] = new EquivalentKeyMap(); } - cache[ selectorName ].set( args, true ); + cache[ selectorName ].set( trimUndefinedValues( args ), true ); }, }; } @@ -324,7 +336,6 @@ function mapResolveSelectors( selectors, store ) { const hasFinished = () => selectors.hasFinishedResolution( selectorName, args ); const getResult = () => selector.apply( null, args ); - // trigger the selector (to trigger the resolver) const result = getResult(); if ( hasFinished() ) { @@ -376,6 +387,7 @@ function mapResolvers( resolvers, selectors, store, resolversCache ) { const selectorResolver = ( ...args ) => { async function fulfillSelector() { const state = store.getState(); + if ( resolversCache.isRunning( selectorName, args ) || ( typeof resolver.isFulfilled === 'function' && diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index b4a0d28056b9dc..e493481dc088f4 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -161,9 +161,10 @@ function Editor( { initialSettings, onError } ) { }, [ isNavigationOpen ] ); // Don't render the Editor until the settings are set and loaded - if ( ! settings?.siteUrl ) { - return null; - } + const isReady = + settings?.siteUrl && + templateType !== undefined && + entityId !== undefined; const secondarySidebar = () => { if ( isInserterOpen ) { @@ -176,107 +177,113 @@ function Editor( { initialSettings, onError } ) { }; return ( - + <> - - - - - - - - - - - - } - secondarySidebar={ secondarySidebar() } - sidebar={ - sidebarIsOpened && ( - - ) - } - header={ -
+ + + + + + + + + + + + } + secondarySidebar={ secondarySidebar() } + sidebar={ + sidebarIsOpened && ( + + ) } - /> - } - notices={ } - content={ - <> - - { template && ( - - ) } - { templateResolved && - ! template && - settings?.siteUrl && - entityId && ( - - { __( - "You attempted to edit an item that doesn't exist. Perhaps it was deleted?" - ) } - - ) } - - - } - actions={ - <> - { isEntitiesSavedStatesOpen ? ( - - ) : ( -
- -
- ) } - - } - footer={ } - /> - - -
-
-
-
-
-
- + + + } + actions={ + <> + { isEntitiesSavedStatesOpen ? ( + + ) : ( +
+ +
+ ) } + + } + footer={ } + /> + + + + + + + + + + ) } + ); } export default Editor; diff --git a/packages/edit-site/src/components/global-styles/global-styles-provider.js b/packages/edit-site/src/components/global-styles/global-styles-provider.js index 79b911067bf570..d9b2b5b13e20b8 100644 --- a/packages/edit-site/src/components/global-styles/global-styles-provider.js +++ b/packages/edit-site/src/components/global-styles/global-styles-provider.js @@ -92,6 +92,7 @@ function useGlobalStylesUserConfig() { styles: record?.styles, }; }, [] ); + const { getEditedEntityRecord } = useSelect( coreStore ); const { editEntityRecord } = useDispatch( coreStore ); @@ -125,7 +126,7 @@ function useGlobalStylesUserConfig() { [ globalStylesId ] ); - return [ config, setConfig ]; + return [ !! settings || !! styles, config, setConfig ]; } function useGlobalStylesBaseConfig() { @@ -138,25 +139,39 @@ function useGlobalStylesBaseConfig() { } function useGlobalStylesContext() { - const [ userConfig, setUserConfig ] = useGlobalStylesUserConfig(); + const [ + isUserConfigReady, + userConfig, + setUserConfig, + ] = useGlobalStylesUserConfig(); const baseConfig = useGlobalStylesBaseConfig(); const mergedConfig = useMemo( () => { return mergeBaseAndUserConfigs( baseConfig, userConfig ); }, [ userConfig, baseConfig ] ); const context = useMemo( () => { return { + isReady: isUserConfigReady, user: userConfig, base: baseConfig, merged: mergedConfig, setUserConfig, }; - }, [ mergedConfig, userConfig, baseConfig, setUserConfig ] ); + }, [ + mergedConfig, + userConfig, + baseConfig, + setUserConfig, + isUserConfigReady, + ] ); return context; } export function GlobalStylesProvider( { children } ) { const context = useGlobalStylesContext(); + if ( ! context.isReady ) { + return null; + } return ( diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-categories.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-categories.js index 91138170cf993f..8d99cf475012c6 100644 --- a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-categories.js +++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-categories.js @@ -30,13 +30,12 @@ export default function ContentCategoriesMenu() { const { getEntityRecords, hasFinishedResolution } = select( coreStore ); - const getEntityRecordsArgs = [ - 'taxonomy', - 'category', - { - search: searchQuery, - }, - ]; + const query = searchQuery + ? { + search: searchQuery, + } + : undefined; + const getEntityRecordsArgs = [ 'taxonomy', 'category', query ]; const hasResolvedPosts = hasFinishedResolution( 'getEntityRecords', getEntityRecordsArgs diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-pages.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-pages.js index 21a857d9b54cd3..bb927f44507f13 100644 --- a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-pages.js +++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-pages.js @@ -30,13 +30,12 @@ export default function ContentPagesMenu() { const { getEntityRecords, hasFinishedResolution } = select( coreStore ); - const getEntityRecordsArgs = [ - 'postType', - 'page', - { - search: searchQuery, - }, - ]; + const query = searchQuery + ? { + search: searchQuery, + } + : undefined; + const getEntityRecordsArgs = [ 'postType', 'page', query ]; const hasResolvedPosts = hasFinishedResolution( 'getEntityRecords', getEntityRecordsArgs diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-posts.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-posts.js index b4b105e5f4c725..c1593627ffebec 100644 --- a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-posts.js +++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/content-posts.js @@ -34,13 +34,12 @@ export default function ContentPostsMenu() { getEditedEntityRecord, hasFinishedResolution, } = select( coreStore ); - const getEntityRecodsArgs = [ - 'postType', - 'post', - { - search: searchQuery, - }, - ]; + const query = searchQuery + ? { + search: searchQuery, + } + : undefined; + const getEntityRecodsArgs = [ 'postType', 'post', query ]; const hasResolvedPosts = hasFinishedResolution( 'getEntityRecords', getEntityRecodsArgs diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js index 1119cc7aa1eccc..1e4de3f2358ad0 100644 --- a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js +++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js @@ -44,9 +44,7 @@ export default function TemplatesMenu() { const { templates, showOnFront } = useSelect( ( select ) => { const { getEntityRecords, getEditedEntityRecord } = select( coreStore ); return { - templates: getEntityRecords( 'postType', 'wp_template', { - per_page: -1, - } ), + templates: getEntityRecords( 'postType', 'wp_template' ), showOnFront: getEditedEntityRecord( 'root', 'site' ).show_on_front, }; }, [] ); diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js index b539cec121578c..a6f46f455b05f7 100644 --- a/packages/edit-site/src/store/selectors.js +++ b/packages/edit-site/src/store/selectors.js @@ -223,10 +223,7 @@ export const getCurrentTemplateNavigationPanelSubMenu = createRegistrySelector( const templates = select( coreDataStore ).getEntityRecords( 'postType', - 'wp_template', - { - per_page: -1, - } + 'wp_template' ); const showOnFront = select( coreDataStore ).getEditedEntityRecord( 'root', @@ -314,10 +311,7 @@ export const getCurrentTemplateTemplateParts = createRegistrySelector( const templateParts = select( coreDataStore ).getEntityRecords( 'postType', - 'wp_template_part', - { - per_page: -1, - } + 'wp_template_part' ); const templatePartsById = keyBy( templateParts, From f72e368abceb8286ae67ec0e33e4544ee10ed6ed Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 28 Oct 2021 17:10:44 +0100 Subject: [PATCH 2/7] Fix JS unit tests --- .../src/utils/test/if-not-resolved.js | 76 ------------------- 1 file changed, 76 deletions(-) delete mode 100644 packages/core-data/src/utils/test/if-not-resolved.js diff --git a/packages/core-data/src/utils/test/if-not-resolved.js b/packages/core-data/src/utils/test/if-not-resolved.js deleted file mode 100644 index 291e224b3833cd..00000000000000 --- a/packages/core-data/src/utils/test/if-not-resolved.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * WordPress dependencies - */ -import { controls } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import ifNotResolved from '../if-not-resolved'; - -jest.mock( '@wordpress/data', () => ( { - controls: { - select: jest.fn(), - }, -} ) ); - -describe( 'ifNotResolved', () => { - beforeEach( () => { - controls.select.mockReset(); - } ); - - it( 'returns a new function', () => { - const originalResolver = () => {}; - - const resolver = ifNotResolved( originalResolver, 'originalResolver' ); - - expect( resolver ).toBeInstanceOf( Function ); - } ); - - it( 'triggers original resolver if not already resolved', async () => { - const select = { hasStartedResolution: () => false }; - const dispatch = () => {}; - - const originalResolver = jest - .fn() - .mockImplementation( async function () {} ); - - const resolver = ifNotResolved( originalResolver, 'originalResolver' ); - await resolver()( { select, dispatch } ); - - expect( originalResolver ).toHaveBeenCalledTimes( 1 ); - } ); - - it( 'does not trigger original resolver if already resolved', async () => { - const select = { hasStartedResolution: () => true }; - const dispatch = () => {}; - - const originalResolver = jest - .fn() - .mockImplementation( async function () {} ); - - const resolver = ifNotResolved( originalResolver, 'originalResolver' ); - await resolver()( { select, dispatch } ); - - expect( originalResolver ).toHaveBeenCalledTimes( 0 ); - } ); - - it( 'returns a promise when the resolver was not already resolved', async () => { - const select = { hasStartedResolution: () => false }; - let thunkRetval; - const dispatch = jest.fn( ( thunk ) => { - thunkRetval = thunk(); - return thunkRetval; - } ); - - const originalResolver = jest.fn( () => () => - Promise.resolve( 'success!' ) - ); - - const resolver = ifNotResolved( originalResolver, 'originalResolver' ); - const result = resolver()( { select, dispatch } ); - - await expect( result ).resolves.toBe( undefined ); - await expect( thunkRetval ).resolves.toBe( 'success!' ); - } ); -} ); From 701542b929d4c52cbf2de00b9ebcd2a875e743df Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 28 Oct 2021 17:12:20 +0100 Subject: [PATCH 3/7] Fix phpcs --- lib/full-site-editing/edit-site-page.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/full-site-editing/edit-site-page.php b/lib/full-site-editing/edit-site-page.php index 9004274460a203..3264ce845dbd9a 100644 --- a/lib/full-site-editing/edit-site-page.php +++ b/lib/full-site-editing/edit-site-page.php @@ -89,7 +89,7 @@ function gutenberg_edit_site_init( $hook ) { */ $current_screen->is_block_editor( true ); - $custom_settings = array( + $custom_settings = array( 'siteUrl' => site_url(), 'postsPerPage' => get_option( 'posts_per_page' ), 'styles' => gutenberg_get_editor_styles(), From a782d7145fe74606875bbbcb9576fd20fc07f292 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 28 Oct 2021 17:29:16 +0100 Subject: [PATCH 4/7] Refactor theme supports --- docs/reference-guides/data/data-core.md | 6 ++---- .../api-fetch/src/middlewares/preloading.js | 6 +++++- packages/core-data/README.md | 6 ++---- packages/core-data/src/actions.js | 12 +++++++---- packages/core-data/src/reducer.js | 21 ------------------- packages/core-data/src/resolvers.js | 9 +------- packages/core-data/src/selectors.js | 2 +- 7 files changed, 19 insertions(+), 43 deletions(-) diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index 16f4d6305fecf1..8bf9b08c273548 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -626,11 +626,9 @@ _Returns_ ### receiveThemeSupports -Returns an action object used in signalling that the index has been received. - -_Parameters_ +> **Deprecated** since WP 5.9, this is not useful anymore, use the selector direclty. -- _themeSupports_ `Object`: Theme support for the current theme. +Returns an action object used in signalling that the index has been received. _Returns_ diff --git a/packages/api-fetch/src/middlewares/preloading.js b/packages/api-fetch/src/middlewares/preloading.js index 662e0149edb223..761c295cac78a2 100644 --- a/packages/api-fetch/src/middlewares/preloading.js +++ b/packages/api-fetch/src/middlewares/preloading.js @@ -15,9 +15,13 @@ function createPreloadingMiddleware( preloadedData ) { return ( options, next ) => { const { parse = true } = options; + /** @type {string | void} */ let rawPath = options.path; if ( ! rawPath && options.url ) { - rawPath = getQueryArg( options.url, 'rest_route' ); + const pathFromQuery = getQueryArg( options.url, 'rest_route' ); + if ( typeof pathFromQuery === 'string' ) { + rawPath = pathFromQuery; + } } if ( typeof rawPath === 'string' ) { const method = options.method || 'GET'; diff --git a/packages/core-data/README.md b/packages/core-data/README.md index f51e091eef84a3..09afdb0ece16fd 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -160,11 +160,9 @@ _Returns_ ### receiveThemeSupports -Returns an action object used in signalling that the index has been received. - -_Parameters_ +> **Deprecated** since WP 5.9, this is not useful anymore, use the selector direclty. -- _themeSupports_ `Object`: Theme support for the current theme. +Returns an action object used in signalling that the index has been received. _Returns_ diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 0b184f8fec4e7f..430090ccb989dc 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -9,6 +9,7 @@ import { v4 as uuid } from 'uuid'; */ import apiFetch from '@wordpress/api-fetch'; import { addQueryArgs } from '@wordpress/url'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -136,14 +137,17 @@ export function __experimentalReceiveCurrentGlobalStylesId( /** * Returns an action object used in signalling that the index has been received. * - * @param {Object} themeSupports Theme support for the current theme. + * @deprecated since WP 5.9, this is not useful anymore, use the selector direclty. * * @return {Object} Action object. */ -export function receiveThemeSupports( themeSupports ) { +export function receiveThemeSupports() { + deprecated( "wp.data.dispatch( 'core' ).receiveThemeSupports", { + since: '5.9', + } ); + return { - type: 'RECEIVE_THEME_SUPPORTS', - themeSupports, + type: 'DO_NOTHING', }; } diff --git a/packages/core-data/src/reducer.js b/packages/core-data/src/reducer.js index 18bc5287e2f84c..6f75216be6a54c 100644 --- a/packages/core-data/src/reducer.js +++ b/packages/core-data/src/reducer.js @@ -136,26 +136,6 @@ export function currentGlobalStylesId( state = undefined, action ) { return state; } -/** - * Reducer managing theme supports data. - * - * @param {Object} state Current state. - * @param {Object} action Dispatched action. - * - * @return {Object} Updated state. - */ -export function themeSupports( state = {}, action ) { - switch ( action.type ) { - case 'RECEIVE_THEME_SUPPORTS': - return { - ...state, - ...action.themeSupports, - }; - } - - return state; -} - /** * Higher Order Reducer for a given entity config. It supports: * @@ -570,7 +550,6 @@ export default combineReducers( { currentGlobalStylesId, currentUser, taxonomies, - themeSupports, entities, undo, embedPreviews, diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index ffc9bf17f191b3..9667f457a5f776 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -231,14 +231,7 @@ export const getCurrentTheme = () => async ( { dispatch, resolveSelect } ) => { /** * Requests theme supports data from the index. */ -export const getThemeSupports = () => async ( { dispatch, resolveSelect } ) => { - const activeThemes = await resolveSelect.getEntityRecords( - 'root', - 'theme', - { status: 'active' } - ); - dispatch.receiveThemeSupports( activeThemes[ 0 ].theme_supports ); -}; +export const getThemeSupports = forwardResolver( 'getCurrentTheme' ); /** * Requests a preview from the from the Embed API. diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index b4e108ee7a2f50..e567df8534e82e 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -710,7 +710,7 @@ export function __experimentalGetCurrentGlobalStylesId( state ) { * @return {*} Index data. */ export function getThemeSupports( state ) { - return state.themeSupports; + return getCurrentTheme( state )?.theme_supports; } /** From 679d966ffa2b060a33034d4a10878a93cdad9072 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Fri, 29 Oct 2021 09:17:01 +0100 Subject: [PATCH 5/7] Fix small bug --- packages/data/src/redux-store/index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/data/src/redux-store/index.js b/packages/data/src/redux-store/index.js index 72f04f6f1766f4..ba0842329dd063 100644 --- a/packages/data/src/redux-store/index.js +++ b/packages/data/src/redux-store/index.js @@ -27,12 +27,13 @@ import * as metadataActions from './metadata/actions'; /** @typedef {import('../types').WPDataReduxStoreConfig} WPDataReduxStoreConfig */ const trimUndefinedValues = ( array ) => { - for ( let i = array.length - 1; i >= 0; i-- ) { - if ( array[ i ] === undefined ) { - array.splice( i, 1 ); + const result = [ ...array ]; + for ( let i = result.length - 1; i >= 0; i-- ) { + if ( result[ i ] === undefined ) { + result.splice( i, 1 ); } } - return array; + return result; }; /** @@ -52,7 +53,7 @@ function createResolversCache() { clear( selectorName, args ) { if ( cache[ selectorName ] ) { - cache[ selectorName ].delete( args ); + cache[ selectorName ].delete( trimUndefinedValues( args ) ); } }, From 2e2ceda0849c04c68a68ef4ec39d96871d25bb0e Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Fri, 29 Oct 2021 15:42:16 +0400 Subject: [PATCH 6/7] Fix e2e test --- packages/block-library/src/embed/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/embed/edit.js b/packages/block-library/src/embed/edit.js index 570f657a8e176e..03bb556f794c69 100644 --- a/packages/block-library/src/embed/edit.js +++ b/packages/block-library/src/embed/edit.js @@ -89,7 +89,7 @@ const EmbedEdit = ( props ) => { return { preview: validPreview ? embedPreview : undefined, fetching: isRequestingEmbedPreview( attributesUrl ), - themeSupportsResponsive: getThemeSupports()[ + themeSupportsResponsive: getThemeSupports()?.[ 'responsive-embeds' ], cannotEmbed: ! validPreview || previewIsFallback, From 2e6eddc016b6280086b38eb1356372432c4330da Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Mon, 1 Nov 2021 14:07:03 +0100 Subject: [PATCH 7/7] Ensure getThemeSupports is backward compatible --- packages/block-library/src/embed/edit.js | 2 +- packages/core-data/src/selectors.js | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/embed/edit.js b/packages/block-library/src/embed/edit.js index 03bb556f794c69..570f657a8e176e 100644 --- a/packages/block-library/src/embed/edit.js +++ b/packages/block-library/src/embed/edit.js @@ -89,7 +89,7 @@ const EmbedEdit = ( props ) => { return { preview: validPreview ? embedPreview : undefined, fetching: isRequestingEmbedPreview( attributesUrl ), - themeSupportsResponsive: getThemeSupports()?.[ + themeSupportsResponsive: getThemeSupports()[ 'responsive-embeds' ], cannotEmbed: ! validPreview || previewIsFallback, diff --git a/packages/core-data/src/selectors.js b/packages/core-data/src/selectors.js index e567df8534e82e..02fa412723a416 100644 --- a/packages/core-data/src/selectors.js +++ b/packages/core-data/src/selectors.js @@ -19,6 +19,15 @@ import { getQueriedItems } from './queried-data'; import { DEFAULT_ENTITY_KEY } from './entities'; import { getNormalizedCommaSeparable, isRawAttribute } from './utils'; +/** + * Shared reference to an empty object for cases where it is important to avoid + * returning a new object reference on every invocation, as in a connected or + * other pure component which performs `shouldComponentUpdate` check on props. + * This should be used as a last resort, since the normalized data should be + * maintained by the reducer result in state. + */ +const EMPTY_OBJECT = {}; + /** * Shared reference to an empty array for cases where it is important to avoid * returning a new array reference on every invocation, as in a connected or @@ -710,7 +719,7 @@ export function __experimentalGetCurrentGlobalStylesId( state ) { * @return {*} Index data. */ export function getThemeSupports( state ) { - return getCurrentTheme( state )?.theme_supports; + return getCurrentTheme( state )?.theme_supports ?? EMPTY_OBJECT; } /**