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 Bindings: Allow only admin users to create and modify bindings by default #64570

Merged
merged 15 commits into from
Sep 4, 2024
Merged
3 changes: 3 additions & 0 deletions backport-changelog/6.7/7258.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
https://github.com/WordPress/wordpress-develop/pull/7258

* https://github.com/WordPress/gutenberg/pull/64570
15 changes: 15 additions & 0 deletions lib/compat/wordpress-6.7/block-bindings.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,18 @@ function gutenberg_add_server_block_bindings_sources_to_editor_settings( $editor
}

add_filter( 'block_editor_settings_all', 'gutenberg_add_server_block_bindings_sources_to_editor_settings', 10 );

/**
* Initialize `canUpdateBlockBindings` editor setting if it doesn't exist. By default, it is `true` only for admin users.
*
* @param array $settings The block editor settings from the `block_editor_settings_all` filter.
* @return array The editor settings including `canUpdateBlockBindings`.
*/
function gutenberg_add_can_update_block_bindings_editor_setting( $editor_settings ) {
if ( empty( $editor_settings['canUpdateBlockBindings'] ) ) {
$editor_settings['canUpdateBlockBindings'] = current_user_can( 'manage_options' );
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm noting that a discussion around how these permissions should be set up is happening in the core PR: https://github.com/WordPress/wordpress-develop/pull/7258/files#r1736575839

Copy link
Member

Choose a reason for hiding this comment

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

It should be fine to start with, but we need to sort it out and sync back to Gutenberg when we arrive on the final way for handling it in WP core. Thank you for connecting the dots 👍🏻

return $editor_settings;
}

add_filter( 'block_editor_settings_all', 'gutenberg_add_can_update_block_bindings_editor_setting', 10 );
3 changes: 0 additions & 3 deletions lib/experimental/editor-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ function gutenberg_enable_experiments() {
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-quick-edit-dataviews', $gutenberg_experiments ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalQuickEditDataViews = true', 'before' );
}
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-block-bindings-ui', $gutenberg_experiments ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalBlockBindingsUI = true', 'before' );
}
if ( $gutenberg_experiments && array_key_exists( 'gutenberg-media-processing', $gutenberg_experiments ) ) {
wp_add_inline_script( 'wp-block-editor', 'window.__experimentalMediaProcessing = true', 'before' );
}
Expand Down
12 changes: 0 additions & 12 deletions lib/experiments-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,6 @@ function gutenberg_initialize_experiments_settings() {
)
);

add_settings_field(
'gutenberg-block-bindings-ui',
__( 'UI to create block bindings', 'gutenberg' ),
'gutenberg_display_experiment_field',
'gutenberg-experiments',
'gutenberg_experiments_section',
array(
'label' => __( 'Add UI to create and update block bindings in block inspector controls.', 'gutenberg' ),
'id' => 'gutenberg-block-bindings-ui',
)
);

