@@ -191,6 +191,11 @@ private function process_img( OD_HTML_Tag_Processor $processor, OD_Tag_Visitor_C
191
191
* @return bool Whether the tag should be tracked in URL Metrics.
192
192
*/
193
193
private function process_picture ( OD_HTML_Tag_Processor $ processor , OD_Tag_Visitor_Context $ context ): bool {
194
+ /**
195
+ * First SOURCE tag's attributes.
196
+ *
197
+ * @var array{ srcset: non-empty-string, sizes: string|null, type: non-empty-string }|null $first_source
198
+ */
194
199
$ first_source = null ;
195
200
$ img_xpath = null ;
196
201
@@ -206,20 +211,35 @@ private function process_picture( OD_HTML_Tag_Processor $processor, OD_Tag_Visit
206
211
break ;
207
212
}
208
213
209
- // Collect SOURCE elements.
214
+ // Process the SOURCE elements.
210
215
if ( 'SOURCE ' === $ tag && ! $ processor ->is_tag_closer () ) {
211
- $ media = $ processor ->get_attribute ( 'media ' );
212
- $ type = $ processor ->get_attribute ( 'type ' );
216
+ // Abort processing if the PICTURE involves art direction since then adding a preload link is infeasible.
217
+ if ( null !== $ processor ->get_attribute ( 'media ' ) ) {
218
+ return false ;
219
+ }
220
+
221
+ // Abort processing if a SOURCE lacks the required srcset attribute.
222
+ $ srcset = $ processor ->get_attribute ( 'srcset ' );
223
+ if ( ! is_string ( $ srcset ) ) {
224
+ return false ;
225
+ }
226
+ $ srcset = trim ( $ srcset );
227
+ if ( '' === $ srcset ) {
228
+ return false ;
229
+ }
213
230
214
- // Ensure that all SOURCE elements have a type attribute and no media attribute.
215
- if ( null !== $ media || null === $ type ) {
231
+ // Abort processing if there is no valid image type.
232
+ $ type = $ this ->get_attribute_value ( $ processor , 'type ' );
233
+ if ( ! is_string ( $ type ) || ! str_starts_with ( $ type , 'image/ ' ) ) {
216
234
return false ;
217
235
}
218
236
237
+ // Collect the first valid SOURCE as the preload link.
219
238
if ( null === $ first_source ) {
239
+ $ sizes = $ processor ->get_attribute ( 'sizes ' );
220
240
$ first_source = array (
221
- 'srcset ' => $ processor -> get_attribute ( ' srcset ' ) ,
222
- 'sizes ' => $ processor -> get_attribute ( ' sizes ' ) ,
241
+ 'srcset ' => $ srcset ,
242
+ 'sizes ' => is_string ( $ sizes ) ? $ sizes : null ,
223
243
'type ' => $ type ,
224
244
);
225
245
}
@@ -243,6 +263,7 @@ private function process_picture( OD_HTML_Tag_Processor $processor, OD_Tag_Visit
243
263
}
244
264
}
245
265
266
+ // Abort if we never encountered a SOURCE or IMG tag.
246
267
if ( null === $ img_xpath || null === $ first_source ) {
247
268
return false ;
248
269
}
0 commit comments