From 00285e8ec9ead5823b0ada340dd799ed13a4f3eb Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 2 Jun 2023 14:55:23 +0200 Subject: [PATCH 1/6] Move behaviors to block supports --- lib/block-supports/behaviors.php | 151 +++++++++++++++++++ lib/load.php | 1 + packages/block-editor/src/hooks/behaviors.js | 28 ++-- packages/block-library/src/image/block.json | 6 +- packages/block-library/src/image/index.php | 75 --------- 5 files changed, 169 insertions(+), 92 deletions(-) create mode 100644 lib/block-supports/behaviors.php diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php new file mode 100644 index 00000000000000..cd25bc898b6f21 --- /dev/null +++ b/lib/block-supports/behaviors.php @@ -0,0 +1,151 @@ +attributes) { + $block_type->attributes = array(); + } + + $block_type->attributes['behaviors'] = array( + 'type' => 'object', + ); + + // If it supports the lightbox behavior, add the hook to that block. + // In the future, this should be a loop with all the behaviors. + $has_lightbox_support = block_has_support($block_type, array('behaviors', 'lightbox'), false); + if ($has_lightbox_support) { + add_filter('render_block_' . $block_type->name, 'gutenberg_blocks_supports_add_lightbox', 15, 2); + } +} + +function gutenberg_apply_behaviors_support($block_type, $block_attributes) +{ + $attributes = array(); + + if (!$block_attributes) { + return $attributes; + } + + if (wp_should_skip_block_supports_serialization($block_type, 'behaviors')) { + return $attributes; + } + + $has_behaviors_support = block_has_support($block_type, array('behaviors'), false); + if (!$has_behaviors_support) { + return $attributes; + } + + // Lightbox behavior. + $has_lightbox_support = block_has_support($block_type, array('behaviors', 'lightbox'), false); + if ($has_lightbox_support) { + $attributes['behaviors']['lightbox'] = true; + } + + return $attributes; +} + +// This functions shouldn't be in this file. It should be moved to a package (or somewhere else), where all the behaviors logic is defined. +function gutenberg_blocks_supports_add_lightbox($block_content, $block) +{ + $experiments = get_option('gutenberg-experiments'); + $link_destination = isset($block['attrs']['linkDestination']) ? $block['attrs']['linkDestination'] : 'none'; + // Get the lightbox setting from the block attributes. + if (isset($block['attrs']['behaviors']['lightbox'])) { + $lightbox = $block['attrs']['behaviors']['lightbox']; + // If the lightbox setting is not set in the block attributes, get it from the theme.json file. + } else { + $theme_data = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data()->get_data(); + if (isset($theme_data['behaviors']['blocks']['core/image']['lightbox'])) { + $lightbox = $theme_data['behaviors']['blocks']['core/image']['lightbox']; + } else { + $lightbox = false; + } + } + + if (!$lightbox || $link_destination !== 'none' || empty($experiments['gutenberg-interactivity-api-core-blocks'])) { + return $block_content; + } + + $processor = new WP_HTML_Tag_Processor($block_content); + + $aria_label = __('Enlarge image'); + + $alt_attribute = trim($processor->get_attribute('alt')); + + if ($alt_attribute) { + /* translators: %s: Image alt text. */ + $aria_label = sprintf(__('Enlarge image: %s'), $alt_attribute); + } + $content = $processor->get_updated_html(); + + $w = new WP_HTML_Tag_Processor($content); + $w->next_tag('figure'); + $w->add_class('wp-lightbox-container'); + $w->set_attribute('data-wp-interactive', true); + $w->set_attribute('data-wp-context', '{ "core": { "image": { "initialized": false, "lightboxEnabled": false } } }'); + $body_content = $w->get_updated_html(); + + // Wrap the image in the body content with a button. + $img = null; + preg_match('/]+>/', $content, $img); + $button = '
+ ' + . $img[0] . + '
'; + $body_content = preg_replace('/]+>/', $button, $body_content); + + $background_color = esc_attr(wp_get_global_styles(array('color', 'background'))); + $close_button_icon = ''; + + $dialog_label = $alt_attribute ? esc_attr($alt_attribute) : esc_attr__('Image'); + $close_button_label = esc_attr__('Close'); + + $lightbox_html = << + + $content +
+ +HTML; + + return str_replace('', $lightbox_html . '', $body_content); +} + +// Register the block support. +WP_Block_Supports::get_instance()->register( + 'behaviors', + array( + 'register_attribute' => 'gutenberg_register_behaviors_support', + 'apply' => 'gutenberg_apply_behaviors_support', + ) +); diff --git a/lib/load.php b/lib/load.php index 801cd27527c96e..29d6fceb4f11c7 100644 --- a/lib/load.php +++ b/lib/load.php @@ -165,3 +165,4 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/block-supports/duotone.php'; require __DIR__ . '/block-supports/anchor.php'; require __DIR__ . '/block-supports/shadow.php'; +require __DIR__ . '/block-supports/behaviors.php'; diff --git a/packages/block-editor/src/hooks/behaviors.js b/packages/block-editor/src/hooks/behaviors.js index 63230b6ee273f4..742e8b48dd886a 100644 --- a/packages/block-editor/src/hooks/behaviors.js +++ b/packages/block-editor/src/hooks/behaviors.js @@ -4,6 +4,7 @@ import { addFilter } from '@wordpress/hooks'; import { SelectControl } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; +import { hasBlockSupport } from '@wordpress/blocks'; import { createHigherOrderComponent } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; @@ -38,24 +39,17 @@ function BehaviorsControl( { [ blockName ] ); - if ( - ! settings || - // If every behavior is disabled, do not show the behaviors inspector control. - Object.entries( settings ).every( ( [ , value ] ) => ! value ) - ) { - return null; - } - - // Block behaviors take precedence over theme behaviors. - const behaviors = merge( themeBehaviors, blockBehaviors || {} ); - const noBehaviorsOption = { value: '', label: __( 'No behaviors' ), }; const behaviorsOptions = Object.entries( settings ) - .filter( ( [ , behaviorValue ] ) => behaviorValue ) // Filter out behaviors that are disabled. + .filter( + ( [ behaviorName, behaviorValue ] ) => + hasBlockSupport( blockName, 'behaviors.' + behaviorName ) && + behaviorValue + ) // Filter out behaviors that are disabled. .map( ( [ behaviorName ] ) => ( { value: behaviorName, label: @@ -64,8 +58,14 @@ function BehaviorsControl( { behaviorName.slice( 1 ).toLowerCase(), } ) ); + // If every behavior is disabled, do not show the behaviors inspector control. + if ( behaviorsOptions.length === 0 ) return null; + const options = [ noBehaviorsOption, ...behaviorsOptions ]; + // Block behaviors take precedence over theme behaviors. + const behaviors = merge( themeBehaviors, blockBehaviors || {} ); + const helpText = disabled ? __( 'The lightbox behavior is disabled for linked images.' ) : __( 'Add behaviors.' ); @@ -101,8 +101,8 @@ function BehaviorsControl( { export const withBehaviors = createHigherOrderComponent( ( BlockEdit ) => { return ( props ) => { const blockEdit = ; - // Only add behaviors to the core/image block. - if ( props.name !== 'core/image' ) { + // Only add behaviors to blocks with support. + if ( ! hasBlockSupport( props.name, 'behaviors' ) ) { return blockEdit; } const blockHasLink = diff --git a/packages/block-library/src/image/block.json b/packages/block-library/src/image/block.json index 791e09f73c8009..d9d8b2c9eb25db 100644 --- a/packages/block-library/src/image/block.json +++ b/packages/block-library/src/image/block.json @@ -80,13 +80,13 @@ "source": "attribute", "selector": "figure > a", "attribute": "target" - }, - "behaviors": { - "type": "object" } }, "supports": { "anchor": true, + "behaviors": { + "lightbox": true + }, "color": { "text": false, "background": false diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 3c90f0fbc21cfe..1e437d860aa097 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -30,81 +30,6 @@ function render_block_core_image( $attributes, $content ) { $processor->set_attribute( 'data-id', $attributes['data-id'] ); } - $link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none'; - - // Get the lightbox setting from the block attributes. - if ( isset( $attributes['behaviors']['lightbox'] ) ) { - $lightbox = $attributes['behaviors']['lightbox']; - // If the lightbox setting is not set in the block attributes, get it from the theme.json file. - } else { - $theme_data = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data()->get_data(); - if ( isset( $theme_data['behaviors']['blocks']['core/image']['lightbox'] ) ) { - $lightbox = $theme_data['behaviors']['blocks']['core/image']['lightbox']; - } else { - $lightbox = false; - } - } - - $experiments = get_option( 'gutenberg-experiments' ); - - if ( ! empty( $experiments['gutenberg-interactivity-api-core-blocks'] ) && 'none' === $link_destination && $lightbox ) { - - $aria_label = __( 'Enlarge image' ); - - $alt_attribute = trim( $processor->get_attribute( 'alt' ) ); - - if ( $alt_attribute ) { - /* translators: %s: Image alt text. */ - $aria_label = sprintf( __( 'Enlarge image: %s' ), $alt_attribute ); - } - $content = $processor->get_updated_html(); - - $w = new WP_HTML_Tag_Processor( $content ); - $w->next_tag( 'figure' ); - $w->add_class( 'wp-lightbox-container' ); - $w->set_attribute( 'data-wp-interactive', true ); - $w->set_attribute( 'data-wp-context', '{ "core": { "image": { "initialized": false, "lightboxEnabled": false } } }' ); - $body_content = $w->get_updated_html(); - - // Wrap the image in the body content with a button. - $img = null; - preg_match( '/]+>/', $content, $img ); - $button = '
- ' - . $img[0] . - '
'; - $body_content = preg_replace( '/]+>/', $button, $body_content ); - - $background_color = esc_attr( wp_get_global_styles( array( 'color', 'background' ) ) ); - $close_button_icon = ''; - - $dialog_label = $alt_attribute ? esc_attr( $alt_attribute ) : esc_attr__( 'Image' ); - $close_button_label = esc_attr__( 'Close' ); - - $lightbox_html = << - - $content -
- -HTML; - - return str_replace( '', $lightbox_html . '', $body_content ); - } - return $processor->get_updated_html(); } From 984e0acba414aed89ca856a5b386881bec04ae85 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 5 Jun 2023 10:56:44 +0200 Subject: [PATCH 2/6] Remove apply from block supports and format PHP --- lib/block-supports/behaviors.php | 199 ++++++++++++++----------------- 1 file changed, 88 insertions(+), 111 deletions(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index cd25bc898b6f21..143a5bbdeb810a 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -1,5 +1,4 @@ attributes) { - $block_type->attributes = array(); - } - - $block_type->attributes['behaviors'] = array( - 'type' => 'object', - ); - - // If it supports the lightbox behavior, add the hook to that block. - // In the future, this should be a loop with all the behaviors. - $has_lightbox_support = block_has_support($block_type, array('behaviors', 'lightbox'), false); - if ($has_lightbox_support) { - add_filter('render_block_' . $block_type->name, 'gutenberg_blocks_supports_add_lightbox', 15, 2); - } +function gutenberg_register_behaviors_support( $block_type ) { + $has_behaviors_support = block_has_support( $block_type, array( 'behaviors' ), false ); + if ( ! $has_behaviors_support ) { + return; + } + + if ( ! $block_type->attributes ) { + $block_type->attributes = array(); + } + + $block_type->attributes['behaviors'] = array( + 'type' => 'object', + ); + + // If it supports the lightbox behavior, add the hook to that block. + // In the future, this should be a loop with all the behaviors. + $has_lightbox_support = block_has_support( $block_type, array( 'behaviors', 'lightbox' ), false ); + if ( $has_lightbox_support ) { + add_filter( 'render_block_' . $block_type->name, 'gutenberg_blocks_supports_add_lightbox', 15, 2 ); + } } -function gutenberg_apply_behaviors_support($block_type, $block_attributes) -{ - $attributes = array(); - - if (!$block_attributes) { - return $attributes; - } - - if (wp_should_skip_block_supports_serialization($block_type, 'behaviors')) { - return $attributes; - } - - $has_behaviors_support = block_has_support($block_type, array('behaviors'), false); - if (!$has_behaviors_support) { - return $attributes; - } - - // Lightbox behavior. - $has_lightbox_support = block_has_support($block_type, array('behaviors', 'lightbox'), false); - if ($has_lightbox_support) { - $attributes['behaviors']['lightbox'] = true; - } - - return $attributes; -} - -// This functions shouldn't be in this file. It should be moved to a package (or somewhere else), where all the behaviors logic is defined. -function gutenberg_blocks_supports_add_lightbox($block_content, $block) -{ - $experiments = get_option('gutenberg-experiments'); - $link_destination = isset($block['attrs']['linkDestination']) ? $block['attrs']['linkDestination'] : 'none'; - // Get the lightbox setting from the block attributes. - if (isset($block['attrs']['behaviors']['lightbox'])) { - $lightbox = $block['attrs']['behaviors']['lightbox']; - // If the lightbox setting is not set in the block attributes, get it from the theme.json file. - } else { - $theme_data = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data()->get_data(); - if (isset($theme_data['behaviors']['blocks']['core/image']['lightbox'])) { - $lightbox = $theme_data['behaviors']['blocks']['core/image']['lightbox']; - } else { - $lightbox = false; - } - } - - if (!$lightbox || $link_destination !== 'none' || empty($experiments['gutenberg-interactivity-api-core-blocks'])) { - return $block_content; - } - - $processor = new WP_HTML_Tag_Processor($block_content); - - $aria_label = __('Enlarge image'); - - $alt_attribute = trim($processor->get_attribute('alt')); - - if ($alt_attribute) { - /* translators: %s: Image alt text. */ - $aria_label = sprintf(__('Enlarge image: %s'), $alt_attribute); - } - $content = $processor->get_updated_html(); - - $w = new WP_HTML_Tag_Processor($content); - $w->next_tag('figure'); - $w->add_class('wp-lightbox-container'); - $w->set_attribute('data-wp-interactive', true); - $w->set_attribute('data-wp-context', '{ "core": { "image": { "initialized": false, "lightboxEnabled": false } } }'); - $body_content = $w->get_updated_html(); - - // Wrap the image in the body content with a button. - $img = null; - preg_match('/]+>/', $content, $img); - $button = '
- ' - . $img[0] . - '
'; - $body_content = preg_replace('/]+>/', $button, $body_content); - - $background_color = esc_attr(wp_get_global_styles(array('color', 'background'))); - $close_button_icon = ''; - - $dialog_label = $alt_attribute ? esc_attr($alt_attribute) : esc_attr__('Image'); - $close_button_label = esc_attr__('Close'); - - $lightbox_html = <<get_data(); + if ( isset( $theme_data['behaviors']['blocks'][ $block['blockName'] ]['lightbox'] ) ) { + $lightbox = $theme_data['behaviors']['blocks'][ $block['blockName'] ]['lightbox']; + } else { + $lightbox = false; + } + } + + if ( ! $lightbox || 'none' !== $link_destination || empty( $experiments['gutenberg-interactivity-api-core-blocks'] ) ) { + return $block_content; + } + + $processor = new WP_HTML_Tag_Processor( $block_content ); + + $aria_label = __( 'Enlarge image', 'gutenberg' ); + + $alt_attribute = trim( $processor->get_attribute( 'alt' ) ); + + if ( $alt_attribute ) { + /* translators: %s: Image alt text. */ + $aria_label = sprintf( __( 'Enlarge image: %s', 'gutenberg' ), $alt_attribute ); + } + $content = $processor->get_updated_html(); + + $w = new WP_HTML_Tag_Processor( $content ); + $w->next_tag( 'figure' ); + $w->add_class( 'wp-lightbox-container' ); + $w->set_attribute( 'data-wp-interactive', true ); + $w->set_attribute( 'data-wp-context', '{ "core": { "image": { "initialized": false, "lightboxEnabled": false } } }' ); + $body_content = $w->get_updated_html(); + + // Wrap the image in the body content with a button. + $img = null; + preg_match( '/]+>/', $content, $img ); + $button = '
+ ' + . $img[0] . + '
'; + $body_content = preg_replace( '/]+>/', $button, $body_content ); + + $background_color = esc_attr( wp_get_global_styles( array( 'color', 'background' ) ) ); + $close_button_icon = ''; + + $dialog_label = $alt_attribute ? esc_attr( $alt_attribute ) : esc_attr__( 'Image', 'gutenberg' ); + $close_button_label = esc_attr__( 'Close', 'gutenberg' ); + + $lightbox_html = << HTML; - return str_replace('', $lightbox_html . '', $body_content); + return str_replace( '', $lightbox_html . '', $body_content ); } // Register the block support. WP_Block_Supports::get_instance()->register( - 'behaviors', - array( - 'register_attribute' => 'gutenberg_register_behaviors_support', - 'apply' => 'gutenberg_apply_behaviors_support', - ) + 'behaviors', + array( + 'register_attribute' => 'gutenberg_register_behaviors_support', + ) ); From 90ed870a6f3465fac83ea0b649e4adbe238a1d1e Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Mon, 5 Jun 2023 13:18:15 +0200 Subject: [PATCH 3/6] Update core-blocks reference docs --- docs/reference-guides/core-blocks.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index bf0d3bf71d06f9..ab86f5728115ff 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -330,8 +330,8 @@ Insert an image to make a visual statement. ([Source](https://github.com/WordPre - **Name:** core/image - **Category:** media -- **Supports:** anchor, color (~~background~~, ~~text~~), filter (duotone) -- **Attributes:** align, alt, behaviors, caption, height, href, id, linkClass, linkDestination, linkTarget, rel, sizeSlug, title, url, width +- **Supports:** anchor, behaviors (lightbox), color (~~background~~, ~~text~~), filter (duotone) +- **Attributes:** align, alt, caption, height, href, id, linkClass, linkDestination, linkTarget, rel, sizeSlug, title, url, width ## Latest Comments From d29fc03796efc88a7b213b2258bd20121740b78b Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Tue, 6 Jun 2023 14:55:55 +0200 Subject: [PATCH 4/6] Update latests changes to the image lightbox --- lib/block-supports/behaviors.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index 143a5bbdeb810a..5dbb4e9e0ac9c9 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -89,9 +89,17 @@ function gutenberg_blocks_supports_add_lightbox( $block_content, $block ) { ''; $body_content = preg_replace( '/]+>/', $button, $body_content ); - $background_color = esc_attr( wp_get_global_styles( array( 'color', 'background' ) ) ); - $close_button_icon = ''; + // Add directive to expand modal image if appropriate. + $m = new WP_HTML_Tag_Processor( $content ); + $m->next_tag( 'img' ); + $m->set_attribute( 'data-wp-context', '{ "core": { "image": { "imageSrc": "' . wp_get_attachment_url( $block['attrs']['id'] ) . '"} } }' ); + $m->set_attribute( 'data-wp-bind--src', 'selectors.core.image.imageSrc' ); + $modal_content = $m->get_updated_html(); + $background_color = esc_attr( wp_get_global_styles( array( 'color', 'background' ) ) ); + + $close_button_icon = ''; + $close_button_color = esc_attr( wp_get_global_styles( array( 'color', 'text' ) ) ); $dialog_label = $alt_attribute ? esc_attr( $alt_attribute ) : esc_attr__( 'Image', 'gutenberg' ); $close_button_label = esc_attr__( 'Close', 'gutenberg' ); @@ -108,10 +116,10 @@ function gutenberg_blocks_supports_add_lightbox( $block_content, $block ) { data-wp-on--mousewheel="actions.core.image.hideLightbox" data-wp-on--click="actions.core.image.hideLightbox" > - - $content + $modal_content
HTML; From 0bb0d30232b00e56cfc241d4a592c90e7272aa81 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Tue, 6 Jun 2023 21:17:13 +0200 Subject: [PATCH 5/6] Add comment to explain the priority --- lib/block-supports/behaviors.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index 5dbb4e9e0ac9c9..8d7fa6d9e0d0de 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -29,6 +29,8 @@ function gutenberg_register_behaviors_support( $block_type ) { // In the future, this should be a loop with all the behaviors. $has_lightbox_support = block_has_support( $block_type, array( 'behaviors', 'lightbox' ), false ); if ( $has_lightbox_support ) { + // Use priority 15 to run this hook after other hooks/plugins. + // They could use the `render_block_{$this->name}` filter to modify the markup. add_filter( 'render_block_' . $block_type->name, 'gutenberg_blocks_supports_add_lightbox', 15, 2 ); } } From 55b30c63de777db8d61b4ddfc7739d3c9c3d8220 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Tue, 6 Jun 2023 21:22:49 +0200 Subject: [PATCH 6/6] Change function name to match patterns --- lib/block-supports/behaviors.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/block-supports/behaviors.php b/lib/block-supports/behaviors.php index 8d7fa6d9e0d0de..ea753b2e6f2612 100644 --- a/lib/block-supports/behaviors.php +++ b/lib/block-supports/behaviors.php @@ -31,7 +31,7 @@ function gutenberg_register_behaviors_support( $block_type ) { if ( $has_lightbox_support ) { // Use priority 15 to run this hook after other hooks/plugins. // They could use the `render_block_{$this->name}` filter to modify the markup. - add_filter( 'render_block_' . $block_type->name, 'gutenberg_blocks_supports_add_lightbox', 15, 2 ); + add_filter( 'render_block_' . $block_type->name, 'gutenberg_render_behaviors_support_lightbox', 15, 2 ); } } @@ -43,7 +43,7 @@ function gutenberg_register_behaviors_support( $block_type ) { * @param array $block Block object. * @return string Filtered block content. */ -function gutenberg_blocks_supports_add_lightbox( $block_content, $block ) { +function gutenberg_render_behaviors_support_lightbox( $block_content, $block ) { $experiments = get_option( 'gutenberg-experiments' ); $link_destination = isset( $block['attrs']['linkDestination'] ) ? $block['attrs']['linkDestination'] : 'none'; // Get the lightbox setting from the block attributes.