Edit File by line
/home/zeestwma/ceyloniy.../wp-inclu.../blocks
File: image.php
<?php
[0] Fix | Delete
/**
[1] Fix | Delete
* Server-side rendering of the `core/image` block.
[2] Fix | Delete
*
[3] Fix | Delete
* @package WordPress
[4] Fix | Delete
*/
[5] Fix | Delete
[6] Fix | Delete
/**
[7] Fix | Delete
* Renders the `core/image` block on the server,
[8] Fix | Delete
* adding a data-id attribute to the element if core/gallery has added on pre-render.
[9] Fix | Delete
*
[10] Fix | Delete
* @since 5.9.0
[11] Fix | Delete
*
[12] Fix | Delete
* @param array $attributes The block attributes.
[13] Fix | Delete
* @param string $content The block content.
[14] Fix | Delete
* @param WP_Block $block The block object.
[15] Fix | Delete
*
[16] Fix | Delete
* @return string The block content with the data-id attribute added.
[17] Fix | Delete
*/
[18] Fix | Delete
function render_block_core_image( $attributes, $content, $block ) {
[19] Fix | Delete
if ( false === stripos( $content, '<img' ) ) {
[20] Fix | Delete
return '';
[21] Fix | Delete
}
[22] Fix | Delete
[23] Fix | Delete
$processor = new class( $content ) extends WP_HTML_Tag_Processor {
[24] Fix | Delete
/**
[25] Fix | Delete
* Return input span for an empty FIGCAPTION element.
[26] Fix | Delete
*
[27] Fix | Delete
* Returns span of input for an empty FIGCAPTION, if currently matched on a
[28] Fix | Delete
* FIGCAPTION opening tag and if the element is properly closed and empty.
[29] Fix | Delete
*
[30] Fix | Delete
* @since 6.9.0
[31] Fix | Delete
*
[32] Fix | Delete
* @return WP_HTML_Span|false Span of input if the element is empty; otherwise false.
[33] Fix | Delete
*/
[34] Fix | Delete
public function block_core_image_extract_empty_figcaption_element() {
[35] Fix | Delete
$this->set_bookmark( 'here' );
[36] Fix | Delete
$opener = $this->bookmarks['here'];
[37] Fix | Delete
[38] Fix | Delete
// Allow comments within the definition of “empty.”
[39] Fix | Delete
while ( $this->next_token() && '#comment' === $this->get_token_name() ) {
[40] Fix | Delete
continue;
[41] Fix | Delete
}
[42] Fix | Delete
[43] Fix | Delete
if ( 'FIGCAPTION' !== $this->get_tag() || ! $this->is_tag_closer() ) {
[44] Fix | Delete
return false;
[45] Fix | Delete
}
[46] Fix | Delete
[47] Fix | Delete
$this->set_bookmark( 'here' );
[48] Fix | Delete
$closer = $this->bookmarks['here'];
[49] Fix | Delete
[50] Fix | Delete
return new WP_HTML_Span( $opener->start, $closer->start + $closer->length - $opener->start );
[51] Fix | Delete
}
[52] Fix | Delete
};
[53] Fix | Delete
[54] Fix | Delete
if ( ! $processor->next_tag( 'img' ) || ! $processor->get_attribute( 'src' ) ) {
[55] Fix | Delete
return '';
[56] Fix | Delete
}
[57] Fix | Delete
[58] Fix | Delete
$has_id_binding = isset( $attributes['metadata']['bindings']['id'] ) && isset( $attributes['id'] );
[59] Fix | Delete
[60] Fix | Delete
// Ensure the `wp-image-id` classname on the image block supports block bindings.
[61] Fix | Delete
if ( $has_id_binding ) {
[62] Fix | Delete
// If there's a mismatch with the 'wp-image-' class and the actual id, the id was
[63] Fix | Delete
// probably overridden by block bindings. Update it to the correct value.
[64] Fix | Delete
// See https://github.com/WordPress/gutenberg/issues/62886 for why this is needed.
[65] Fix | Delete
$id = $attributes['id'];
[66] Fix | Delete
$image_classnames = $processor->get_attribute( 'class' );
[67] Fix | Delete
$class_with_binding_value = "wp-image-$id";
[68] Fix | Delete
if ( is_string( $image_classnames ) && ! str_contains( $image_classnames, $class_with_binding_value ) ) {
[69] Fix | Delete
$image_classnames = preg_replace( '/wp-image-(\d+)/', $class_with_binding_value, $image_classnames );
[70] Fix | Delete
$processor->set_attribute( 'class', $image_classnames );
[71] Fix | Delete
}
[72] Fix | Delete
}
[73] Fix | Delete
[74] Fix | Delete
// For backwards compatibility, the data-id html attribute is only set for
[75] Fix | Delete
// image blocks nested in a gallery. Detect if the image is in a gallery by
[76] Fix | Delete
// checking the data-id attribute.
[77] Fix | Delete
// See the `block_core_gallery_data_id_backcompatibility` function.
[78] Fix | Delete
if ( isset( $attributes['data-id'] ) ) {
[79] Fix | Delete
// If there's a binding for the `id`, the `id` attribute is used for the
[80] Fix | Delete
// value, since `data-id` does not support block bindings.
[81] Fix | Delete
// Else the `data-id` is used for backwards compatibility, since
[82] Fix | Delete
// third parties may be filtering its value.
[83] Fix | Delete
$data_id = $has_id_binding ? $attributes['id'] : $attributes['data-id'];
[84] Fix | Delete
$processor->set_attribute( 'data-id', $data_id );
[85] Fix | Delete
}
[86] Fix | Delete
[87] Fix | Delete
/*
[88] Fix | Delete
* If the `caption` attribute is empty and we encounter a `<figcaption>` element,
[89] Fix | Delete
* we take note of its span so we can remove it later.
[90] Fix | Delete
*/
[91] Fix | Delete
if ( $processor->next_tag( 'FIGCAPTION' ) && empty( $attributes['caption'] ) ) {
[92] Fix | Delete
$figcaption_span = $processor->block_core_image_extract_empty_figcaption_element();
[93] Fix | Delete
}
[94] Fix | Delete
[95] Fix | Delete
$link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none';
[96] Fix | Delete
$lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block );
[97] Fix | Delete
[98] Fix | Delete
/*
[99] Fix | Delete
* If the lightbox is enabled and the image is not linked, adds the filter and
[100] Fix | Delete
* the JavaScript view file.
[101] Fix | Delete
*/
[102] Fix | Delete
if (
[103] Fix | Delete
isset( $lightbox_settings ) &&
[104] Fix | Delete
'none' === $link_destination &&
[105] Fix | Delete
isset( $lightbox_settings['enabled'] ) &&
[106] Fix | Delete
true === $lightbox_settings['enabled']
[107] Fix | Delete
) {
[108] Fix | Delete
wp_enqueue_script_module( '@wordpress/block-library/image/view' );
[109] Fix | Delete
[110] Fix | Delete
/*
[111] Fix | Delete
* This render needs to happen in a filter with priority 15 to ensure that
[112] Fix | Delete
* it runs after the duotone filter and that duotone styles are applied to
[113] Fix | Delete
* the image in the lightbox. Lightbox has to work with any plugins that
[114] Fix | Delete
* might use filters as well. Removing this can be considered in the future
[115] Fix | Delete
* if the way the blocks are rendered changes, or if a new kind of filter is
[116] Fix | Delete
* introduced.
[117] Fix | Delete
*/
[118] Fix | Delete
add_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15, 2 );
[119] Fix | Delete
} else {
[120] Fix | Delete
/*
[121] Fix | Delete
* Remove the filter if previously added by other Image blocks.
[122] Fix | Delete
*/
[123] Fix | Delete
remove_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15 );
[124] Fix | Delete
}
[125] Fix | Delete
[126] Fix | Delete
$output = $processor->get_updated_html();
[127] Fix | Delete
if ( ! empty( $figcaption_span ) ) {
[128] Fix | Delete
return substr( $output, 0, $figcaption_span->start ) . substr( $output, $figcaption_span->start + $figcaption_span->length );
[129] Fix | Delete
}
[130] Fix | Delete
return $output;
[131] Fix | Delete
}
[132] Fix | Delete
[133] Fix | Delete
/**
[134] Fix | Delete
* Adds the lightboxEnabled flag to the block data.
[135] Fix | Delete
*
[136] Fix | Delete
* This is used to determine whether the lightbox should be rendered or not.
[137] Fix | Delete
*
[138] Fix | Delete
* @since 6.4.0
[139] Fix | Delete
*
[140] Fix | Delete
* @param array $block Block data.
[141] Fix | Delete
*
[142] Fix | Delete
* @return array|null Filtered block data.
[143] Fix | Delete
*/
[144] Fix | Delete
function block_core_image_get_lightbox_settings( $block ) {
[145] Fix | Delete
// Gets the lightbox setting from the block attributes.
[146] Fix | Delete
if ( isset( $block['attrs']['lightbox'] ) ) {
[147] Fix | Delete
$lightbox_settings = $block['attrs']['lightbox'];
[148] Fix | Delete
}
[149] Fix | Delete
[150] Fix | Delete
if ( ! isset( $lightbox_settings ) ) {
[151] Fix | Delete
$lightbox_settings = wp_get_global_settings( array( 'lightbox' ), array( 'block_name' => 'core/image' ) );
[152] Fix | Delete
[153] Fix | Delete
// If not present in global settings, check the top-level global settings.
[154] Fix | Delete
//
[155] Fix | Delete
// NOTE: If no block-level settings are found, the previous call to
[156] Fix | Delete
// `wp_get_global_settings` will return the whole `theme.json` structure in
[157] Fix | Delete
// which case we can check if the "lightbox" key is present at the top-level
[158] Fix | Delete
// of the global settings and use its value.
[159] Fix | Delete
if ( isset( $lightbox_settings['lightbox'] ) ) {
[160] Fix | Delete
$lightbox_settings = wp_get_global_settings( array( 'lightbox' ) );
[161] Fix | Delete
}
[162] Fix | Delete
}
[163] Fix | Delete
[164] Fix | Delete
return $lightbox_settings ?? null;
[165] Fix | Delete
}
[166] Fix | Delete
[167] Fix | Delete
/**
[168] Fix | Delete
* Adds the directives and layout needed for the lightbox behavior.
[169] Fix | Delete
*
[170] Fix | Delete
* @since 6.4.0
[171] Fix | Delete
*
[172] Fix | Delete
* @param string $block_content Rendered block content.
[173] Fix | Delete
* @param array $block Block object.
[174] Fix | Delete
*
[175] Fix | Delete
* @return string Filtered block content.
[176] Fix | Delete
*/
[177] Fix | Delete
function block_core_image_render_lightbox( $block_content, $block ) {
[178] Fix | Delete
/*
[179] Fix | Delete
* If there's no IMG tag in the block then return the given block content
[180] Fix | Delete
* as-is. There's nothing that this code can knowingly modify to add the
[181] Fix | Delete
* lightbox behavior.
[182] Fix | Delete
*/
[183] Fix | Delete
$processor = new WP_HTML_Tag_Processor( $block_content );
[184] Fix | Delete
if ( $processor->next_tag( 'figure' ) ) {
[185] Fix | Delete
$processor->set_bookmark( 'figure' );
[186] Fix | Delete
}
[187] Fix | Delete
if ( ! $processor->next_tag( 'img' ) ) {
[188] Fix | Delete
return $block_content;
[189] Fix | Delete
}
[190] Fix | Delete
[191] Fix | Delete
$alt = $processor->get_attribute( 'alt' );
[192] Fix | Delete
$img_uploaded_src = $processor->get_attribute( 'src' );
[193] Fix | Delete
$img_class_names = $processor->get_attribute( 'class' );
[194] Fix | Delete
$img_styles = $processor->get_attribute( 'style' );
[195] Fix | Delete
$img_width = 'none';
[196] Fix | Delete
$img_height = 'none';
[197] Fix | Delete
$aria_label = __( 'Enlarge' );
[198] Fix | Delete
$dialog_aria_label = __( 'Enlarged image' );
[199] Fix | Delete
[200] Fix | Delete
if ( isset( $block['attrs']['id'] ) ) {
[201] Fix | Delete
$img_uploaded_src = wp_get_attachment_url( $block['attrs']['id'] );
[202] Fix | Delete
$img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] );
[203] Fix | Delete
$img_width = $img_metadata['width'] ?? 'none';
[204] Fix | Delete
$img_height = $img_metadata['height'] ?? 'none';
[205] Fix | Delete
}
[206] Fix | Delete
[207] Fix | Delete
// Figure.
[208] Fix | Delete
$processor->seek( 'figure' );
[209] Fix | Delete
$figure_class_names = $processor->get_attribute( 'class' );
[210] Fix | Delete
$figure_styles = $processor->get_attribute( 'style' );
[211] Fix | Delete
[212] Fix | Delete
// Create unique id and set the image metadata in the state.
[213] Fix | Delete
$unique_image_id = uniqid();
[214] Fix | Delete
[215] Fix | Delete
wp_interactivity_state(
[216] Fix | Delete
'core/image',
[217] Fix | Delete
array(
[218] Fix | Delete
'metadata' => array(
[219] Fix | Delete
$unique_image_id => array(
[220] Fix | Delete
'uploadedSrc' => $img_uploaded_src,
[221] Fix | Delete
'figureClassNames' => $figure_class_names,
[222] Fix | Delete
'figureStyles' => $figure_styles,
[223] Fix | Delete
'imgClassNames' => $img_class_names,
[224] Fix | Delete
'imgStyles' => $img_styles,
[225] Fix | Delete
'targetWidth' => $img_width,
[226] Fix | Delete
'targetHeight' => $img_height,
[227] Fix | Delete
'scaleAttr' => $block['attrs']['scale'] ?? false,
[228] Fix | Delete
'ariaLabel' => $dialog_aria_label,
[229] Fix | Delete
'alt' => $alt,
[230] Fix | Delete
),
[231] Fix | Delete
),
[232] Fix | Delete
)
[233] Fix | Delete
);
[234] Fix | Delete
[235] Fix | Delete
$processor->add_class( 'wp-lightbox-container' );
[236] Fix | Delete
$processor->set_attribute( 'data-wp-interactive', 'core/image' );
[237] Fix | Delete
$processor->set_attribute(
[238] Fix | Delete
'data-wp-context',
[239] Fix | Delete
wp_json_encode(
[240] Fix | Delete
array(
[241] Fix | Delete
'imageId' => $unique_image_id,
[242] Fix | Delete
),
[243] Fix | Delete
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
[244] Fix | Delete
)
[245] Fix | Delete
);
[246] Fix | Delete
$processor->set_attribute( 'data-wp-key', $unique_image_id );
[247] Fix | Delete
[248] Fix | Delete
// Image.
[249] Fix | Delete
$processor->next_tag( 'img' );
[250] Fix | Delete
$processor->set_attribute( 'data-wp-init', 'callbacks.setButtonStyles' );
[251] Fix | Delete
$processor->set_attribute( 'data-wp-on--load', 'callbacks.setButtonStyles' );
[252] Fix | Delete
$processor->set_attribute( 'data-wp-on-window--resize', 'callbacks.setButtonStyles' );
[253] Fix | Delete
// Sets an event callback on the `img` because the `figure` element can also
[254] Fix | Delete
// contain a caption, and we don't want to trigger the lightbox when the
[255] Fix | Delete
// caption is clicked.
[256] Fix | Delete
$processor->set_attribute( 'data-wp-on--click', 'actions.showLightbox' );
[257] Fix | Delete
$processor->set_attribute( 'data-wp-class--hide', 'state.isContentHidden' );
[258] Fix | Delete
$processor->set_attribute( 'data-wp-class--show', 'state.isContentVisible' );
[259] Fix | Delete
[260] Fix | Delete
$body_content = $processor->get_updated_html();
[261] Fix | Delete
[262] Fix | Delete
// Adds a button alongside image in the body content.
[263] Fix | Delete
$img = null;
[264] Fix | Delete
preg_match( '/<img[^>]+>/', $body_content, $img );
[265] Fix | Delete
[266] Fix | Delete
$button =
[267] Fix | Delete
$img[0]
[268] Fix | Delete
. '<button
[269] Fix | Delete
class="lightbox-trigger"
[270] Fix | Delete
type="button"
[271] Fix | Delete
aria-haspopup="dialog"
[272] Fix | Delete
aria-label="' . esc_attr( $aria_label ) . '"
[273] Fix | Delete
data-wp-init="callbacks.initTriggerButton"
[274] Fix | Delete
data-wp-on--click="actions.showLightbox"
[275] Fix | Delete
data-wp-style--right="state.imageButtonRight"
[276] Fix | Delete
data-wp-style--top="state.imageButtonTop"
[277] Fix | Delete
>
[278] Fix | Delete
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
[279] Fix | Delete
<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
[280] Fix | Delete
</svg>
[281] Fix | Delete
</button>';
[282] Fix | Delete
[283] Fix | Delete
$body_content = preg_replace( '/<img[^>]+>/', $button, $body_content );
[284] Fix | Delete
[285] Fix | Delete
add_action( 'wp_footer', 'block_core_image_print_lightbox_overlay' );
[286] Fix | Delete
[287] Fix | Delete
return $body_content;
[288] Fix | Delete
}
[289] Fix | Delete
[290] Fix | Delete
/**
[291] Fix | Delete
* @since 6.5.0
[292] Fix | Delete
*/
[293] Fix | Delete
function block_core_image_print_lightbox_overlay() {
[294] Fix | Delete
$close_button_label = esc_attr__( 'Close' );
[295] Fix | Delete
[296] Fix | Delete
// If the current theme does NOT have a `theme.json`, or the colors are not
[297] Fix | Delete
// defined, it needs to set the background color & close button color to some
[298] Fix | Delete
// default values because it can't get them from the Global Styles.
[299] Fix | Delete
$background_color = '#fff';
[300] Fix | Delete
$close_button_color = '#000';
[301] Fix | Delete
if ( wp_theme_has_theme_json() ) {
[302] Fix | Delete
$global_styles_color = wp_get_global_styles( array( 'color' ) );
[303] Fix | Delete
if ( ! empty( $global_styles_color['background'] ) ) {
[304] Fix | Delete
$background_color = esc_attr( $global_styles_color['background'] );
[305] Fix | Delete
}
[306] Fix | Delete
if ( ! empty( $global_styles_color['text'] ) ) {
[307] Fix | Delete
$close_button_color = esc_attr( $global_styles_color['text'] );
[308] Fix | Delete
}
[309] Fix | Delete
}
[310] Fix | Delete
[311] Fix | Delete
echo <<<HTML
[312] Fix | Delete
<div
[313] Fix | Delete
class="wp-lightbox-overlay zoom"
[314] Fix | Delete
data-wp-interactive="core/image"
[315] Fix | Delete
data-wp-router-region='{ "id": "core/image-overlay", "attachTo": "body" }'
[316] Fix | Delete
data-wp-key="wp-lightbox-overlay"
[317] Fix | Delete
data-wp-context='{}'
[318] Fix | Delete
data-wp-bind--role="state.roleAttribute"
[319] Fix | Delete
data-wp-bind--aria-label="state.currentImage.ariaLabel"
[320] Fix | Delete
data-wp-bind--aria-modal="state.ariaModal"
[321] Fix | Delete
data-wp-class--active="state.overlayEnabled"
[322] Fix | Delete
data-wp-class--show-closing-animation="state.overlayOpened"
[323] Fix | Delete
data-wp-watch="callbacks.setOverlayFocus"
[324] Fix | Delete
data-wp-on--keydown="actions.handleKeydown"
[325] Fix | Delete
data-wp-on--touchstart="actions.handleTouchStart"
[326] Fix | Delete
data-wp-on--touchmove="actions.handleTouchMove"
[327] Fix | Delete
data-wp-on--touchend="actions.handleTouchEnd"
[328] Fix | Delete
data-wp-on--click="actions.hideLightbox"
[329] Fix | Delete
data-wp-on-window--resize="callbacks.setOverlayStyles"
[330] Fix | Delete
data-wp-on-window--scroll="actions.handleScroll"
[331] Fix | Delete
data-wp-bind--style="state.overlayStyles"
[332] Fix | Delete
tabindex="-1"
[333] Fix | Delete
>
[334] Fix | Delete
<button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button">
[335] Fix | Delete
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false"><path d="m13.06 12 6.47-6.47-1.06-1.06L12 10.94 5.53 4.47 4.47 5.53 10.94 12l-6.47 6.47 1.06 1.06L12 13.06l6.47 6.47 1.06-1.06L13.06 12Z"></path></svg>
[336] Fix | Delete
</button>
[337] Fix | Delete
<div class="lightbox-image-container">
[338] Fix | Delete
<figure data-wp-bind--class="state.currentImage.figureClassNames" data-wp-bind--style="state.figureStyles">
[339] Fix | Delete
<img data-wp-bind--alt="state.currentImage.alt" data-wp-bind--class="state.currentImage.imgClassNames" data-wp-bind--style="state.imgStyles" data-wp-bind--src="state.currentImage.currentSrc">
[340] Fix | Delete
</figure>
[341] Fix | Delete
</div>
[342] Fix | Delete
<div class="lightbox-image-container">
[343] Fix | Delete
<figure data-wp-bind--class="state.currentImage.figureClassNames" data-wp-bind--style="state.figureStyles">
[344] Fix | Delete
<img data-wp-bind--alt="state.currentImage.alt" data-wp-bind--class="state.currentImage.imgClassNames" data-wp-bind--style="state.imgStyles" data-wp-bind--src="state.enlargedSrc">
[345] Fix | Delete
</figure>
[346] Fix | Delete
</div>
[347] Fix | Delete
<div class="scrim" style="background-color: $background_color" aria-hidden="true"></div>
[348] Fix | Delete
</div>
[349] Fix | Delete
HTML;
[350] Fix | Delete
}
[351] Fix | Delete
[352] Fix | Delete
/**
[353] Fix | Delete
* Registers the `core/image` block on server.
[354] Fix | Delete
*
[355] Fix | Delete
* @since 5.9.0
[356] Fix | Delete
*/
[357] Fix | Delete
function register_block_core_image() {
[358] Fix | Delete
register_block_type_from_metadata(
[359] Fix | Delete
__DIR__ . '/image',
[360] Fix | Delete
array(
[361] Fix | Delete
'render_callback' => 'render_block_core_image',
[362] Fix | Delete
)
[363] Fix | Delete
);
[364] Fix | Delete
}
[365] Fix | Delete
add_action( 'init', 'register_block_core_image' );
[366] Fix | Delete
[367] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function