Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Register each reference widget as a separate block #25741

Closed

Conversation

adamziel
Copy link
Contributor

@adamziel adamziel commented Sep 30, 2020

Description

Solves #25494

Before this PR, reference widgets were registered as variations of the legacy-widget block. Unfortunately, the requirements for handling reference widgets are very different from regular widgets. One such example is that there should never be more than one reference widget present. This feature is already supported at the block level via supports.multiple = false. Unfortunately, it's not possible to use that setting for specific variations.

This PR attempts to solve the problem by registering each reference widget as a separate block. It is a highly unusual pattern as each block usually comes with it's own block.json and a set of components. That being said, widgets are dynamic in nature, so relying on anything generated during the transpilation wouldn't work.

Let's discuss this approach. Are there any downsides? Are there any better ways of achieving the same result?

Side note: If this PR were to be merged, we should add a lot of inline comments to explain what's happening. As I wasn't sure if it's a viable approach, I didn't include any documentation in this initial attempt.

How has this been tested?

  1. Add a reference widget to your WordPress, for example marquee: https://gist.github.com/adamziel/526436b4cc9bc82a7221c77e00137ae1
  2. Go to the widgets editor, confirm Marquee is available in the block inserter.
  3. Insert the Legacy Widget block, confirm Marquee is on the list of available blocks.
  4. Choose Marquee, confirm it worked.
  5. Confirm Marquee is greyed out in the block inserter.
  6. Add another Legacy Widget, confirm you are not able to add another Marquee.
  7. Remove the Marquee, insert another one using block inserter, confirm you're unable to insert yet another one.

Types of changes

Bug fix

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • [] I've updated all React Native files affected by any refactorings/renamings in this PR.

@github-actions
Copy link

Size Change: +182 B (0%)

Total Size: 1.18 MB

Filename Size Change
build/edit-widgets/index.js 21.3 kB +182 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/annotations/index.js 3.52 kB 0 B
build/api-fetch/index.js 3.35 kB 0 B
build/autop/index.js 2.72 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/index.js 8.61 kB 0 B
build/block-directory/style-rtl.css 943 B 0 B
build/block-directory/style.css 942 B 0 B
build/block-editor/index.js 129 kB 0 B
build/block-editor/style-rtl.css 11 kB 0 B
build/block-editor/style.css 11 kB 0 B
build/block-library/editor-rtl.css 8.6 kB 0 B
build/block-library/editor.css 8.6 kB 0 B
build/block-library/index.js 135 kB 0 B
build/block-library/style-rtl.css 7.65 kB 0 B
build/block-library/style.css 7.65 kB 0 B
build/block-library/theme-rtl.css 741 B 0 B
build/block-library/theme.css 741 B 0 B
build/block-serialization-default-parser/index.js 1.78 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/blocks/index.js 47.5 kB 0 B
build/components/index.js 169 kB 0 B
build/components/style-rtl.css 15.4 kB 0 B
build/components/style.css 15.4 kB 0 B
build/compose/index.js 9.42 kB 0 B
build/core-data/index.js 12 kB 0 B
build/data-controls/index.js 1.27 kB 0 B
build/data/index.js 8.41 kB 0 B
build/date/index.js 31.9 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 568 B 0 B
build/dom/index.js 4.42 kB 0 B
build/edit-navigation/index.js 10.7 kB 0 B
build/edit-navigation/style-rtl.css 868 B 0 B
build/edit-navigation/style.css 871 B 0 B
build/edit-post/index.js 306 kB 0 B
build/edit-post/style-rtl.css 6.25 kB 0 B
build/edit-post/style.css 6.24 kB 0 B
build/edit-site/index.js 20.4 kB 0 B
build/edit-site/style-rtl.css 3.78 kB 0 B
build/edit-site/style.css 3.78 kB 0 B
build/edit-widgets/style-rtl.css 3 kB 0 B
build/edit-widgets/style.css 3 kB 0 B
build/editor/editor-styles-rtl.css 492 B 0 B
build/editor/editor-styles.css 493 B 0 B
build/editor/index.js 45.4 kB 0 B
build/editor/style-rtl.css 3.83 kB 0 B
build/editor/style.css 3.82 kB 0 B
build/element/index.js 4.44 kB 0 B
build/escape-html/index.js 733 B 0 B
build/format-library/index.js 7.49 kB 0 B
build/format-library/style-rtl.css 547 B 0 B
build/format-library/style.css 548 B 0 B
build/hooks/index.js 1.74 kB 0 B
build/html-entities/index.js 621 B 0 B
build/i18n/index.js 3.54 kB 0 B
build/is-shallow-equal/index.js 709 B 0 B
build/keyboard-shortcuts/index.js 2.39 kB 0 B
build/keycodes/index.js 1.85 kB 0 B
build/list-reusable-blocks/index.js 3.02 kB 0 B
build/list-reusable-blocks/style-rtl.css 476 B 0 B
build/list-reusable-blocks/style.css 476 B 0 B
build/media-utils/index.js 5.12 kB 0 B
build/notices/index.js 1.69 kB 0 B
build/nux/index.js 3.27 kB 0 B
build/nux/style-rtl.css 671 B 0 B
build/nux/style.css 668 B 0 B
build/plugins/index.js 2.44 kB 0 B
build/primitives/index.js 1.34 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.85 kB 0 B
build/rich-text/index.js 13 kB 0 B
build/server-side-render/index.js 2.6 kB 0 B
build/shortcode/index.js 1.69 kB 0 B
build/token-list/index.js 1.24 kB 0 B
build/url/index.js 4.06 kB 0 B
build/viewport/index.js 1.74 kB 0 B
build/warning/index.js 1.13 kB 0 B
build/wordcount/index.js 1.17 kB 0 B

