diff --git a/lib/widgets.php b/lib/widgets.php index d309fd2610dd65..d076cc31c9862e 100644 --- a/lib/widgets.php +++ b/lib/widgets.php @@ -174,6 +174,7 @@ function gutenberg_get_legacy_widget_settings() { null, 'isReferenceWidget' => false, 'isHidden' => in_array( $class, $widgets_to_exclude_from_legacy_widget_block, true ), + 'blockName' => 'core/legacy-widget', ); } } @@ -195,6 +196,7 @@ function gutenberg_get_legacy_widget_settings() { 'name' => html_entity_decode( $widget_obj['name'] ), 'description' => html_entity_decode( wp_widget_description( $widget_id ) ), 'isReferenceWidget' => true, + 'blockName' => 'core/legacy-widget-' . preg_replace( '#[^a-zA-Z0-9-]#', '-', $widget_id ), ); } } @@ -288,4 +290,3 @@ function change_post_template_to_widget_preview( $template ) { return $template; } add_filter( 'template_include', 'change_post_template_to_widget_preview' ); - diff --git a/packages/edit-widgets/src/blocks/legacy-widget/edit/index.js b/packages/edit-widgets/src/blocks/legacy-widget/edit/index.js index 276fe713e04314..5f4fa259533a58 100644 --- a/packages/edit-widgets/src/blocks/legacy-widget/edit/index.js +++ b/packages/edit-widgets/src/blocks/legacy-widget/edit/index.js @@ -6,10 +6,11 @@ import { get, omit } from 'lodash'; /** * WordPress dependencies */ +import { createBlock } from '@wordpress/blocks'; import { useState } from '@wordpress/element'; import { Button, PanelBody, ToolbarGroup } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { withSelect } from '@wordpress/data'; +import { useDispatch, withSelect } from '@wordpress/data'; import { BlockControls, InspectorControls } from '@wordpress/block-editor'; import { update } from '@wordpress/icons'; @@ -23,6 +24,7 @@ import WidgetPreview from './widget-preview'; function LegacyWidgetEdit( { attributes, availableLegacyWidgets, + clientId, hasPermissionsToManageWidgets, prerenderedEditForm, setAttributes, @@ -33,6 +35,7 @@ function LegacyWidgetEdit( { const [ hasEditForm, setHasEditForm ] = useState( true ); const [ isPreview, setIsPreview ] = useState( false ); const shouldHidePreview = ! isPreview && hasEditForm; + const { replaceBlocks } = useDispatch( 'core/block-editor' ); function changeWidget() { switchToEdit(); @@ -59,26 +62,8 @@ function LegacyWidgetEdit( { availableLegacyWidgets={ availableLegacyWidgets } hasPermissionsToManageWidgets={ hasPermissionsToManageWidgets } onChangeWidget={ ( newWidget ) => { - const { - isReferenceWidget, - id_base: idBase, - } = availableLegacyWidgets[ newWidget ]; - - if ( isReferenceWidget ) { - setAttributes( { - instance: {}, - idBase, - referenceWidgetName: newWidget, - widgetClass: undefined, - } ); - } else { - setAttributes( { - instance: {}, - idBase, - referenceWidgetName: undefined, - widgetClass: newWidget, - } ); - } + const { blockName } = availableLegacyWidgets[ newWidget ]; + replaceBlocks( clientId, createBlock( blockName, {} ) ); } } /> ); diff --git a/packages/edit-widgets/src/blocks/legacy-widget/edit/placeholder.js b/packages/edit-widgets/src/blocks/legacy-widget/edit/placeholder.js index 2fe3f1ed1b9c65..c08bf0338c7487 100644 --- a/packages/edit-widgets/src/blocks/legacy-widget/edit/placeholder.js +++ b/packages/edit-widgets/src/blocks/legacy-widget/edit/placeholder.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { pickBy, isEmpty, map } from 'lodash'; +import { isEmpty, map, some } from 'lodash'; /** * WordPress dependencies @@ -11,6 +11,7 @@ import { __ } from '@wordpress/i18n'; import { SelectControl, Placeholder } from '@wordpress/components'; import { BlockIcon } from '@wordpress/block-editor'; import { brush } from '@wordpress/icons'; +import { useSelect } from '@wordpress/data'; export default function LegacyWidgetPlaceholder( { availableLegacyWidgets, @@ -18,10 +19,36 @@ export default function LegacyWidgetPlaceholder( { hasPermissionsToManageWidgets, onChangeWidget, } ) { - const visibleLegacyWidgets = useMemo( - () => pickBy( availableLegacyWidgets, ( { isHidden } ) => ! isHidden ), - [ availableLegacyWidgets ] + const blocksByClientId = useSelect( ( select ) => + select( 'core/block-editor' ).getBlocksByClientId( + select( 'core/block-editor' ).getClientIdsWithDescendants() + ) ); + + const visibleLegacyWidgets = useMemo( () => { + const visible = {}; + for ( const widgetName in availableLegacyWidgets ) { + const { + isReferenceWidget, + blockName, + isHidden, + } = availableLegacyWidgets[ widgetName ]; + if ( isHidden ) { + continue; + } + if ( isReferenceWidget ) { + const blockExists = some( blocksByClientId, { + name: blockName, + } ); + if ( blockExists ) { + continue; + } + } + visible[ widgetName ] = availableLegacyWidgets[ widgetName ]; + } + return visible; + }, [ availableLegacyWidgets, blocksByClientId ] ); + let placeholderContent; if ( ! hasPermissionsToManageWidgets ) { placeholderContent = __( diff --git a/packages/edit-widgets/src/blocks/legacy-widget/index.js b/packages/edit-widgets/src/blocks/legacy-widget/index.js index bf9ed2abe45a94..4826e6768c4007 100644 --- a/packages/edit-widgets/src/blocks/legacy-widget/index.js +++ b/packages/edit-widgets/src/blocks/legacy-widget/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { widget as icon } from '@wordpress/icons'; -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -23,6 +23,12 @@ export const settings = { transforms, }; +const blockBasis = { + metadata, + name, + settings, +}; + /** * Special factory function created specifically for the legacy-widget block. For every other block, JS module exports * are used for registration. In case of this special block, the return value of the create function is used instead. @@ -34,49 +40,74 @@ export const settings = { * @return {Object} Block object. */ export const create = ( editorSettings ) => { - const legacyWidgets = editorSettings?.availableLegacyWidgets ?? {}; + const legacyWidgets = Object.entries( + editorSettings.availableLegacyWidgets + ).filter( ( [ , widget ] ) => ! widget.isHidden ); + + return [ + { + ...blockBasis, + settings: { + ...blockBasis.settings, + variations: legacyWidgets + .filter( ( [ , widget ] ) => ! widget.isReferenceWidget ) + .map( ( [ className, widget ] ) => + legacyWidgetToBlockVariation( className, widget ) + ), + }, + }, + ...legacyWidgets + .filter( ( [ , widget ] ) => widget.isReferenceWidget ) + .map( ( [ className, widget ] ) => + referenceLegacyWidgetsToBlockType( className, widget ) + ), + ]; +}; + +function referenceLegacyWidgetsToBlockType( className, widget ) { + const attrs = blockBasis.metadata.attributes; return { - metadata, - name, + ...blockBasis, + name: widget.blockName, + metadata: { + ...blockBasis.metadata, + name: widget.blockName, + supports: { + ...blockBasis.metadata.supports, + multiple: false, + }, + attributes: { + ...attrs, + referenceWidgetName: { + ...attrs.referenceWidgetName, + default: className, + }, + instance: { + ...attrs.instance, + default: {}, + }, + }, + }, settings: { - ...settings, - variations: legacyWidgetsToBlockVariations( legacyWidgets ), + ...blockBasis.settings, + title: widget.name, + // translators: %s: widget label e.g: "Marquee". + description: sprintf( __( 'Displays a %s widget' ), widget.name ), }, }; -}; - -function legacyWidgetsToBlockVariations( availableLegacyWidgets ) { - const variations = []; - for ( const className in availableLegacyWidgets ) { - const widget = availableLegacyWidgets[ className ]; - if ( widget.isHidden ) { - continue; - } - variations.push( legacyWidgetToBlockVariation( className, widget ) ); - } - return variations; } function legacyWidgetToBlockVariation( className, widget ) { - const blockVariation = { - attributes: {}, + return { + attributes: { + idBase: widget.id_base, + widgetClass: className, + instance: {}, + }, category: 'widgets', description: widget.description, icon: settings.icon, name: className, title: widget.name, }; - if ( widget.isReferenceWidget ) { - blockVariation.attributes = { - referenceWidgetName: className, - instance: {}, - }; - } else { - blockVariation.attributes = { - idBase: widget.id_base, - widgetClass: className, - instance: {}, - }; - } - return blockVariation; } diff --git a/packages/edit-widgets/src/blocks/legacy-widget/index.php b/packages/edit-widgets/src/blocks/legacy-widget/index.php index 7f209f3f4fd4b2..ada6146a212cb5 100644 --- a/packages/edit-widgets/src/blocks/legacy-widget/index.php +++ b/packages/edit-widgets/src/blocks/legacy-widget/index.php @@ -9,12 +9,22 @@ * Register legacy widget block. */ function register_block_core_legacy_widget() { - register_block_type_from_metadata( + $block_type = register_block_type_from_metadata( __DIR__ . '/legacy-widget', array( 'render_callback' => 'render_block_core_legacy_widget', ) ); + $settings = gutenberg_get_legacy_widget_settings(); + $legacy_widgets = $settings['availableLegacyWidgets']; + foreach ( $legacy_widgets as $widget_id => $legacy_widget ) { + if ( ! $legacy_widget['isReferenceWidget'] ) { + continue; + } + $legacy_block = clone $block_type; + $legacy_block->name = $legacy_widget['blockName']; + WP_Block_Type_Registry::get_instance()->register( $legacy_block ); + } } /** diff --git a/packages/edit-widgets/src/index.js b/packages/edit-widgets/src/index.js index b4a958d0fb104e..96112f763d0afd 100644 --- a/packages/edit-widgets/src/index.js +++ b/packages/edit-widgets/src/index.js @@ -17,7 +17,7 @@ import { */ import './store'; import './hooks'; -import { create as createLegacyWidget } from './blocks/legacy-widget'; +import { create as createLegacyWidgetBlocks } from './blocks/legacy-widget'; import * as widgetArea from './blocks/widget-area'; import EditWidgetsInitializer from './components/edit-widgets-initializer'; @@ -31,7 +31,8 @@ export function initialize( id, settings ) { registerCoreBlocks(); if ( process.env.GUTENBERG_PHASE === 2 ) { __experimentalRegisterExperimentalCoreBlocks( settings ); - registerBlock( createLegacyWidget( settings ) ); + const blocks = createLegacyWidgetBlocks( settings ); + blocks.forEach( registerBlock ); registerBlock( widgetArea ); } render(