6
6
* @since 1.4.0
7
7
*/
8
8
9
+ /*
10
+ * Map alignment values to a weighting value so they can be compared.
11
+ * Note that 'left' and 'right' alignments are only constrained by max alignment.
12
+ */
13
+ const AUTO_SIZES_CONSTRAINTS = array (
14
+ 'full ' => 0 ,
15
+ 'wide ' => 1 ,
16
+ 'left ' => 2 ,
17
+ 'right ' => 2 ,
18
+ 'default ' => 3 ,
19
+ 'center ' => 3 ,
20
+ );
21
+
9
22
/**
10
23
* Primes attachment into the cache with a single database query.
11
24
*
@@ -82,10 +95,11 @@ function auto_sizes_filter_image_tag( $content, array $parsed_block, WP_Block $b
82
95
*/
83
96
$ filter = static function ( $ sizes , $ size ) use ( $ block ) {
84
97
85
- $ id = isset ( $ block ->attributes ['id ' ] ) ? (int ) $ block ->attributes ['id ' ] : 0 ;
86
- $ alignment = $ block ->attributes ['align ' ] ?? '' ;
87
- $ width = isset ( $ block ->attributes ['width ' ] ) ? (int ) $ block ->attributes ['width ' ] : 0 ;
88
- $ max_alignment = $ block ->context ['max_alignment ' ] ?? '' ;
98
+ $ id = isset ( $ block ->attributes ['id ' ] ) ? (int ) $ block ->attributes ['id ' ] : 0 ;
99
+ $ alignment = $ block ->attributes ['align ' ] ?? '' ;
100
+ $ width = isset ( $ block ->attributes ['width ' ] ) ? (int ) $ block ->attributes ['width ' ] : 0 ;
101
+ $ max_alignment = $ block ->context ['max_alignment ' ] ?? '' ;
102
+ $ container_relative_width = $ block ->context ['container_relative_width ' ] ?? 1.0 ;
89
103
90
104
/*
91
105
* Update width for cover block.
@@ -95,7 +109,7 @@ function auto_sizes_filter_image_tag( $content, array $parsed_block, WP_Block $b
95
109
$ size = array ( 420 , 420 );
96
110
}
97
111
98
- $ better_sizes = auto_sizes_calculate_better_sizes ( $ id , $ size , $ alignment , $ width , $ max_alignment );
112
+ $ better_sizes = auto_sizes_calculate_better_sizes ( $ id , $ size , $ alignment , $ width , $ max_alignment, $ container_relative_width );
99
113
100
114
// If better sizes can't be calculated, use the default sizes.
101
115
return false !== $ better_sizes ? $ better_sizes : $ sizes ;
@@ -132,14 +146,15 @@ function auto_sizes_filter_image_tag( $content, array $parsed_block, WP_Block $b
132
146
*
133
147
* @since 1.4.0
134
148
*
135
- * @param int $id The image attachment post ID.
136
- * @param string|array{int, int} $size Image size name or array of width and height.
137
- * @param string $align The image alignment.
138
- * @param int $resize_width Resize image width.
139
- * @param string $max_alignment The maximum usable layout alignment.
149
+ * @param int $id The image attachment post ID.
150
+ * @param string|array{int, int} $size Image size name or array of width and height.
151
+ * @param string $align The image alignment.
152
+ * @param int $resize_width Resize image width.
153
+ * @param string $max_alignment The maximum usable layout alignment.
154
+ * @param float $container_relative_width Container relative width.
140
155
* @return string|false An improved sizes attribute or false if a better size cannot be calculated.
141
156
*/
142
- function auto_sizes_calculate_better_sizes ( int $ id , $ size , string $ align , int $ resize_width , string $ max_alignment ) {
157
+ function auto_sizes_calculate_better_sizes ( int $ id , $ size , string $ align , int $ resize_width , string $ max_alignment, float $ container_relative_width ) {
143
158
// Bail early if not a block theme.
144
159
if ( ! wp_is_block_theme () ) {
145
160
return false ;
@@ -172,18 +187,8 @@ function auto_sizes_calculate_better_sizes( int $id, $size, string $align, int $
172
187
// Normalize default alignment values.
173
188
$ align = '' !== $ align ? $ align : 'default ' ;
174
189
175
- /*
176
- * Map alignment values to a weighting value so they can be compared.
177
- * Note that 'left' and 'right' alignments are only constrained by max alignment.
178
- */
179
- $ constraints = array (
180
- 'full ' => 0 ,
181
- 'wide ' => 1 ,
182
- 'left ' => 2 ,
183
- 'right ' => 2 ,
184
- 'default ' => 3 ,
185
- 'center ' => 3 ,
186
- );
190
+ // Use the defined constant for constraints.
191
+ $ constraints = AUTO_SIZES_CONSTRAINTS ;
187
192
188
193
$ alignment = $ constraints [ $ align ] > $ constraints [ $ max_alignment ] ? $ align : $ max_alignment ;
189
194
@@ -195,6 +200,18 @@ function auto_sizes_calculate_better_sizes( int $id, $size, string $align, int $
195
200
196
201
case 'wide ' :
197
202
$ layout_width = auto_sizes_get_layout_width ( 'wide ' );
203
+ // TODO: Add support for em, rem, vh, and vw.
204
+ if (
205
+ str_ends_with ( $ layout_width , 'px ' ) &&
206
+ ( $ container_relative_width > 0.0 ||
207
+ $ container_relative_width < 1.0 )
208
+ ) {
209
+ // First remove 'px' from width.
210
+ $ layout_width = str_replace ( 'px ' , '' , $ layout_width );
211
+ // Convert to float for better precision.
212
+ $ layout_width = (float ) $ layout_width * $ container_relative_width ;
213
+ $ layout_width = sprintf ( '%dpx ' , (int ) $ layout_width );
214
+ }
198
215
break ;
199
216
200
217
case 'left ' :
@@ -207,8 +224,18 @@ function auto_sizes_calculate_better_sizes( int $id, $size, string $align, int $
207
224
/*
208
225
* If the layout width is in pixels, we can compare against the image width
209
226
* on the server. Otherwise, we need to rely on CSS functions.
227
+ *
228
+ * TODO: Add support for em, rem, vh, and vw.
210
229
*/
211
- if ( str_ends_with ( $ layout_width , 'px ' ) ) {
230
+ if (
231
+ str_ends_with ( $ layout_width , 'px ' ) &&
232
+ ( $ container_relative_width > 0.0 ||
233
+ $ container_relative_width < 1.0 )
234
+ ) {
235
+ // First remove 'px' from width.
236
+ $ layout_width = str_replace ( 'px ' , '' , $ layout_width );
237
+ // Convert to float for better precision.
238
+ $ layout_width = (float ) $ layout_width * $ container_relative_width ;
212
239
$ layout_width = sprintf ( '%dpx ' , min ( (int ) $ layout_width , $ image_width ) );
213
240
} else {
214
241
$ layout_width = sprintf ( 'min(%1$s, %2$spx) ' , $ layout_width , $ image_width );
@@ -255,15 +282,18 @@ function auto_sizes_get_layout_width( string $alignment ): string {
255
282
* @return string[] The filtered context keys used by the block type.
256
283
*/
257
284
function auto_sizes_filter_uses_context ( array $ uses_context , WP_Block_Type $ block_type ): array {
258
- // The list of blocks that can consume outer layout context.
259
- $ consumer_blocks = array (
260
- 'core/cover ' ,
261
- 'core/image ' ,
285
+ // Define block-specific context usage.
286
+ $ block_specific_context = array (
287
+ 'core/cover ' => array ( 'max_alignment ' , 'container_relative_width ' ),
288
+ 'core/image ' => array ( 'max_alignment ' , 'container_relative_width ' ),
289
+ 'core/group ' => array ( 'max_alignment ' ),
290
+ 'core/columns ' => array ( 'max_alignment ' , 'container_relative_width ' ),
291
+ 'core/column ' => array ( 'max_alignment ' , 'column_count ' ),
262
292
);
263
293
264
- if ( in_array ( $ block_type ->name , $ consumer_blocks , true ) ) {
265
- // Use array_values to reset the array keys after merging.
266
- return array_values ( array_unique ( array_merge ( $ uses_context , array ( ' max_alignment ' ) ) ) );
294
+ if ( isset ( $ block_specific_context [ $ block_type ->name ] ) ) {
295
+ // Use array_values to reset array keys after merging.
296
+ return array_values ( array_unique ( array_merge ( $ uses_context , $ block_specific_context [ $ block_type -> name ] ) ) );
267
297
}
268
298
return $ uses_context ;
269
299
}
@@ -273,11 +303,12 @@ function auto_sizes_filter_uses_context( array $uses_context, WP_Block_Type $blo
273
303
*
274
304
* @since 1.4.0
275
305
*
276
- * @param array<string, mixed> $context Current block context.
277
- * @param array<string, mixed> $block The block being rendered.
306
+ * @param array<string, mixed> $context Current block context.
307
+ * @param array<string, mixed> $block The block being rendered.
308
+ * @param WP_Block|null $parent_block If this is a nested block, a reference to the parent block.
278
309
* @return array<string, mixed> Modified block context.
279
310
*/
280
- function auto_sizes_filter_render_block_context ( array $ context , array $ block ): array {
311
+ function auto_sizes_filter_render_block_context ( array $ context , array $ block, ? WP_Block $ parent_block ): array {
281
312
// When no max alignment is set, the maximum is assumed to be 'full'.
282
313
$ context ['max_alignment ' ] = $ context ['max_alignment ' ] ?? 'full ' ;
283
314
@@ -288,15 +319,44 @@ function auto_sizes_filter_render_block_context( array $context, array $block ):
288
319
);
289
320
290
321
if ( in_array ( $ block ['blockName ' ], $ provider_blocks , true ) ) {
291
- $ alignment = $ block ['attrs ' ]['align ' ] ?? '' ;
322
+ // Normalize default alignment values.
323
+ $ alignment = isset ( $ block ['attrs ' ]['align ' ] ) && '' !== $ block ['attrs ' ]['align ' ] ? $ block ['attrs ' ]['align ' ] : 'default ' ;
324
+ // Use the defined constant for constraints.
325
+ $ constraints = AUTO_SIZES_CONSTRAINTS ;
292
326
293
- // If the container block doesn't have alignment, it's assumed to be 'default'.
294
- if ( '' === $ alignment ) {
295
- $ context [ ' max_alignment ' ] = ' default ' ;
296
- } elseif ( 'wide ' === $ alignment ) {
297
- $ context[ ' max_alignment ' ] = ' wide ' ;
298
- }
327
+ $ context [ ' max_alignment ' ] = $ constraints [ $ context [ ' max_alignment ' ] ] > $ constraints [ $ alignment ] ? $ context [ ' max_alignment ' ] : $ alignment ;
328
+ }
329
+
330
+ if ( 'core/columns ' === $ block [ ' blockName ' ] ) {
331
+ // This is a special context key just to pass to the child 'core/column' block.
332
+ $ context [ ' column_count ' ] = count ( $ block [ ' innerBlocks ' ] );
299
333
}
300
334
335
+ if ( 'core/column ' === $ block ['blockName ' ] ) {
336
+ $ found_image_block = wp_get_first_block ( $ block ['innerBlocks ' ], 'core/image ' );
337
+ $ found_cover_block = wp_get_first_block ( $ block ['innerBlocks ' ], 'core/cover ' );
338
+ if ( count ( $ found_image_block ) > 0 || count ( $ found_cover_block ) > 0 ) {
339
+ // Get column width, if explicitly set.
340
+ if ( isset ( $ block ['attrs ' ]['width ' ] ) && '' !== $ block ['attrs ' ]['width ' ] ) {
341
+ $ current_width = floatval ( rtrim ( $ block ['attrs ' ]['width ' ], '% ' ) ) / 100 ;
342
+ } elseif ( isset ( $ parent_block ->context ['column_count ' ] ) && $ parent_block ->context ['column_count ' ] ) {
343
+ // Default to equally divided width if not explicitly set.
344
+ $ current_width = 1.0 / $ parent_block ->context ['column_count ' ];
345
+ } else {
346
+ // Full width fallback.
347
+ $ current_width = 1.0 ;
348
+ }
349
+
350
+ // Multiply with parent's width if available.
351
+ if (
352
+ isset ( $ parent_block ->context ['container_relative_width ' ] ) &&
353
+ ( $ current_width > 0.0 || $ current_width < 1.0 )
354
+ ) {
355
+ $ context ['container_relative_width ' ] = $ parent_block ->context ['container_relative_width ' ] * $ current_width ;
356
+ } else {
357
+ $ context ['container_relative_width ' ] = $ current_width ;
358
+ }
359
+ }
360
+ }
301
361
return $ context ;
302
362
}
0 commit comments