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

Block Directory: Provide documented way to disable #23961

Closed
sirreal opened this issue Jul 15, 2020 · 28 comments · Fixed by #24357
Closed

Block Directory: Provide documented way to disable #23961

sirreal opened this issue Jul 15, 2020 · 28 comments · Fixed by #24357
Labels
[Feature] Block Directory Related to the Block Directory, a repository of block plugins [Type] Developer Documentation Documentation for developers [Type] Enhancement A suggestion for improvement.

Comments

@sirreal
Copy link
Member

sirreal commented Jul 15, 2020

There's no clear way of disabling the Block Directory. I expect sites will want to control whether the Block Directory is available, and to be disable it if desired. I would like to disable it on some of my sites.

I propose that the Block Directory provide a way for it to be disabled entirely in code. A filter or constant are likely a good fit.

Alternatives

It's possible to prevent the Block Directory assets from being enqueued:

function disable_block_directory() {
	remove_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets_block_directory' );
}
add_action( 'plugins_loaded', 'disable_block_directory' );

UPDATE: The following details are only accurate under certain circumstances. See #23961 (comment) for details.

However, this is not a documented way of disabling the feature has unintended consequences. In this case, the "no blocks found" message is removed:

With Block Directory Without
Screen Shot 2020-07-15 at 16 04 41 Screen Shot 2020-07-15 at 16 04 13
More implementation details…

It's difficult to restore the "no blocks found" functionality because an experimental API __experimentalInserterMenuExtension handles it:

<__experimentalInserterMenuExtension>
{ ( { onSelect, onHover, filterValue, hasItems } ) => {
if ( hasItems || ! filterValue ) {
return null;
}
if ( debouncedFilterValue !== filterValue ) {
debouncedSetFilterValue( filterValue );
}
return (
<DownloadableBlocksPanel
onSelect={ onSelect }
onHover={ onHover }
filterValue={ debouncedFilterValue }
isWaiting={ filterValue !== debouncedFilterValue }
/>
);
} }
</__experimentalInserterMenuExtension>

@sirreal sirreal added [Type] Enhancement A suggestion for improvement. [Feature] Block Directory Related to the Block Directory, a repository of block plugins labels Jul 15, 2020
@sirreal
Copy link
Member Author

sirreal commented Jul 16, 2020

I worked up a solution that may help inform the necessary changes. Note that this depends on __experimentalInserterMenuExtension (like the Block Directory itself) so isn't suitable for widespread use.

  1. Remove the enqueue action for the Block Directory (as mentioned in the description):
function block_directory_empty_results() {
	wp_enqueue_script( /* Enqueue the JavaScript below… */ );
}
function disable_block_directory() {
	remove_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets_block_directory' );
	add_action( 'enqueue_block_editor_assets', 'block_directory_empty_results' );
}
add_action( 'plugins_loaded', 'disable_block_directory' );
  1. Add this script which is an extraction of the minimum necessary bit of Block Directory to render empty results:
var wp = window.wp;
var __ = wp.i18n.__
var registerPlugin = wp.plugins.registerPlugin
var __experimentalInserterMenuExtension = wp.blockEditor.__experimentalInserterMenuExtension
var createElement = wp.element.createElement;

// Check if the experimental slot is available before registering the plugin.
if ( typeof __experimentalInserterMenuExtension !== 'undefined' ) {
	registerPlugin( 'disable-block-registry', {
		render: function() {
			return createElement( __experimentalInserterMenuExtension, {},
				function( props ) {
					var hasItems = props.hasItems;
					var filterValue = props.filterValue;
					if ( hasItems || ! filterValue ) {
						return null;
					}
					return (
						createElement('div', {},
							createElement(
								'p',
								{ style: {
										    padding: 0,
										    margin: '112px 0',
										    textAlign: 'center',
										    color: '#606a73',
								} },
								/* translators: Displayed when block search returns no results. */
								__( 'No blocks found in your library.' )
							)
						)
					);
				}
			);
		}
	} );
}

Inspiration:

<__experimentalInserterMenuExtension>
{ ( { onSelect, onHover, filterValue, hasItems } ) => {
if ( hasItems || ! filterValue ) {
return null;
}
if ( debouncedFilterValue !== filterValue ) {
debouncedSetFilterValue( filterValue );
}
return (
<DownloadableBlocksPanel
onSelect={ onSelect }
onHover={ onHover }
filterValue={ debouncedFilterValue }
isWaiting={ filterValue !== debouncedFilterValue }
/>
);
} }
</__experimentalInserterMenuExtension>

<p className="block-directory-downloadable-blocks-panel__description has-no-results">
{ __( 'No blocks found in your library.' ) }
</p>

@sirreal
Copy link
Member Author

sirreal commented Jul 16, 2020

The information I've provided so far is not entirely correct. It turns out that other functionality in my case was also using __experimentalInserterMenuExtension. If anything goes into that slot, the default "no results" behavior is not shown. If I disable the block directory and nothing else is rendered into the slot, this is what I see:

