diff --git a/gutenberg.php b/gutenberg.php index a8e822b1ea4ee..7ab481538e32c 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -43,14 +43,16 @@ function gutenberg_menu() { 'gutenberg' ); - add_submenu_page( - 'gutenberg', - __( 'Widgets (beta)', 'gutenberg' ), - __( 'Widgets (beta)', 'gutenberg' ), - 'edit_theme_options', - 'gutenberg-widgets', - 'the_gutenberg_widgets' - ); + if ( get_option( 'gutenberg-experiments' ) && array_key_exists( 'gutenberg-widget-experiments', get_option( 'gutenberg-experiments' ) ) ) { + add_submenu_page( + 'gutenberg', + __( 'Widgets (beta)', 'gutenberg' ), + __( 'Widgets (beta)', 'gutenberg' ), + 'edit_theme_options', + 'gutenberg-widgets', + 'the_gutenberg_widgets' + ); + } if ( current_user_can( 'edit_posts' ) ) { $submenu['gutenberg'][] = array( @@ -65,6 +67,15 @@ function gutenberg_menu() { 'https://developer.wordpress.org/block-editor/', ); } + + add_submenu_page( + 'gutenberg', + __( 'Experiments Settings', 'gutenberg' ), + __( 'Experiments', 'gutenberg' ), + 'edit_posts', + 'gutenberg-experiments', + 'the_gutenberg_experiments' + ); } add_action( 'admin_menu', 'gutenberg_menu' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php new file mode 100644 index 0000000000000..0ca203444dc81 --- /dev/null +++ b/lib/experiments-page.php @@ -0,0 +1,120 @@ + +
+

+ +
+ + + +
+
+ __( 'Enable Widgets Screen and Legacy Widget Block', 'gutenberg' ), + 'id' => 'gutenberg-widget-experiments', + ) + ); + add_settings_field( + 'gutenberg-menu-block', + __( 'Menu Block', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Enable Navigation Menu Block', 'gutenberg' ), + 'id' => 'gutenberg-menu-block', + ) + ); + register_setting( + 'gutenberg-experiments', + 'gutenberg-experiments' + ); +} + +add_action( 'admin_init', 'gutenberg_initialize_experiments_settings' ); + +/** + * Display a checkbox field for a Gutenberg experiment. + * + * @since 6.3.0 + * + * @param array $args ( $label, $id ). + */ +function gutenberg_display_experiment_field( $args ) { + $options = get_option( 'gutenberg-experiments' ); + $value = isset( $options[ $args['id'] ] ) ? 1 : 0; + ?> + + +

+ + $experiments_exist ? array_key_exists( 'gutenberg-widget-experiments', get_option( 'gutenberg-experiments' ) ) : false, + '__experimentalEnableMenuBlock' => $experiments_exist ? array_key_exists( 'gutenberg-menu-block', get_option( 'gutenberg-experiments' ) ) : false, + ); + return array_merge( $settings, $experiments_settings ); +} +add_filter( 'block_editor_settings', 'gutenberg_experiments_editor_settings' ); diff --git a/lib/load.php b/lib/load.php index c34a8d4fc4d40..f97db4e38eb89 100644 --- a/lib/load.php +++ b/lib/load.php @@ -35,4 +35,5 @@ require dirname( __FILE__ ) . '/demo.php'; require dirname( __FILE__ ) . '/widgets.php'; require dirname( __FILE__ ) . '/widgets-page.php'; +require dirname( __FILE__ ) . '/experiments-page.php'; require dirname( __FILE__ ) . '/customizer.php'; diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 36a256f93cb68..477c8657e40db 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -382,7 +382,9 @@ The default editor settings bodyPlaceholder string Empty post placeholder titlePlaceholder string Empty title placeholder codeEditingEnabled string Whether or not the user can switch to the code editor - \_\_experimentalCanUserUseUnfilteredHTML string Whether the user should be able to use unfiltered HTML or the HTML should be filtered e.g., to remove elements considered insecure like iframes. + **experimentalCanUserUseUnfilteredHTML string Whether the user should be able to use unfiltered HTML or the HTML should be filtered e.g., to remove elements considered insecure like iframes. + **experimentalEnableLegacyWidgetBlock boolean Whether the user has enabled the Legacy Widget Block + \_\_experimentalEnableMenuBlock boolean Whether the user has enabled the Menu Block # **SkipToSelectedBlock** diff --git a/packages/block-editor/src/store/defaults.js b/packages/block-editor/src/store/defaults.js index 1f91e29c7e2f5..885a8b79f7fb0 100644 --- a/packages/block-editor/src/store/defaults.js +++ b/packages/block-editor/src/store/defaults.js @@ -28,6 +28,8 @@ export const PREFERENCES_DEFAULTS = { * titlePlaceholder string Empty title placeholder * codeEditingEnabled string Whether or not the user can switch to the code editor * __experimentalCanUserUseUnfilteredHTML string Whether the user should be able to use unfiltered HTML or the HTML should be filtered e.g., to remove elements considered insecure like iframes. + * __experimentalEnableLegacyWidgetBlock boolean Whether the user has enabled the Legacy Widget Block + * __experimentalEnableMenuBlock boolean Whether the user has enabled the Menu Block */ export const SETTINGS_DEFAULTS = { alignWide: false, @@ -144,5 +146,7 @@ export const SETTINGS_DEFAULTS = { availableLegacyWidgets: {}, hasPermissionsToManageWidgets: false, __experimentalCanUserUseUnfilteredHTML: false, + __experimentalEnableLegacyWidgetBlock: false, + __experimentalEnableMenuBlock: false, }; diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index a9a9b78f34ca9..0d313bc171b20 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -62,6 +62,23 @@ import * as tagCloud from './tag-cloud'; import * as classic from './classic'; +/** + * Function to register an individual block. + * + * @param {Object} block The block to be registered. + * + */ +const registerBlock = ( block ) => { + if ( ! block ) { + return; + } + const { metadata, settings, name } = block; + if ( metadata ) { + unstable__bootstrapServerSideBlockDefinitions( { [ name ]: metadata } ); // eslint-disable-line camelcase + } + registerBlockType( name, settings ); +}; + /** * Function to register core blocks provided by the block editor. * @@ -104,11 +121,8 @@ export const registerCoreBlocks = () => { mediaText, latestComments, latestPosts, - process.env.GUTENBERG_PHASE === 2 ? legacyWidget : null, missing, more, - process.env.GUTENBERG_PHASE === 2 ? navigationMenu : null, - process.env.GUTENBERG_PHASE === 2 ? navigationMenuItem : null, nextpage, preformatted, pullquote, @@ -124,16 +138,7 @@ export const registerCoreBlocks = () => { textColumns, verse, video, - ].forEach( ( block ) => { - if ( ! block ) { - return; - } - const { metadata, settings, name } = block; - if ( metadata ) { - unstable__bootstrapServerSideBlockDefinitions( { [ name ]: metadata } ); // eslint-disable-line camelcase - } - registerBlockType( name, settings ); - } ); + ].forEach( registerBlock ); setDefaultBlockName( paragraph.name ); if ( window.wp && window.wp.oldEditor ) { @@ -145,3 +150,25 @@ export const registerCoreBlocks = () => { setGroupingBlockName( group.name ); } }; + +/** + * Function to register experimental core blocks depending on editor settings. + * + * @param {Object} settings Editor settings. + * + * @example + * ```js + * import { __experimentalRegisterExperimentalCoreBlocks } from '@wordpress/block-library'; + * + * __experimentalRegisterExperimentalCoreBlocks( settings ); + * ``` + */ +export const __experimentalRegisterExperimentalCoreBlocks = process.env.GUTENBERG_PHASE === 2 ? ( settings ) => { + const { __experimentalEnableLegacyWidgetBlock, __experimentalEnableMenuBlock } = settings; + + [ + __experimentalEnableLegacyWidgetBlock ? legacyWidget : null, + __experimentalEnableMenuBlock ? navigationMenu : null, + __experimentalEnableMenuBlock ? navigationMenuItem : null, + ].forEach( registerBlock ); +} : undefined; diff --git a/packages/block-library/src/navigation-menu/index.js b/packages/block-library/src/navigation-menu/index.js index 8ca8e0c3fe560..a7343c61100b4 100644 --- a/packages/block-library/src/navigation-menu/index.js +++ b/packages/block-library/src/navigation-menu/index.js @@ -26,7 +26,7 @@ export const settings = { align: [ 'wide', 'full' ], anchor: true, html: false, - inserter: false, + inserter: true, }, edit, diff --git a/packages/e2e-test-utils/src/enable-experimental-features.js b/packages/e2e-test-utils/src/enable-experimental-features.js new file mode 100644 index 0000000000000..fcb47843b54b9 --- /dev/null +++ b/packages/e2e-test-utils/src/enable-experimental-features.js @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { addQueryArgs } from '@wordpress/url'; + +/** + * Internal dependencies + */ +import { visitAdminPage } from './visit-admin-page'; + +/** + * Enables experimental features from the plugin settings section. + * + * @param {Array} features Array of {string} selectors of settings to enable. Assumes they can be enabled with one click. + */ +export async function enableExperimentalFeatures( features ) { + const query = addQueryArgs( '', { + page: 'gutenberg-experiments', + } ); + await visitAdminPage( '/admin.php', query ); + + await Promise.all( features.map( async ( feature ) => { + await page.waitForSelector( feature ); + await page.click( feature ); + await page.click( '#submit' ); + } ) ); +} diff --git a/packages/e2e-test-utils/src/index.js b/packages/e2e-test-utils/src/index.js index c6839ac84f1d5..06d898b31fc37 100644 --- a/packages/e2e-test-utils/src/index.js +++ b/packages/e2e-test-utils/src/index.js @@ -11,6 +11,7 @@ export { createURL } from './create-url'; export { deactivatePlugin } from './deactivate-plugin'; export { disablePrePublishChecks } from './disable-pre-publish-checks'; export { dragAndResize } from './drag-and-resize'; +export { enableExperimentalFeatures } from './enable-experimental-features'; export { enablePageDialogAccept } from './enable-page-dialog-accept'; export { enablePrePublishChecks } from './enable-pre-publish-checks'; export { ensureSidebarOpened } from './ensure-sidebar-opened'; diff --git a/packages/e2e-tests/specs/block-transforms.test.js b/packages/e2e-tests/specs/block-transforms.test.js index 89d14bf524491..381facd4c0067 100644 --- a/packages/e2e-tests/specs/block-transforms.test.js +++ b/packages/e2e-tests/specs/block-transforms.test.js @@ -19,6 +19,7 @@ import { getEditedPostContent, hasBlockSwitcher, createNewPost, + enableExperimentalFeatures, setPostContent, selectBlockByClientId, transformBlockTo, @@ -99,6 +100,7 @@ describe( 'Block transforms', () => { const transformStructure = {}; beforeAll( async () => { + await enableExperimentalFeatures( [ '#gutenberg-widget-experiments', '#gutenberg-menu-block' ] ); await createNewPost(); for ( const fileBase of fileBasenames ) { diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 8027695313a6f..531f8e1c0267e 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -7,7 +7,7 @@ import '@wordpress/editor'; import '@wordpress/nux'; import '@wordpress/viewport'; import '@wordpress/notices'; -import { registerCoreBlocks } from '@wordpress/block-library'; +import { registerCoreBlocks, __experimentalRegisterExperimentalCoreBlocks } from '@wordpress/block-library'; import { render, unmountComponentAtNode } from '@wordpress/element'; /** @@ -65,8 +65,10 @@ export function reinitializeEditor( postType, postId, target, settings, initialE export function initializeEditor( id, postType, postId, settings, initialEdits ) { const target = document.getElementById( id ); const reboot = reinitializeEditor.bind( null, postType, postId, target, settings, initialEdits ); - registerCoreBlocks(); + if ( process.env.GUTENBERG_PHASE === 2 ) { + __experimentalRegisterExperimentalCoreBlocks( settings ); + } // Show a console log warning if the browser is not in Standards rendering mode. const documentMode = document.compatMode === 'CSS1Compat' ? 'Standards' : 'Quirks'; diff --git a/packages/edit-widgets/src/index.js b/packages/edit-widgets/src/index.js index 16035513da954..7efa0d6c5a4dd 100644 --- a/packages/edit-widgets/src/index.js +++ b/packages/edit-widgets/src/index.js @@ -3,7 +3,7 @@ */ import '@wordpress/notices'; import { render } from '@wordpress/element'; -import { registerCoreBlocks } from '@wordpress/block-library'; +import { registerCoreBlocks, __experimentalRegisterExperimentalCoreBlocks } from '@wordpress/block-library'; /** * Internal dependencies @@ -21,6 +21,9 @@ import CustomizerEditWidgetsInitializer from './components/customizer-edit-widge */ export function initialize( id, settings ) { registerCoreBlocks(); + if ( process.env.GUTENBERG_PHASE === 2 ) { + __experimentalRegisterExperimentalCoreBlocks( settings ); + } render( { beforeAll( () => { unstable__bootstrapServerSideBlockDefinitions( require( './server-registered.json' ) ); - + const settings = { __experimentalEnableLegacyWidgetBlock: true, __experimentalEnableMenuBlock: true }; // Load all hooks that modify blocks require( '../../../packages/editor/src/hooks' ); registerCoreBlocks(); + if ( process.env.GUTENBERG_PHASE === 2 ) { + __experimentalRegisterExperimentalCoreBlocks( settings ); + } } ); blockBasenames.forEach( ( basename ) => {