add_settings_field(
'gutenberg-media-processing',
__( 'Client-side media processing', 'gutenberg' ),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ const BlockInspectorSingleBlock = ( { clientId, blockName } ) => {
/>
<InspectorControls.Slot group="styles" />
<PositionControls />
<InspectorControls.Slot group="bindings" />
<div>
<AdvancedControls />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const SettingsTab = ( { showAdvancedControls = false } ) => (
<>
<InspectorControls.Slot />
<PositionControls />
<InspectorControls.Slot group="bindings" />
{ showAdvancedControls && (
<div>
<AdvancedControls />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function getShowTabs( blockName, tabSettings = {} ) {
export default function useInspectorControlsTabs( blockName ) {
const tabs = [];
const {
bindings: bindingsGroup,
border: borderGroup,
color: colorGroup,
default: defaultGroup,
Expand Down Expand Up @@ -64,8 +65,10 @@ export default function useInspectorControlsTabs( blockName ) {
// (i.e. both list view and styles), check only the default and position
// InspectorControls slots. If we have multiple tabs, we'll need to check
// the advanced controls slot as well to ensure they are rendered.
const advancedFills =
useSlotFills( InspectorAdvancedControls.slotName ) || [];
const advancedFills = [
...( useSlotFills( InspectorAdvancedControls.slotName ) || [] ),
...( useSlotFills( bindingsGroup.Slot.__unstableName ) || [] ),
];

const settingsFills = [
...( useSlotFills( defaultGroup.Slot.__unstableName ) || [] ),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { createSlotFill } from '@wordpress/components';

const InspectorControlsDefault = createSlotFill( 'InspectorControls' );
const InspectorControlsAdvanced = createSlotFill( 'InspectorAdvancedControls' );
const InspectorControlsBindings = createSlotFill( 'InspectorControlsBindings' );
const InspectorControlsBackground = createSlotFill(
'InspectorControlsBackground'
);
Expand All @@ -26,6 +27,7 @@ const groups = {
default: InspectorControlsDefault,
advanced: InspectorControlsAdvanced,
background: InspectorControlsBackground,
bindings: InspectorControlsBindings,
border: InspectorControlsBorder,
color: InspectorControlsColor,
dimensions: InspectorControlsDimensions,
Expand Down
27 changes: 19 additions & 8 deletions packages/block-editor/src/hooks/block-bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
__experimentalVStack as VStack,
privateApis as componentsPrivateApis,
} from '@wordpress/components';
import { useRegistry } from '@wordpress/data';
import { useRegistry, useSelect } from '@wordpress/data';
import { useContext, Fragment } from '@wordpress/element';
import { useViewportMatch } from '@wordpress/compose';

Expand All @@ -28,6 +28,7 @@ import { unlock } from '../lock-unlock';
import InspectorControls from '../components/inspector-controls';
import BlockContext from '../components/block-context';
import { useBlockBindingsUtils } from '../utils/block-bindings';
import { store as blockEditorStore } from '../store';

const { DropdownMenuV2 } = unlock( componentsPrivateApis );

Expand Down Expand Up @@ -201,6 +202,13 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
}
} );

const { canUpdateBlockBindings } = useSelect( ( select ) => {
return {
canUpdateBlockBindings:
select( blockEditorStore ).getSettings().canUpdateBlockBindings,
};
}, [] );

if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
return null;
}
Expand Down Expand Up @@ -236,17 +244,16 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
}
} );

// Lock the UI when the experiment is not enabled or there are no fields to connect to.
// Lock the UI when the user can't update bindings or there are no fields to connect to.
const readOnly =
! window.__experimentalBlockBindingsUI ||
! Object.keys( fieldsList ).length;
! canUpdateBlockBindings || ! Object.keys( fieldsList ).length;

if ( readOnly && Object.keys( filteredBindings ).length === 0 ) {
return null;
}

return (
<InspectorControls>
<InspectorControls group="bindings">
<ToolsPanel
label={ __( 'Attributes' ) }
resetAll={ () => {
Expand All @@ -268,9 +275,13 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
/>
) }
</ItemGroup>
<Text variant="muted">
{ __( 'Attributes connected to various sources.' ) }
</Text>
<ItemGroup>
<Text variant="muted">
{ __(
'Attributes connected to custom fields or other dynamic data.'
) }
</Text>
</ItemGroup>
</ToolsPanel>
</InspectorControls>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const BLOCK_EDITOR_SETTINGS = [
'allowedMimeTypes',
'bodyPlaceholder',
'canLockBlocks',
'canUpdateBlockBindings',
'capabilities',
'clearBlockSelection',
'codeEditingEnabled',
Expand Down
54 changes: 6 additions & 48 deletions test/e2e/specs/editor/various/block-bindings.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1394,20 +1394,10 @@ test.describe( 'Block bindings', () => {
editor,
page,
} ) => {
// Activate the block bindings UI experiment.
await page.evaluate( () => {
window.__experimentalBlockBindingsUI = true;
} );

await editor.insertBlock( {
name: 'core/paragraph',
} );
await page
.getByRole( 'tabpanel', {
name: 'Settings',
} )
.getByLabel( 'Attributes options' )
.click();
await page.getByLabel( 'Attributes options' ).click();
const contentAttribute = page.getByRole( 'menuitemcheckbox', {
name: 'Show content',
} );
Expand All @@ -1417,11 +1407,6 @@ test.describe( 'Block bindings', () => {
editor,
page,
} ) => {
// Activate the block bindings UI experiment.
await page.evaluate( () => {
window.__experimentalBlockBindingsUI = true;
} );

await editor.insertBlock( {
name: 'core/paragraph',
attributes: {
Expand All @@ -1436,12 +1421,7 @@ test.describe( 'Block bindings', () => {
},
},
} );
await page
.getByRole( 'tabpanel', {
name: 'Settings',
} )
.getByRole( 'button', { name: 'content' } )
.click();
await page.getByRole( 'button', { name: 'content' } ).click();

await page
.getByRole( 'menuitemradio' )
Expand Down Expand Up @@ -1539,20 +1519,10 @@ test.describe( 'Block bindings', () => {
editor,
page,
} ) => {
// Activate the block bindings UI experiment.
await page.evaluate( () => {
window.__experimentalBlockBindingsUI = true;
} );

await editor.insertBlock( {
name: 'core/heading',
} );
await page
.getByRole( 'tabpanel', {
name: 'Settings',
} )
.getByLabel( 'Attributes options' )
.click();
await page.getByLabel( 'Attributes options' ).click();
const contentAttribute = page.getByRole( 'menuitemcheckbox', {
name: 'Show content',
} );
Expand Down Expand Up @@ -1739,11 +1709,6 @@ test.describe( 'Block bindings', () => {
editor,
page,
} ) => {
// Activate the block bindings UI experiment.
await page.evaluate( () => {
window.__experimentalBlockBindingsUI = true;
} );

await editor.insertBlock( {
name: 'core/buttons',
innerBlocks: [
Expand Down Expand Up @@ -2074,11 +2039,6 @@ test.describe( 'Block bindings', () => {
editor,
page,
} ) => {
// Activate the block bindings UI experiment.
await page.evaluate( () => {
window.__experimentalBlockBindingsUI = true;
} );

await editor.insertBlock( {
name: 'core/image',
} );
Expand Down Expand Up @@ -2367,11 +2327,9 @@ test.describe( 'Block bindings', () => {
},
} );

const bindingsPanel = page
.getByRole( 'tabpanel', {
name: 'Settings',
} )
.locator( '.block-editor-bindings__panel' );
const bindingsPanel = page.locator(
'.block-editor-bindings__panel'
);
await expect( bindingsPanel ).toContainText( 'Server Source' );
} );
} );
Expand Down
Loading