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

First stab at sidebars_widgets-based widget management #24290

Merged
merged 41 commits into from
Aug 13, 2020

Conversation

adamziel
Copy link
Contributor

@adamziel adamziel commented Jul 30, 2020

Description

This is an attempt at making the experimental widget management screen fully functional so that it's possible to mix&match legacy widgets and gutenberg blocks.

It works as follows:

  • wp_options are embraced, posts-based manipulations are removed (see Experimental widgets editor - API and data model #24267).
  • Blocks are just regular widgets implemented using the WP_Widget_Block class.
  • Frontend is based on the data layer where we use widgetArea as the entity. It has a corresponding API endpoint which returns a widget area with all its widgets and it also makes it possible to POST a widget area with a set of desired widgets.
  • Legacy widgets on the new screen are no longer saved on change, in fact they're not saved at all until a "Save" button is clicked.

Other considerations:

  • Consider making widget a base entity instead of widget area - batch saving is a pre-requisite for this approach though, also it would require some discussion about how reordering widgets would work.
  • The endpoint says /sidebars but the entity name is widgetArea - it would be good to address this discrepancy somehow.
  • Customizer will only display rendered blocks instead of an actual Gutenberg instance - let's discuss.
  • /widget-utils controller is still there and would be a good candidate for removal in some future iteration.
  • Overall this PR adds a bunch of code behind a feature flag, merging it and then iterating on bugfixes would make a sensible approach.

Reuses parts of the following plugin (CC @martin-pettersson) https://github.com/martin-pettersson/wp-rest-api-sidebars

How has this been tested?

Screenshots

Types of changes

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.

@adamziel adamziel self-assigned this Jul 30, 2020
@adamziel adamziel added [Block] Legacy Widget Affects the Legacy Widget Block - used for displaying Classic Widgets [Feature] Widgets Screen The block-based screen that replaced widgets.php. [Package] Edit Widgets /packages/edit-widgets labels Jul 30, 2020
@github-actions
Copy link

github-actions bot commented Jul 30, 2020

Size Change: +1.89 kB (0%)

Total Size: 1.16 MB

Filename Size Change
build/block-directory/index.js 7.96 kB -1 B
build/block-editor/index.js 125 kB +72 B (0%)
build/block-editor/style-rtl.css 10.6 kB -180 B (1%)
build/block-editor/style.css 10.6 kB -178 B (1%)
build/block-library/index.js 132 kB -176 B (0%)
build/block-library/style.css 7.77 kB +1 B
build/block-library/theme-rtl.css 729 B +1 B
build/block-library/theme.css 730 B +1 B
build/blocks/index.js 48.2 kB -19 B (0%)
build/components/index.js 200 kB -5 B (0%)
build/core-data/index.js 11.8 kB -5 B (0%)
build/data/index.js 8.45 kB -2 B (0%)
build/edit-navigation/index.js 10.9 kB +1 B
build/edit-post/index.js 304 kB -1 B
build/edit-post/style-rtl.css 5.59 kB -17 B (0%)
build/edit-post/style.css 5.59 kB -17 B (0%)
build/edit-site/index.js 17 kB +10 B (0%)
build/edit-widgets/index.js 11.7 kB +2.36 kB (20%) 🚨
build/editor/index.js 45.3 kB +42 B (0%)
build/format-library/index.js 7.71 kB -3 B (0%)
build/list-reusable-blocks/index.js 3.12 kB +1 B
build/media-utils/index.js 5.33 kB +2 B (0%)
build/rich-text/index.js 13.9 kB +1 B
build/token-list/index.js 1.27 kB +2 B (0%)
build/url/index.js 4.06 kB +1 B
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/annotations/index.js 3.67 kB 0 B
build/api-fetch/index.js 3.44 kB 0 B
build/autop/index.js 2.82 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/style-rtl.css 953 B 0 B
build/block-directory/style.css 952 B 0 B
build/block-library/editor-rtl.css 7.59 kB 0 B
build/block-library/editor.css 7.59 kB 0 B
build/block-library/style-rtl.css 7.76 kB 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/components/style-rtl.css 15.7 kB 0 B
build/components/style.css 15.7 kB 0 B
build/compose/index.js 9.68 kB 0 B
build/data-controls/index.js 1.29 kB 0 B
build/date/index.js 5.38 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 568 B 0 B
build/dom/index.js 3.23 kB 0 B
build/edit-navigation/style-rtl.css 1.08 kB 0 B
build/edit-navigation/style.css 1.08 kB 0 B
build/edit-site/style-rtl.css 3.06 kB 0 B
build/edit-site/style.css 3.06 kB 0 B
build/edit-widgets/style-rtl.css 2.45 kB 0 B
build/edit-widgets/style.css 2.45 kB 0 B
build/editor/editor-styles-rtl.css 537 B 0 B
build/editor/editor-styles.css 539 B 0 B
build/editor/style-rtl.css 3.8 kB 0 B
build/editor/style.css 3.79 kB 0 B
build/element/index.js 4.65 kB 0 B
build/escape-html/index.js 733 B 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 2.13 kB 0 B
build/html-entities/index.js 621 B 0 B
build/i18n/index.js 3.56 kB 0 B
build/is-shallow-equal/index.js 711 B 0 B
build/keyboard-shortcuts/index.js 2.52 kB 0 B
build/keycodes/index.js 1.94 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/notices/index.js 1.79 kB 0 B
build/nux/index.js 3.4 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.56 kB 0 B
build/primitives/index.js 1.41 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.85 kB 0 B
build/server-side-render/index.js 2.71 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/viewport/index.js 1.85 kB 0 B
build/warning/index.js 1.14 kB 0 B
build/wordcount/index.js 1.17 kB 0 B

compressed-size-action

@noisysocks
Copy link
Member

Looks promising. It's amazing just how similar this ends up being to how the Navigation screen works.

wp-rest-api-sidebars is a nice find! I think let's copy class-sidebars-controller.php and class-widgets-controller.php into lib. That will make it easier to test this PR and see exactly what code from the plugin we're proposing to add to Core.

Copy link
Member

@TimothyBJacobs TimothyBJacobs left a comment

Choose a reason for hiding this comment

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

Thanks for adding the PHP tests they're looking good! Let's also add coverage for when the user is logged out or has insufficient permissions.

It'd probably also be good to have a test that covers the slashing behavior specifically. Those can get tricky.

@noisysocks
Copy link
Member

Any thoughts on having a new Gutenberg Block widget vs. using the existing HTML widget?

Copy link
Member

@jorgefilipecosta jorgefilipecosta left a comment

Choose a reason for hiding this comment

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

Hi @adamziel thank you for continuing the widgets work, and for all the work on this PR 👍

Generally, it seems the PR in on a good path, I left some initial comments.

I'm having some problems when testing the branch:
I get the following error:

Target container is not a DOM element.
    at http://yah.local/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:25173:28
    at render (http://yah.local/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:25176:7)
    at Module.customizerInitialize (http://yah.local/wp-content/plugins/gutenberg/build/edit-widgets/index.js?ver=2ebbe5d16afdab3466a61f4165697cd3:1914:68)

I got this error even when loading the old screen. But on master, I don't have these errors it seems we are now running customizer specific code on both the old and new widgets screen?

I was able to test with success (excluding the errors referred above) the interoperability between the old and new screens I was able to reorder blocks on the old screen :) Nice work accomplishing this!

@@ -67,22 +64,9 @@ class LegacyWidgetEditDomManager extends Component {
className="form"
ref={ this.formRef }
method="post"
onBlur={ () => {
if ( this.shouldTriggerInstanceUpdate() ) {
if ( isReferenceWidget ) {
Copy link
Member

Choose a reason for hiding this comment

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

The non-class based widgets render their own form and perform their own save sometimes using tables they created. This data is outside the structure we use to control the widgets and I guess we need a specific save for it, it can be automatically or we can have a save button on the legacy widgets block.

const [ blocks, onInput, onChange ] = useEntityBlockEditor(
KIND,
POST_TYPE,
{ id: buildWidgetAreasPostId() }
Copy link
Member

@jorgefilipecosta jorgefilipecosta Aug 11, 2020

Choose a reason for hiding this comment

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

What is the reason that makes us need to have a post id and use useEntityBlockEditor here? Using it inside the widget area block causes some problem?

@@ -137,6 +137,7 @@ function gutenberg_get_legacy_widget_settings() {
foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
$available_legacy_widgets[ $class ] = array(
Copy link
Member

Choose a reason for hiding this comment

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

Right now I'm seeing "Gutenberg block" as an available legacy widget I guess we need to filter it ?

@@ -36,8 +36,8 @@ class="blocks-widgets-container
* @param string $hook Page.
*/
function gutenberg_widgets_init( $hook ) {
if ( 'gutenberg_page_gutenberg-widgets' !== $hook && 'gutenberg_customizer' !== $hook ) {
return;
if ( ! in_array( $hook, array( 'gutenberg_page_gutenberg-widgets', 'gutenberg_customizer', 'widgets.php' ) ) ) {
Copy link
Member

Choose a reason for hiding this comment

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

We don't need to run all of this function in widgets.php, just wp_enqueue_style( 'wp-block-library' );

* @param array $instance Settings for the current Block widget instance.
*/
public function widget( $args, $instance ) {
echo do_blocks( $instance['content'] );
Copy link
Member

Choose a reason for hiding this comment

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

This will sometimes render a <form> (e.g. Search block), which is invalid HTML, because we'll then have a <form> nested within a <form>.

Copy link
Contributor Author

@adamziel adamziel Aug 25, 2020

Choose a reason for hiding this comment

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

@noisysocks I don't see a <form> anywhere in this file:

https://github.com/WordPress/gutenberg/tree/master/packages/block-library/src/search/edit.js

Where I can see a <form> is in the legacy-widget block:

https://github.com/WordPress/gutenberg/blob/master/packages/block-library/src/legacy-widget/edit/dom-manager.js#L63

I don't think that's a problem though - the widget screen is not wrapped in a <form> and so each block is free to render anything it wants. I'm going to mark the related to-do item as complete, feel free to mark it as incomplete if I'm wrong here.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I wasn't clear here. I'm referring to the legacy widgets.php screen. By default every widget is wrapped with a <form>.

https://github.com/WordPress/wordpress-develop/blob/master/src/wp-admin/includes/widgets.php#L205

This means that you can sometimes end up with invalid HTML.

  1. Navigate to Widgets (beta) and add a Search block to one of the block areas.
  2. Navigatie to Widgets (the old screen).
  3. View the page source and search for wp-block-search.

You'll see that there's a <form> inside a <form>. Firefox helpfully highlights the invalid HTML.

Screen Shot 2020-08-26 at 11 05 17

Copy link
Member

@noisysocks noisysocks left a comment

Choose a reason for hiding this comment

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

I think the direction here is solid and that it's the right way to go. There's lots of remaining work, but we will be here forever addressing it in this already very large PR. Since this is all behind a feature flag, let's merge it now and address the feedback in more manageable follow-up PRs.

Thanks @adamziel! Nice work. I think we can get this feature in for WP 5.6 💪

@noisysocks noisysocks merged commit e3d4e49 into master Aug 13, 2020
@noisysocks noisysocks deleted the update/widgets-based-blocks branch August 13, 2020 00:12
@noisysocks
Copy link
Member

I created #24530 which summarises and tracks the necessary follow-up work here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Legacy Widget Affects the Legacy Widget Block - used for displaying Classic Widgets [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.

5 participants