compressed-size-action

@noisysocks
Copy link
Member

Clever!

To me, dynamically registering a bunch of blocks doesn't feel any more wrong than dynamically registering a bunch of block variations. The Legacy Widget block is an atypical "block": it's highly coupled to WP Admin and changes depending on what plugins and themes you have activated.

What do you think about removing variations altogether and registering one block per widget, regardless of whether it's a callback widget or a class 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 ),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we've ever done this but I wonder if we should use sub-namespaces here? In other words, the name would be core/legacy-widget/marquee.

continue;
}
if ( isReferenceWidget ) {
const blockExists = some( blocksByClientId, {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's probably a nicer way to do this using canInsertBlock or some such.

...blockBasis,
settings: {
...blockBasis.settings,
variations: legacyWidgets
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we go all in with the block per widget approach so that there's only one type of block to test and debug?

@@ -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(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does using block metadata give us anything at this point? Should we do away with registering the block using metadata altogether and use register_block_type? No need, I think, to pretend that this is a normal block with normal block conventions 🙂

if ( ! $legacy_widget['isReferenceWidget'] ) {
continue;
}
$legacy_block = clone $block_type;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I'd find array_merge easier to understand than cloning and mutating objects.

@noisysocks
Copy link
Member

What do you think about removing variations altogether and registering one block per widget, regardless of whether it's a callback widget or a class widget?

Doing this would let us implement the sidebar design described in #24870 (comment).

@kevin940726
Copy link
Member

How does this fix #25699? Should it be #25494 instead?

Comment on lines +70 to +90
...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: {},
},
},
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's time we bring immer into our toolchains 😅

Or before that happens, could we just deepClone the object and mutate it here?

@adamziel
Copy link
Contributor Author

adamziel commented Oct 5, 2020

I'll abstain from addressing the feedback here until we get consensus about the way forward on #25494.

@adamziel adamziel closed this Oct 20, 2020
@aristath aristath deleted the update/reference-widgets-as-separate-block-types branch November 10, 2020 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Widgets Screen The block-based screen that replaced widgets.php. [Package] Edit Widgets /packages/edit-widgets
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants