@@ -139,79 +139,139 @@ function auto_sizes_get_width( string $layout_width, int $image_width ): string
139
139
}
140
140
141
141
/**
142
- * Filter the sizes attribute for images to improve the default calculation .
142
+ * Primes attachment into the cache with a single database query .
143
143
*
144
- * @since 1.1.0
144
+ * @since n.e.x.t
145
145
*
146
- * @param string $content The block content about to be rendered.
147
- * @param array{ attrs?: array{ align?: string, width?: string } } $parsed_block The parsed block.
148
- * @return string The updated block content.
146
+ * @param string|mixed $content The HTML content.
147
+ * @return string The HTML content.
149
148
*/
150
- function auto_sizes_filter_image_tag ( string $ content , array $ parsed_block ): string {
149
+ function auto_sizes_prime_attachment_caches ( $ content ): string {
150
+ if ( ! is_string ( $ content ) ) {
151
+ return '' ;
152
+ }
153
+
151
154
$ processor = new WP_HTML_Tag_Processor ( $ content );
152
- $ has_image = $ processor ->next_tag ( array ( 'tag_name ' => 'img ' ) );
153
155
154
- // Only update the markup if an image is found.
155
- if ( $ has_image ) {
156
- $ processor ->set_attribute ( 'data-needs-sizes-update ' , true );
157
- if ( isset ( $ parsed_block ['attrs ' ]['align ' ] ) ) {
158
- $ processor ->set_attribute ( 'data-align ' , $ parsed_block ['attrs ' ]['align ' ] );
156
+ $ images = array ();
157
+ while ( $ processor ->next_tag ( array ( 'tag_name ' => 'IMG ' ) ) ) {
158
+ $ class = $ processor ->get_attribute ( 'class ' );
159
+
160
+ if ( ! is_string ( $ class ) ) {
161
+ continue ;
159
162
}
160
163
161
- // Resize image width.
162
- if ( isset ( $ parsed_block ['attrs ' ]['width ' ] ) ) {
163
- $ processor ->set_attribute ( 'data-resize-width ' , $ parsed_block ['attrs ' ]['width ' ] );
164
+ if ( preg_match ( '/(?:^|\s)wp-image-([1-9][0-9]*)(?:\s|$)/ ' , $ class , $ class_id ) === 1 ) {
165
+ $ attachment_id = (int ) $ class_id [1 ];
166
+ if ( $ attachment_id > 0 ) {
167
+ $ images [] = $ attachment_id ;
168
+ }
164
169
}
170
+ }
171
+
172
+ // Reduce the array to unique attachment IDs.
173
+ $ attachment_ids = array_unique ( $ images );
165
174
166
- $ content = $ processor ->get_updated_html ();
175
+ if ( count ( $ attachment_ids ) > 1 ) {
176
+ /*
177
+ * Warm the object cache with post and meta information for all found
178
+ * images to avoid making individual database calls.
179
+ */
180
+ _prime_post_caches ( $ attachment_ids , false , true );
167
181
}
182
+
168
183
return $ content ;
169
184
}
170
- add_filter ( 'render_block_core/image ' , 'auto_sizes_filter_image_tag ' , 10 , 2 );
171
- add_filter ( 'render_block_core/cover ' , 'auto_sizes_filter_image_tag ' , 10 , 2 );
185
+
186
+ // This must run before 'do_blocks', which runs at priority 9.
187
+ add_filter ( 'the_content ' , 'auto_sizes_prime_attachment_caches ' , 9 );
172
188
173
189
/**
174
190
* Filter the sizes attribute for images to improve the default calculation.
175
191
*
176
192
* @since 1.1.0
177
193
*
178
- * @param string $content The block content about to be rendered.
194
+ * @param string|mixed $content The block content about to be rendered.
195
+ * @param array{ attrs?: array{ align?: string, width?: string } } $parsed_block The parsed block.
196
+ * @param WP_Block $block Block instance.
179
197
* @return string The updated block content.
180
198
*/
181
- function auto_sizes_improve_image_sizes_attributes ( string $ content ): string {
182
- $ processor = new WP_HTML_Tag_Processor ( $ content );
183
- if ( ! $ processor ->next_tag ( array ( 'tag_name ' => 'img ' ) ) ) {
184
- return $ content ;
199
+ function auto_sizes_filter_image_tag ( $ content , array $ parsed_block , WP_Block $ block ): string {
200
+ if ( ! is_string ( $ content ) ) {
201
+ return '' ;
185
202
}
203
+ $ processor = new WP_HTML_Tag_Processor ( $ content );
204
+ $ has_image = $ processor ->next_tag ( array ( 'tag_name ' => 'IMG ' ) );
186
205
187
- $ remove_data_attributes = static function () use ( $ processor ): void {
188
- $ processor ->remove_attribute ( 'data-needs-sizes-update ' );
189
- $ processor ->remove_attribute ( 'data-align ' );
190
- $ processor ->remove_attribute ( 'data-resize-width ' );
191
- };
206
+ // Only update the markup if an image is found.
207
+ if ( $ has_image ) {
208
+
209
+ /**
210
+ * Callback for calculating image sizes attribute value for an image block.
211
+ *
212
+ * This is a workaround to use block context data when calculating the img sizes attribute.
213
+ *
214
+ * @param string $sizes The image sizes attribute value.
215
+ * @param string $size The image size data.
216
+ */
217
+ $ filter = static function ( $ sizes , $ size ) use ( $ block ) {
218
+ $ id = $ block ->attributes ['id ' ] ?? 0 ;
219
+ $ alignment = $ block ->attributes ['align ' ] ?? '' ;
220
+ $ width = $ block ->attributes ['width ' ] ?? '' ;
221
+
222
+ return auto_sizes_calculate_better_sizes ( (int ) $ id , (string ) $ size , (string ) $ alignment , (string ) $ width );
223
+ };
224
+
225
+ // Hook this filter early, before default filters are run.
226
+ add_filter ( 'wp_calculate_image_sizes ' , $ filter , 9 , 2 );
227
+
228
+ $ sizes = wp_calculate_image_sizes (
229
+ // If we don't have a size slug, assume the full size was used.
230
+ $ parsed_block ['attrs ' ]['sizeSlug ' ] ?? 'full ' ,
231
+ null ,
232
+ null ,
233
+ $ parsed_block ['attrs ' ]['id ' ] ?? 0
234
+ );
235
+
236
+ remove_filter ( 'wp_calculate_image_sizes ' , $ filter , 9 );
237
+
238
+ // Bail early if sizes are not calculated.
239
+ if ( false === $ sizes ) {
240
+ return $ content ;
241
+ }
242
+
243
+ $ processor ->set_attribute ( 'sizes ' , $ sizes );
192
244
193
- // Bail early if the responsive images are disabled.
194
- if ( null === $ processor ->get_attribute ( 'sizes ' ) ) {
195
- $ remove_data_attributes ();
196
245
return $ processor ->get_updated_html ();
197
246
}
198
247
199
- // Skips second time parsing if already processed.
200
- if ( null === $ processor ->get_attribute ( 'data-needs-sizes-update ' ) ) {
201
- return $ content ;
202
- }
248
+ return $ content ;
249
+ }
250
+ add_filter ( 'render_block_core/image ' , 'auto_sizes_filter_image_tag ' , 10 , 3 );
251
+ add_filter ( 'render_block_core/cover ' , 'auto_sizes_filter_image_tag ' , 10 , 3 );
252
+
253
+ /**
254
+ * Modifies the sizes attribute of an image based on layout context.
255
+ *
256
+ * @param int $id The image id.
257
+ * @param string $size The image size data.
258
+ * @param string $align The image alignment.
259
+ * @param string $resize_width Resize image width.
260
+ * @return string The sizes attribute value.
261
+ */
262
+ function auto_sizes_calculate_better_sizes ( int $ id , string $ size , string $ align , string $ resize_width ): string {
263
+ $ sizes = '' ;
264
+ $ image = wp_get_attachment_image_src ( $ id , $ size );
203
265
204
- $ align = $ processor ->get_attribute ( 'data-align ' );
266
+ if ( false === $ image ) {
267
+ return $ sizes ;
268
+ }
205
269
206
270
// Retrieve width from the image tag itself.
207
- $ image_width = $ processor ->get_attribute ( 'width ' );
208
- if ( ! is_string ( $ image_width ) && ! in_array ( $ align , array ( 'full ' , 'wide ' ), true ) ) {
209
- return $ content ;
210
- }
271
+ $ image_width = '' !== $ resize_width ? (int ) $ resize_width : $ image [1 ];
211
272
212
273
$ layout = wp_get_global_settings ( array ( 'layout ' ) );
213
274
214
- $ sizes = null ;
215
275
// Handle different alignment use cases.
216
276
switch ( $ align ) {
217
277
case 'full ' :
@@ -227,28 +287,16 @@ function auto_sizes_improve_image_sizes_attributes( string $content ): string {
227
287
case 'left ' :
228
288
case 'right ' :
229
289
case 'center ' :
230
- // Resize image width.
231
- $ image_width = $ processor ->get_attribute ( 'data-resize-width ' ) ?? $ image_width ;
232
- $ sizes = sprintf ( '(max-width: %1$dpx) 100vw, %1$dpx ' , $ image_width );
290
+ $ sizes = sprintf ( '(max-width: %1$dpx) 100vw, %1$dpx ' , $ image_width );
233
291
break ;
234
292
235
293
default :
236
294
if ( array_key_exists ( 'contentSize ' , $ layout ) ) {
237
- // Resize image width.
238
- $ image_width = $ processor ->get_attribute ( 'data-resize-width ' ) ?? $ image_width ;
239
- $ width = auto_sizes_get_width ( $ layout ['contentSize ' ], (int ) $ image_width );
240
- $ sizes = sprintf ( '(max-width: %1$s) 100vw, %1$s ' , $ width );
295
+ $ width = auto_sizes_get_width ( $ layout ['contentSize ' ], $ image_width );
296
+ $ sizes = sprintf ( '(max-width: %1$s) 100vw, %1$s ' , $ width );
241
297
}
242
298
break ;
243
299
}
244
300
245
- if ( is_string ( $ sizes ) ) {
246
- $ processor ->set_attribute ( 'sizes ' , $ sizes );
247
- }
248
-
249
- $ remove_data_attributes ();
250
-
251
- return $ processor ->get_updated_html ();
301
+ return $ sizes ;
252
302
}
253
- // Run filter prior to auto sizes "auto_sizes_update_content_img_tag" filter.
254
- add_filter ( 'wp_content_img_tag ' , 'auto_sizes_improve_image_sizes_attributes ' , 9 );
0 commit comments