Changeset 56710 for trunk/src/wp-includes/blocks/image.php
- Timestamp:
- 09/26/2023 02:20:18 PM (17 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/blocks/image.php
r56065 r56710 10 10 * adding a data-id attribute to the element if core/gallery has added on pre-render. 11 11 * 12 * @param array $attributes The block attributes. 13 * @param string $content The block content. 12 * @param array $attributes The block attributes. 13 * @param string $content The block content. 14 * @param WP_Block $block The block object. 14 15 * @return string Returns the block content with the data-id attribute added. 15 16 */ 16 function render_block_core_image( $attributes, $content ) {17 function render_block_core_image( $attributes, $content, $block ) { 17 18 18 19 $processor = new WP_HTML_Tag_Processor( $content ); … … 31 32 } 32 33 34 $lightbox_enabled = false; 35 $link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none'; 36 $lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block ); 37 38 // If the lightbox is enabled and the image is not linked, flag the lightbox to be rendered. 39 if ( isset( $lightbox_settings ) && 'none' === $link_destination ) { 40 41 if ( isset( $lightbox_settings['enabled'] ) && true === $lightbox_settings['enabled'] ) { 42 $lightbox_enabled = true; 43 } 44 } 45 46 // If at least one block in the page has the lightbox, mark the block type as interactive. 47 if ( $lightbox_enabled ) { 48 $block->block_type->supports['interactivity'] = true; 49 } 50 51 // Determine whether the view script should be enqueued or not. 52 $view_js_file = 'wp-block-image-view'; 53 if ( ! wp_script_is( $view_js_file ) ) { 54 $script_handles = $block->block_type->view_script_handles; 55 56 // If the script is not needed, and it is still in the `view_script_handles`, remove it. 57 if ( ! $lightbox_enabled && in_array( $view_js_file, $script_handles, true ) ) { 58 $block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file ) ); 59 } 60 // If the script is needed, but it was previously removed, add it again. 61 if ( $lightbox_enabled && ! in_array( $view_js_file, $script_handles, true ) ) { 62 $block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file ) ); 63 } 64 } 65 66 if ( $lightbox_enabled ) { 67 return block_core_image_render_lightbox( $processor->get_updated_html(), $block->parsed_block ); 68 } 69 33 70 return $processor->get_updated_html(); 34 71 } 35 72 36 73 /** 74 * Add the lightboxEnabled flag to the block data. 75 * 76 * This is used to determine whether the lightbox should be rendered or not. 77 * 78 * @param array $block Block data. 79 * @return array Filtered block data. 80 */ 81 function block_core_image_get_lightbox_settings( $block ) { 82 // Get the lightbox setting from the block attributes. 83 if ( isset( $block['attrs']['lightbox'] ) ) { 84 $lightbox_settings = $block['attrs']['lightbox']; 85 // If the lightbox setting is not set in the block attributes, 86 // check the legacy lightbox settings that are set using the 87 // `gutenberg_should_render_lightbox` filter. 88 // We can remove this elseif statement when the legacy lightbox settings are removed. 89 } elseif ( isset( $block['legacyLightboxSettings'] ) ) { 90 $lightbox_settings = $block['legacyLightboxSettings']; 91 } 92 93 if ( ! isset( $lightbox_settings ) ) { 94 $lightbox_settings = wp_get_global_settings( array( 'lightbox' ), array( 'block_name' => 'core/image' ) ); 95 96 // If not present in global settings, check the top-level global settings. 97 // 98 // NOTE: If no block-level settings are found, the previous call to 99 // `wp_get_global_settings` will return the whole `theme.json` 100 // structure in which case we can check if the "lightbox" key is present at 101 // the top-level of the global settings and use its value. 102 if ( isset( $lightbox_settings['lightbox'] ) ) { 103 $lightbox_settings = wp_get_global_settings( array( 'lightbox' ) ); 104 } 105 } 106 107 return $lightbox_settings ?? null; 108 } 109 110 /** 111 * Add the directives and layout needed for the lightbox behavior. 112 * 113 * @param string $block_content Rendered block content. 114 * @param array $block Block object. 115 * @return string Filtered block content. 116 */ 117 function block_core_image_render_lightbox( $block_content, $block ) { 118 $processor = new WP_HTML_Tag_Processor( $block_content ); 119 120 $aria_label = __( 'Enlarge image' ); 121 122 $alt_attribute = $processor->get_attribute( 'alt' ); 123 124 if ( null !== $alt_attribute ) { 125 $alt_attribute = trim( $alt_attribute ); 126 } 127 128 if ( $alt_attribute ) { 129 /* translators: %s: Image alt text. */ 130 $aria_label = sprintf( __( 'Enlarge image: %s' ), $alt_attribute ); 131 } 132 $content = $processor->get_updated_html(); 133 134 // Currently, we are only enabling the zoom animation. 135 $lightbox_animation = 'zoom'; 136 137 // We want to store the src in the context so we can set it dynamically when the lightbox is opened. 138 $z = new WP_HTML_Tag_Processor( $content ); 139 $z->next_tag( 'img' ); 140 141 if ( isset( $block['attrs']['id'] ) ) { 142 $img_uploaded_src = wp_get_attachment_url( $block['attrs']['id'] ); 143 $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); 144 $img_width = $img_metadata['width']; 145 $img_height = $img_metadata['height']; 146 } else { 147 $img_uploaded_src = $z->get_attribute( 'src' ); 148 $img_width = 'none'; 149 $img_height = 'none'; 150 } 151 152 if ( isset( $block['attrs']['scale'] ) ) { 153 $scale_attr = $block['attrs']['scale']; 154 } else { 155 $scale_attr = false; 156 } 157 158 $w = new WP_HTML_Tag_Processor( $content ); 159 $w->next_tag( 'figure' ); 160 $w->add_class( 'wp-lightbox-container' ); 161 $w->set_attribute( 'data-wp-interactive', true ); 162 163 $w->set_attribute( 164 'data-wp-context', 165 sprintf( 166 '{ "core": 167 { "image": 168 { "imageLoaded": false, 169 "initialized": false, 170 "lightboxEnabled": false, 171 "hideAnimationEnabled": false, 172 "preloadInitialized": false, 173 "lightboxAnimation": "%s", 174 "imageUploadedSrc": "%s", 175 "imageCurrentSrc": "", 176 "targetWidth": "%s", 177 "targetHeight": "%s", 178 "scaleAttr": "%s" 179 } 180 } 181 }', 182 $lightbox_animation, 183 $img_uploaded_src, 184 $img_width, 185 $img_height, 186 $scale_attr 187 ) 188 ); 189 $w->next_tag( 'img' ); 190 $w->set_attribute( 'data-wp-init', 'effects.core.image.setCurrentSrc' ); 191 $w->set_attribute( 'data-wp-on--load', 'actions.core.image.handleLoad' ); 192 $w->set_attribute( 'data-wp-effect', 'effects.core.image.setButtonStyles' ); 193 $body_content = $w->get_updated_html(); 194 195 // Wrap the image in the body content with a button. 196 $img = null; 197 preg_match( '/<img[^>]+>/', $body_content, $img ); 198 $button = 199 '<button 200 type="button" 201 aria-haspopup="dialog" 202 aria-label="' . esc_attr( $aria_label ) . '" 203 data-wp-on--click="actions.core.image.showLightbox" 204 data-wp-style--width="context.core.image.imageButtonWidth" 205 data-wp-style--height="context.core.image.imageButtonHeight" 206 data-wp-style--left="context.core.image.imageButtonLeft" 207 data-wp-style--top="context.core.image.imageButtonTop" 208 > 209 </button>' 210 . $img[0]; 211 $body_content = preg_replace( '/<img[^>]+>/', $button, $body_content ); 212 213 // We need both a responsive image and an enlarged image to animate 214 // the zoom seamlessly on slow internet connections; the responsive 215 // image is a copy of the one in the body, which animates immediately 216 // as the lightbox is opened, while the enlarged one is a full-sized 217 // version that will likely still be loading as the animation begins. 218 $m = new WP_HTML_Tag_Processor( $content ); 219 $m->next_tag( 'figure' ); 220 $m->add_class( 'responsive-image' ); 221 $m->next_tag( 'img' ); 222 // We want to set the 'src' attribute to an empty string in the responsive image 223 // because otherwise, as of this writing, the wp_filter_content_tags() function in 224 // WordPress will automatically add a 'srcset' attribute to the image, which will at 225 // times cause the incorrectly sized image to be loaded in the lightbox on Firefox. 226 // Because of this, we bind the 'src' attribute explicitly the current src to reliably 227 // use the exact same image as in the content when the lightbox is first opened while 228 // we wait for the larger image to load. 229 $m->set_attribute( 'src', '' ); 230 $m->set_attribute( 'data-wp-bind--src', 'context.core.image.imageCurrentSrc' ); 231 $m->set_attribute( 'data-wp-style--object-fit', 'selectors.core.image.lightboxObjectFit' ); 232 $initial_image_content = $m->get_updated_html(); 233 234 $q = new WP_HTML_Tag_Processor( $content ); 235 $q->next_tag( 'figure' ); 236 $q->add_class( 'enlarged-image' ); 237 $q->next_tag( 'img' ); 238 239 // We set the 'src' attribute to an empty string to prevent the browser from loading the image 240 // on initial page load, then bind the attribute to a selector that returns the full-sized image src when 241 // the lightbox is opened. We could use 'loading=lazy' in combination with the 'hidden' attribute to 242 // accomplish the same behavior, but that approach breaks progressive loading of the image in Safari 243 // and Chrome (see https://github.com/WordPress/gutenberg/pull/52765#issuecomment-1674008151). Until that 244 // is resolved, manually setting the 'src' seems to be the best solution to load the large image on demand. 245 $q->set_attribute( 'src', '' ); 246 $q->set_attribute( 'data-wp-bind--src', 'selectors.core.image.enlargedImgSrc' ); 247 $q->set_attribute( 'data-wp-style--object-fit', 'selectors.core.image.lightboxObjectFit' ); 248 $enlarged_image_content = $q->get_updated_html(); 249 250 $background_color = esc_attr( wp_get_global_styles( array( 'color', 'background' ) ) ); 251 252 $close_button_icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="15" height="15" aria-hidden="true" focusable="false"><path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path></svg>'; 253 $close_button_color = esc_attr( wp_get_global_styles( array( 'color', 'text' ) ) ); 254 $dialog_label = $alt_attribute ? esc_attr( $alt_attribute ) : esc_attr__( 'Image' ); 255 $close_button_label = esc_attr__( 'Close' ); 256 257 $lightbox_html = <<<HTML 258 <div data-wp-body="" class="wp-lightbox-overlay $lightbox_animation" 259 data-wp-bind--role="selectors.core.image.roleAttribute" 260 aria-label="$dialog_label" 261 data-wp-class--initialized="context.core.image.initialized" 262 data-wp-class--active="context.core.image.lightboxEnabled" 263 data-wp-class--hideAnimationEnabled="context.core.image.hideAnimationEnabled" 264 data-wp-bind--aria-hidden="!context.core.image.lightboxEnabled" 265 aria-hidden="true" 266 data-wp-bind--aria-modal="context.core.image.lightboxEnabled" 267 aria-modal="false" 268 data-wp-effect="effects.core.image.initLightbox" 269 data-wp-on--keydown="actions.core.image.handleKeydown" 270 data-wp-on--mousewheel="actions.core.image.hideLightbox" 271 data-wp-on--click="actions.core.image.hideLightbox" 272 > 273 <button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button" data-wp-on--click="actions.core.image.hideLightbox"> 274 $close_button_icon 275 </button> 276 <div class="lightbox-image-container">$initial_image_content</div> 277 <div class="lightbox-image-container">$enlarged_image_content</div> 278 <div class="scrim" style="background-color: $background_color"></div> 279 </div> 280 HTML; 281 282 return str_replace( '</figure>', $lightbox_html . '</figure>', $body_content ); 283 } 284 285 /** 286 * Ensure that the view script has the `wp-interactivity` dependency. 287 * 288 * @since 6.4.0 289 * 290 * @global WP_Scripts $wp_scripts 291 */ 292 function block_core_image_ensure_interactivity_dependency() { 293 global $wp_scripts; 294 if ( 295 isset( $wp_scripts->registered['wp-block-image-view'] ) && 296 ! in_array( 'wp-interactivity', $wp_scripts->registered['wp-block-image-view']->deps, true ) 297 ) { 298 $wp_scripts->registered['wp-block-image-view']->deps[] = 'wp-interactivity'; 299 } 300 } 301 302 add_action( 'wp_print_scripts', 'block_core_image_ensure_interactivity_dependency' ); 303 304 /** 37 305 * Registers the `core/image` block on server. 38 306 */ 39 307 function register_block_core_image() { 40 41 308 register_block_type_from_metadata( 42 309 __DIR__ . '/image',
Note: See TracChangeset
for help on using the changeset viewer.