Screen Shot 2020-07-16 at 17 41 19

This makes for an interesting question around __experimentalInserterMenuExtension - as a slot, multiple things can be rendered there and may cause the results reporting to either be omitted or duplicated.

I'm not sure if there's a great way to improve this API, it's an advanced feature and exposes some functionality that it's clearly fragile if not used carefully. Thanks to @mcsf for feedback and help debugging.

@sirreal
Copy link
Member Author

sirreal commented Jul 17, 2020

👋 @StevenDufresne — this issue may be relevant for you.

@youknowriad
Copy link
Contributor

youknowriad commented Jul 17, 2020

the block directory is written as an extension so I think the unregistering is a good way to disable it.

But I feel if there's no fill registered for the slot, the "No blocks" found should definitely appear, and I'd consider this as a bug.

@sirreal
Copy link
Member Author

sirreal commented Jul 17, 2020

… if there's no fill registered for the slot, the "No blocks" found should definitely appear, and I'd consider this as a bug.

If the Block Directory is enabled, it handles the empty results case and the default is not show. The problem I encountered was when the Block Directory was disabled but the slot wasn't empty. With a slot, there can be 0, 1, or multiple things in the slot. 0 seems to work as expected. However, when multiple things can go into the slot, it's unclear how they should coordinate to handle results messaging.

@ryelle
Copy link
Contributor

ryelle commented Jul 17, 2020

In fixing the missing style issue, I added a similar hook to core, so this should be all that's needed to disable the block directory:

add_action(
	'plugins_loaded',
	function() {
		remove_action( 'enqueue_block_editor_assets', 'wp_enqueue_block_editor_assets_block_directory' );
		remove_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets_block_directory' );
	}
);

The issue of the "no results" message still stands though.

@StevenDufresne
Copy link
Contributor

StevenDufresne commented Jul 20, 2020

I think for @sirreal's problem, the hook seems reasonable.

I think we may also want a no code approach as well. Maybe a checkbox in the Block Manager or an option in the Options menu?

Options

@ryelle
Copy link
Contributor

ryelle commented Jul 20, 2020

I don't think we need a UI solution, most people will be fine with having the Block Directory enabled (or using the hook). Maybe it's something to revisit, but if enough people want to disable the Block Directory that we want UI for it, we've probably done something wrong 😅

@mcsf
Copy link
Contributor

mcsf commented Jul 20, 2020

My own take:

  • Preventing registration using remove_action, as suggested in previous comments, seems totally adequate.
  • I would also avoid a UI solution. There will always be micro-plugins for people who want to explicitly disable the Directory, as has always been the case in WordPress.
  • Not a strong opinion, but I think that __experimentalInserterMenuExtension is a fairly specific / advanced API, so it's a bit "use at your own risk". I don't think it's necessarily wrong to delegate the responsibility to show the "No results found" view if a site has custom pieces tapping into the interface. But I'm open to improvements.

@sirreal
Copy link
Member Author

sirreal commented Jul 20, 2020

  • Preventing registration using remove_action, as suggested in previous comments, seems totally adequate.
  • I would also avoid a UI solution. There will always be micro-plugins for people who want to explicitly disable the Directory, as has always been the case in WordPress.

I agree with these two points (this does not imply disagreement with the third point). I would add:

  • I'd like to see the remove_action approach documented and therefore officially supported in some way.
  • This implies a degree of stability. The block editor should continue to without any negative side effects. Any issues with the block editor when using this approach would be considered regressions.

@mcsf
Copy link
Contributor

mcsf commented Jul 20, 2020

This implies a degree of stability. The block editor should continue to without any negative side effects. Any issues with the block editor when using this approach would be considered regressions.

This is fair. It should be fairly easy to add an E2E test with an accompanying WP plugin. The plugin would disable the Block Directory. The test would assert the bare minimum: that the editor loads with no errors, that searching in the Inserter for a known core block returns said block, and that searching for something else yields the No blocks found message.

@StevenDufresne
Copy link
Contributor

I don't think we need a UI solution, most people will be fine with having the Block Directory enabled (or using the hook). Maybe it's something to revisit, but if enough people want to disable the Block Directory that we want UI for it, we've probably done something wrong 😅

I would also avoid a UI solution. There will always be micro-plugins for people who want to explicitly disable the Directory, as has always been the case in WordPress.

Fair enough. With that being said, I wonder how the other options made it in?

@uamv
Copy link

uamv commented Jul 30, 2020

so this should be all that's needed to disable the block directory

Should this still work to disable the block directory? I've attempted both via theme and plugin and can't get it to change the behaviour when searching blocks with WP5.5-RC1-48681.

@ryelle
Copy link
Contributor

ryelle commented Jul 30, 2020

The function name was changed before merging, so the actual code you should use is this:

add_action(
	'plugins_loaded',
	function() {
		remove_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' );
		remove_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets_block_directory' );
	}
);

