31 } |
33 } |
32 |
34 |
33 add_filter( 'render_block_data', 'block_core_gallery_data_id_backcompatibility' ); |
35 add_filter( 'render_block_data', 'block_core_gallery_data_id_backcompatibility' ); |
34 |
36 |
35 /** |
37 /** |
36 * Adds a style tag for the --wp--style--unstable-gallery-gap var. |
38 * Renders the `core/gallery` block on the server. |
37 * |
39 * |
38 * The Gallery block needs to recalculate Image block width based on |
40 * @since 6.0.0 |
39 * the current gap setting in order to maintain the number of flex columns |
|
40 * so a css var is added to allow this. |
|
41 * |
41 * |
42 * @param array $attributes Attributes of the block being rendered. |
42 * @param array $attributes Attributes of the block being rendered. |
43 * @param string $content Content 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. |
44 * @return string The content of the block being rendered. |
45 */ |
45 */ |
46 function block_core_gallery_render( $attributes, $content ) { |
46 function block_core_gallery_render( $attributes, $content ) { |
47 $gap = _wp_array_get( $attributes, array( 'style', 'spacing', 'blockGap' ) ); |
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; |
48 // Skip if gap value contains unsupported characters. |
53 // Skip if gap value contains unsupported characters. |
49 // Regex for CSS value borrowed from `safecss_filter_attr`, and used here |
54 // Regex for CSS value borrowed from `safecss_filter_attr`, and used here |
50 // because we only want to match against the value, not the CSS attribute. |
55 // because we only want to match against the value, not the CSS attribute. |
51 if ( is_array( $gap ) ) { |
56 if ( is_array( $gap ) ) { |
52 foreach ( $gap as $key => $value ) { |
57 foreach ( $gap as $key => $value ) { |
53 $gap[ $key ] = $value && preg_match( '%[\\\(&=}]|/\*%', $value ) ? null : $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; |
54 } |
70 } |
55 } else { |
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 : ''; |
56 $gap = $gap && preg_match( '%[\\\(&=}]|/\*%', $gap ) ? null : $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 } |
57 } |
82 } |
58 |
83 |
59 $class = wp_unique_id( 'wp-block-gallery-' ); |
84 $unique_gallery_classname = wp_unique_id( 'wp-block-gallery-' ); |
60 $content = preg_replace( |
85 $processed_content = new WP_HTML_Tag_Processor( $content ); |
61 '/' . preg_quote( 'class="', '/' ) . '/', |
86 $processed_content->next_tag(); |
62 'class="' . $class . ' ', |
87 $processed_content->add_class( $unique_gallery_classname ); |
63 $content, |
|
64 1 |
|
65 ); |
|
66 |
88 |
67 // --gallery-block--gutter-size is deprecated. --wp--style--gallery-gap-default should be used by themes that want to set a default |
89 // --gallery-block--gutter-size is deprecated. --wp--style--gallery-gap-default should be used by themes that want to set a default |
68 // gap on the gallery. |
90 // gap on the gallery. |
69 $fallback_gap = 'var( --wp--style--gallery-gap-default, var( --gallery-block--gutter-size, var( --wp--style--block-gap, 0.5em ) ) )'; |
91 $fallback_gap = 'var( --wp--style--gallery-gap-default, var( --gallery-block--gutter-size, var( --wp--style--block-gap, 0.5em ) ) )'; |
70 $gap_value = $gap ? $gap : $fallback_gap; |
92 $gap_value = $gap ? $gap : $fallback_gap; |
74 $gap_row = isset( $gap_value['top'] ) ? $gap_value['top'] : $fallback_gap; |
96 $gap_row = isset( $gap_value['top'] ) ? $gap_value['top'] : $fallback_gap; |
75 $gap_column = isset( $gap_value['left'] ) ? $gap_value['left'] : $fallback_gap; |
97 $gap_column = isset( $gap_value['left'] ) ? $gap_value['left'] : $fallback_gap; |
76 $gap_value = $gap_row === $gap_column ? $gap_row : $gap_row . ' ' . $gap_column; |
98 $gap_value = $gap_row === $gap_column ? $gap_row : $gap_row . ' ' . $gap_column; |
77 } |
99 } |
78 |
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 |
79 // Set the CSS variable to the column value, and the `gap` property to the combined gap value. |
106 // Set the CSS variable to the column value, and the `gap` property to the combined gap value. |
80 $style = '.' . $class . '{ --wp--style--unstable-gallery-gap: ' . $gap_column . '; gap: ' . $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 ); |
81 |
116 |
82 // Ideally styles should be loaded in the head, but blocks may be parsed |
117 wp_style_engine_get_stylesheet_from_css_rules( |
83 // after that, so loading in the footer for now. |
118 $gallery_styles, |
84 // See https://core.trac.wordpress.org/ticket/53494. |
119 array( |
85 add_action( |
120 'context' => 'block-supports', |
86 'wp_footer', |
121 ) |
87 function () use ( $style ) { |
122 ); |
88 echo '<style> ' . $style . '</style>'; |
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>/'; |
|
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; |
89 }, |
163 }, |
90 11 |
164 $updated_content |
91 ); |
165 ); |
|
166 |
92 return $content; |
167 return $content; |
93 } |
168 } |
94 /** |
169 /** |
95 * Registers the `core/gallery` block on server. |
170 * Registers the `core/gallery` block on server. |
|
171 * |
|
172 * @since 5.9.0 |
96 */ |
173 */ |
97 function register_block_core_gallery() { |
174 function register_block_core_gallery() { |
98 register_block_type_from_metadata( |
175 register_block_type_from_metadata( |
99 __DIR__ . '/gallery', |
176 __DIR__ . '/gallery', |
100 array( |
177 array( |