PluginProbe
Gutenberg / 22.3.0
Gutenberg v22.3.0
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / build / scripts / block-library / gallery.php

gallery.php in Gutenberg 22.3.0, at build/scripts/block-library/gallery.php

184 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Server-side rendering of the `core/gallery` block.
4 *
5 * @package WordPress
6 */
7
8 /**
9 * Handles backwards compatibility for Gallery Blocks,
10 * whose images feature a `data-id` attribute.
11 *
12 * Now that the Gallery Block contains inner Image Blocks,
13 * we add a custom `data-id` attribute before rendering the gallery
14 * so that the Image Block can pick it up in its render_callback.
15 *
16 * @since 5.9.0
17 *
18 * @param array $parsed_block The block being rendered.
19 * @return array The migrated block object.
20 */
21 function gutenberg_block_core_gallery_data_id_backcompatibility( $parsed_block ) {
22 if ( 'core/gallery' === $parsed_block['blockName'] ) {
23 foreach ( $parsed_block['innerBlocks'] as $key => $inner_block ) {
24 if ( 'core/image' === $inner_block['blockName'] ) {
25 if ( ! isset( $parsed_block['innerBlocks'][ $key ]['attrs']['data-id'] ) && isset( $inner_block['attrs']['id'] ) ) {
26 $parsed_block['innerBlocks'][ $key ]['attrs']['data-id'] = esc_attr( $inner_block['attrs']['id'] );
27 }
28 }
29 }
30 }
31
32 return $parsed_block;
33 }
34
35 add_filter( 'render_block_data', 'gutenberg_block_core_gallery_data_id_backcompatibility' );
36
37 /**
38 * Renders the `core/gallery` block on the server.
39 *
40 * @since 6.0.0
41 *
42 * @param array $attributes Attributes of the block being rendered.
43 * @param string $content Content of the block being rendered.
44 * @return string The content of the block being rendered.
45 */
46 function gutenberg_block_core_gallery_render( $attributes, $content ) {
47 // Adds a style tag for the --wp--style--unstable-gallery-gap var.
48 // The Gallery block needs to recalculate Image block width based on
49 // the current gap setting in order to maintain the number of flex columns
50 // so a css var is added to allow this.
51
52 $gap = $attributes['style']['spacing']['blockGap'] ?? null;
53 // Skip if gap value contains unsupported characters.
54 // Regex for CSS value borrowed from `safecss_filter_attr`, and used here
55 // because we only want to match against the value, not the CSS attribute.
56 if ( is_array( $gap ) ) {
57 foreach ( $gap as $key => $value ) {
58 // Make sure $value is a string to avoid PHP 8.1 deprecation error in preg_match() when the value is null.
59 $value = is_string( $value ) ? $value : '';
60 $value = $value && preg_match( '%[\\\(&=}]|/\*%', $value ) ? null : $value;
61
62 // Get spacing CSS variable from preset value if provided.
63 if ( is_string( $value ) && str_contains( $value, 'var:preset|spacing|' ) ) {
64 $index_to_splice = strrpos( $value, '|' ) + 1;
65 $slug = _wp_to_kebab_case( substr( $value, $index_to_splice ) );
66 $value = "var(--wp--preset--spacing--$slug)";
67 }
68
69 $gap[ $key ] = $value;
70 }
71 } else {
72 // Make sure $gap is a string to avoid PHP 8.1 deprecation error in preg_match() when the value is null.
73 $gap = is_string( $gap ) ? $gap : '';
74 $gap = $gap && preg_match( '%[\\\(&=}]|/\*%', $gap ) ? null : $gap;
75
76 // Get spacing CSS variable from preset value if provided.
77 if ( is_string( $gap ) && str_contains( $gap, 'var:preset|spacing|' ) ) {
78 $index_to_splice = strrpos( $gap, '|' ) + 1;
79 $slug = _wp_to_kebab_case( substr( $gap, $index_to_splice ) );
80 $gap = "var(--wp--preset--spacing--$slug)";
81 }
82 }
83
84 $unique_gallery_classname = wp_unique_id( 'wp-block-gallery-' );
85 $processed_content = new WP_HTML_Tag_Processor( $content );
86 $processed_content->next_tag();
87 $processed_content->add_class( $unique_gallery_classname );
88
89 // --gallery-block--gutter-size is deprecated. --wp--style--gallery-gap-default should be used by themes that want to set a default
90 // gap on the gallery.
91 $fallback_gap = 'var( --wp--style--gallery-gap-default, var( --gallery-block--gutter-size, var( --wp--style--block-gap, 0.5em ) ) )';
92 $gap_value = $gap ? $gap : $fallback_gap;
93 $gap_column = $gap_value;
94
95 if ( is_array( $gap_value ) ) {
96 $gap_row = isset( $gap_value['top'] ) ? $gap_value['top'] : $fallback_gap;
97 $gap_column = isset( $gap_value['left'] ) ? $gap_value['left'] : $fallback_gap;
98 $gap_value = $gap_row === $gap_column ? $gap_row : $gap_row . ' ' . $gap_column;
99 }
100
101 // The unstable gallery gap calculation requires a real value (such as `0px`) and not `0`.
102 if ( '0' === $gap_column ) {
103 $gap_column = '0px';
104 }
105
106 // Set the CSS variable to the column value, and the `gap` property to the combined gap value.
107 $gallery_styles = array(
108 array(
109 'selector' => ".wp-block-gallery.{$unique_gallery_classname}",
110 'declarations' => array(
111 '--wp--style--unstable-gallery-gap' => $gap_column,
112 'gap' => $gap_value,
113 ),
114 ),
115 );
116
117 gutenberg_style_engine_get_stylesheet_from_css_rules(
118 $gallery_styles,
119 array(
120 'context' => 'block-supports',
121 )
122 );
123
124 // The WP_HTML_Tag_Processor class calls get_updated_html() internally
125 // when the instance is treated as a string, but here we explicitly
126 // convert it to a string.
127 $updated_content = $processed_content->get_updated_html();
128
129 /*
130 * Randomize the order of image blocks. Ideally we should shuffle
131 * the `$parsed_block['innerBlocks']` via the `render_block_data` hook.
132 * However, this hook doesn't apply inner block updates when blocks are
133 * nested.
134 * @todo In the future, if this hook supports updating innerBlocks in
135 * nested blocks, it should be refactored.
136 *
137 * @see: https://github.com/WordPress/gutenberg/pull/58733
138 */
139 if ( empty( $attributes['randomOrder'] ) ) {
140 return $updated_content;
141 }
142
143 // This pattern matches figure elements with the `wp-block-image` class to
144 // avoid the gallery's wrapping `figure` element and extract images only.
145 $pattern = '/<figure[^>]*\bwp-block-image\b[^>]*>.*?<\/figure>/s';
146
147 // Find all Image blocks.
148 preg_match_all( $pattern, $updated_content, $matches );
149 if ( ! $matches ) {
150 return $updated_content;
151 }
152 $image_blocks = $matches[0];
153
154 // Randomize the order of Image blocks.
155 shuffle( $image_blocks );
156 $i = 0;
157 $content = preg_replace_callback(
158 $pattern,
159 static function () use ( $image_blocks, &$i ) {
160 $new_image_block = $image_blocks[ $i ];
161 ++$i;
162 return $new_image_block;
163 },
164 $updated_content
165 );
166
167 return $content;
168 }
169 /**
170 * Registers the `core/gallery` block on server.
171 *
172 * @since 5.9.0
173 */
174 function gutenberg_register_block_core_gallery() {
175 register_block_type_from_metadata(
176 __DIR__ . '/gallery',
177 array(
178 'render_callback' => 'gutenberg_block_core_gallery_render',
179 )
180 );
181 }
182
183 add_action( 'init', 'gutenberg_register_block_core_gallery', 20 );
184