@StevenDufresne
Copy link
Contributor

@sirreal Anything left to do here?

@sirreal
Copy link
Member Author

sirreal commented Aug 3, 2020

We seem to have settled on an accepted approach for disabling the Block Directory. Has it been officially documented somehow? That still seems important.

@sirreal sirreal added the [Type] Developer Documentation Documentation for developers label Aug 3, 2020
@mcsf
Copy link
Contributor

mcsf commented Aug 3, 2020

Documentation is definitely welcome!

@gpsugy
Copy link

gpsugy commented Sep 7, 2020

Is anyone able to confirm this still works in WP 5.5.1? Using the code snippet that @ryelle posted does not disable the Block Directory for me. All the of the blocks are still present.

On another related note, is there a way to disable specific blocks from the Block Directory as there is with disabling Gutenberg blocks from the editor using add_filter('allowed_block_types')?

@sirreal
Copy link
Member Author

sirreal commented Sep 7, 2020

@gpsugy are you using the recommended approach in the handbook? That does seem to work.

add_action(
    'plugins_loaded',
    function() {
        remove_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' );
        remove_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets_block_directory' );
    }
);

@gpsugy
Copy link

gpsugy commented Sep 7, 2020

@sirreal This is actually the same snippet of code I was referencing, and it is not working for me. For a second I thought it was working, but that was only because I tried opening the Block Directory in a custom post type (which led to a new discovery that the Block Directory does not work with custom post types by default).

My setup PHP file involves usage of add_action(enqueue_block_editor_assets) to register theme assets with the block editor. Perhaps the snippet of code you posted does not work compatibly with that?

@uamv
Copy link

uamv commented Sep 7, 2020

My setup PHP file involves usage of add_action(enqueue_block_editor_assets) to register theme assets with the block editor. Perhaps the snippet of code you posted does not work compatibly with that?

Not sure if this might be your issue, but as I previously noted here, this code won't work within themes since theme setup happens after the plugins_loaded hook has fired. You'll want to instead hook into admin_init.

@gpsugy
Copy link

gpsugy commented Sep 8, 2020

@uamv I am indeed utilizing a theme; thank you for that helpful reply, and it is likely the reason for my issue. Having trouble with getting that to work, however. Hooking into admin_it still requires usage of add_action, correct? If so, there seems to be an order of when this snippet of code is supposed to run in relation to other hooks that I am unaware of. Could you please specify?

@TimothyBJacobs
Copy link
Member

In a theme, you should be able to just add the remove_action calls directly, without putting it in a hook.

remove_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' );
remove_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets_block_directory' );

@uamv
Copy link

uamv commented Sep 8, 2020

Yep. Directly removing should work. And, to clarify, if you did want to have it hooked, admin_init should work – I see you mention admin_it above, which wouldn't fire anything.

@gpsugy
Copy link

gpsugy commented Sep 9, 2020

Ah, my apologies. I actually meant admin_init, but misspelled it as admin_it. This is very strange... I inserted the following code snippet

remove_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' );
remove_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets_block_directory' );

in the hook, add_action('init'), along with after that hook further down in my setup PHP file - yet no success. I have also tried the following, which did not work for me:

add_action(
    'admin_init',
    function() {
        remove_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' );
        remove_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets_block_directory' );
    }
);

(I have also tried replacing admin_init with plugins_loaded, which was also unsuccessful.)

I am using a Sage Roots framework, if that perhaps sheds any light as to why this is not working for me. After all of this, clicking "Browse All" in the gutenberg editor still opens up the left sidebar Block Directory.

Is there a way to specifically disable specific blocks from the Block Directory? That should suffice as an alternative (and better) solution.

@TimothyBJacobs
Copy link
Member

@gpsugy I think there might be some confusion here about what the Block Directory is. The left sidebar is the block inserter. The block directory is a part of the block inserter that is used to display suggestions for blocks to install from WordPress.org.

As far as I know, there is no way to completely disable the block inserter.

If you want to hide specific blocks, you can use the allowed_block_types filter that is documented here.

@gpsugy
Copy link

gpsugy commented Sep 11, 2020

@TimothyBJacobs, thank you for the clarification. What I was thinking to be the Block Directory was indeed the Block Inserter. Referencing the allowed_block_types filter is also greatly appreciated. Thank you to everyone who helped in resolving my questions!

@tomjn
Copy link
Contributor

tomjn commented Mar 31, 2021

Noting that removing the actions isn't the only method, you can do this by unregistering the block-directory plugin in javascript. This PHP snippet will add the inline JS to do this when the block editor is enqueued:

function tomjn_remove_block_directory() {
	wp_add_inline_script(
		'wp-block-editor',
		"wp.domReady( () => wp.plugins.unregisterPlugin( 'block-directory' ) )"
	);
}
add_action( 'admin_enqueue_scripts', 'tomjn_remove_block_directory' );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block Directory Related to the Block Directory, a repository of block plugins [Type] Developer Documentation Documentation for developers [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants