Skip to content

Commit 3ac0253

Browse files
committed
Merge branch 'trunk' of https://github.com/WordPress/performance into add/external-bg-preload
2 parents b8b79de + d13f33c commit 3ac0253

File tree

8 files changed

+375
-45
lines changed

8 files changed

+375
-45
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
return array(
3+
'set_up' => static function ( Test_Image_Prioritizer_Helper $test_case ): void {
4+
$breakpoint_max_widths = array( 480, 600, 782 );
5+
6+
add_filter(
7+
'od_breakpoint_max_widths',
8+
static function () use ( $breakpoint_max_widths ) {
9+
return $breakpoint_max_widths;
10+
}
11+
);
12+
13+
OD_URL_Metrics_Post_Type::store_url_metric(
14+
od_get_url_metrics_slug( od_get_normalized_query_vars() ),
15+
$test_case->get_sample_url_metric(
16+
array(
17+
'viewport_width' => 375,
18+
'elements' => array(
19+
array(
20+
'xpath' => '/*[1][self::HTML]/*[2][self::BODY]/*[1][self::IMG]',
21+
'isLCP' => true,
22+
),
23+
),
24+
)
25+
)
26+
);
27+
28+
OD_URL_Metrics_Post_Type::store_url_metric(
29+
od_get_url_metrics_slug( od_get_normalized_query_vars() ),
30+
$test_case->get_sample_url_metric(
31+
array(
32+
'viewport_width' => 1000,
33+
'elements' => array(
34+
array(
35+
'xpath' => '/*[1][self::HTML]/*[2][self::BODY]/*[1][self::IMG]',
36+
'isLCP' => true,
37+
),
38+
),
39+
)
40+
)
41+
);
42+
},
43+
'buffer' => '
44+
<html lang="en">
45+
<head>
46+
<meta charset="utf-8">
47+
<title>...</title>
48+
</head>
49+
<body>
50+
<img src="https://example.com/foo.jpg" alt="Foo" width="1200" height="800" fetchpriority="high">
51+
</body>
52+
</html>
53+
',
54+
'expected' => '
55+
<html lang="en">
56+
<head>
57+
<meta charset="utf-8">
58+
<title>...</title>
59+
<link data-od-added-tag rel="preload" fetchpriority="high" as="image" href="https://example.com/foo.jpg" media="screen and (max-width: 480px)">
60+
<link data-od-added-tag rel="preload" fetchpriority="high" as="image" href="https://example.com/foo.jpg" media="screen and (min-width: 783px)">
61+
</head>
62+
<body>
63+
<img data-od-fetchpriority-already-added data-od-xpath="/*[1][self::HTML]/*[2][self::BODY]/*[1][self::IMG]" src="https://example.com/foo.jpg" alt="Foo" width="1200" height="800" fetchpriority="high">
64+
<script type="module">/* import detect ... */</script>
65+
</body>
66+
</html>
67+
',
68+
);

plugins/optimization-detective/class-od-url-metric-group-collection.php

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ public function get_groups_by_lcp_element( string $xpath ): array {
427427
* Gets common LCP element.
428428
*
429429
* @since 0.3.0
430+
* @since n.e.x.t An LCP element is also considered common if it is the same in the narrowest and widest viewport groups, and all intermediate groups are empty.
430431
*
431432
* @return OD_Element|null Common LCP element if it exists.
432433
*/
@@ -437,38 +438,40 @@ public function get_common_lcp_element(): ?OD_Element {
437438

438439
$result = ( function () {
439440

440-
// If every group isn't populated, then we can't say whether there is a common LCP element across every viewport group.
441-
if ( ! $this->is_every_group_populated() ) {
441+
// Ensure both the narrowest (first) and widest (last) viewport groups are populated.
442+
$first_group = $this->get_first_group();
443+
$last_group = $this->get_last_group();
444+
if ( $first_group->count() === 0 || $last_group->count() === 0 ) {
442445
return null;
443446
}
444447

445-
// Look at the LCP elements across all the viewport groups.
446-
$groups_by_lcp_element_xpath = array();
447-
$lcp_elements_by_xpath = array();
448-
$group_has_unknown_lcp_element = false;
449-
foreach ( $this->groups as $group ) {
450-
$lcp_element = $group->get_lcp_element();
451-
if ( $lcp_element instanceof OD_Element ) {
452-
$groups_by_lcp_element_xpath[ $lcp_element->get_xpath() ][] = $group;
453-
$lcp_elements_by_xpath[ $lcp_element->get_xpath() ][] = $lcp_element;
454-
} else {
455-
$group_has_unknown_lcp_element = true;
456-
}
457-
}
448+
$first_group_lcp_element = $first_group->get_lcp_element();
449+
$last_group_lcp_element = $last_group->get_lcp_element();
458450

451+
// Validate LCP elements exist and have matching XPaths in the extreme viewport groups.
459452
if (
460-
// All breakpoints share the same LCP element.
461-
1 === count( $groups_by_lcp_element_xpath )
462-
&&
463-
// The breakpoints don't share a common lack of a detected LCP element.
464-
! $group_has_unknown_lcp_element
453+
! $first_group_lcp_element instanceof OD_Element
454+
||
455+
! $last_group_lcp_element instanceof OD_Element
456+
||
457+
$first_group_lcp_element->get_xpath() !== $last_group_lcp_element->get_xpath()
465458
) {
466-
$xpath = key( $lcp_elements_by_xpath );
459+
return null; // No common LCP element across the narrowest and widest viewports.
460+
}
467461

468-
return $lcp_elements_by_xpath[ $xpath ][0];
462+
// Check intermediate viewport groups for conflicting LCP elements.
463+
foreach ( array_slice( $this->groups, 1, -1 ) as $group ) {
464+
$group_lcp_element = $group->get_lcp_element();
465+
if (
466+
$group_lcp_element instanceof OD_Element
467+
&&
468+
$group_lcp_element->get_xpath() !== $first_group_lcp_element->get_xpath()
469+
) {
470+
return null; // Conflicting LCP element found in an intermediate group.
471+
}
469472
}
470473

471-
return null;
474+
return $first_group_lcp_element;
472475
} )();
473476

474477
$this->result_cache[ __FUNCTION__ ] = $result;

plugins/optimization-detective/tests/test-class-od-url-metrics-group-collection.php

Lines changed: 96 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -721,45 +721,119 @@ public function test_get_groups_by_lcp_element(): void {
721721
$this->assertNull( $group_collection->get_common_lcp_element() );
722722
}
723723

724+
/**
725+
* Data provider.
726+
*
727+
* @return array<string, mixed>
728+
*/
729+
public function data_provider_test_get_common_lcp_element(): array {
730+
$xpath1 = '/*[1][self::HTML]/*[2][self::BODY]/*[1][self::IMG]/*[1]';
731+
$xpath2 = '/*[1][self::HTML]/*[2][self::BODY]/*[1][self::IMG]/*[2]';
732+
733+
$get_sample_url_metric = function ( int $viewport_width, string $lcp_element_xpath, bool $is_lcp = true ): OD_URL_Metric {
734+
return $this->get_sample_url_metric(
735+
array(
736+
'viewport_width' => $viewport_width,
737+
'element' => array(
738+
'isLCP' => $is_lcp,
739+
'xpath' => $lcp_element_xpath,
740+
),
741+
)
742+
);
743+
};
744+
745+
return array(
746+
'all_groups_have_common_lcp' => array(
747+
'url_metrics' => array(
748+
$get_sample_url_metric( 400, $xpath1 ),
749+
$get_sample_url_metric( 600, $xpath1 ),
750+
$get_sample_url_metric( 1000, $xpath1 ),
751+
),
752+
'expected' => $xpath1,
753+
),
754+
'no_url_metrics' => array(
755+
'url_metrics' => array(),
756+
'expected' => null,
757+
),
758+
'empty_first_group' => array(
759+
'url_metrics' => array(
760+
$get_sample_url_metric( 600, $xpath1 ),
761+
$get_sample_url_metric( 1000, $xpath1 ),
762+
),
763+
'expected' => null,
764+
),
765+
'empty_last_group' => array(
766+
'url_metrics' => array(
767+
$get_sample_url_metric( 400, $xpath1 ),
768+
$get_sample_url_metric( 600, $xpath1 ),
769+
),
770+
'expected' => null,
771+
),
772+
'first_and_last_common_lcp_others_empty' => array(
773+
'url_metrics' => array(
774+
$get_sample_url_metric( 400, $xpath1 ),
775+
$get_sample_url_metric( 1000, $xpath1 ),
776+
),
777+
'expected' => $xpath1,
778+
),
779+
'intermediate_groups_conflict' => array(
780+
'url_metrics' => array(
781+
$get_sample_url_metric( 400, $xpath1 ),
782+
$get_sample_url_metric( 600, $xpath2 ),
783+
$get_sample_url_metric( 1000, $xpath1 ),
784+
),
785+
'expected' => null,
786+
),
787+
'first_and_last_lcp_mismatch' => array(
788+
'url_metrics' => array(
789+
$get_sample_url_metric( 400, $xpath1 ),
790+
$get_sample_url_metric( 600, $xpath1 ),
791+
$get_sample_url_metric( 1000, $xpath2 ),
792+
),
793+
'expected' => null,
794+
),
795+
'no_lcp_metrics' => array(
796+
'url_metrics' => array(
797+
$get_sample_url_metric( 400, $xpath1, false ),
798+
$get_sample_url_metric( 600, $xpath1, false ),
799+
$get_sample_url_metric( 1000, $xpath1, false ),
800+
),
801+
'expected' => null,
802+
),
803+
);
804+
}
805+
724806
/**
725807
* Test get_common_lcp_element().
726808
*
727809
* @covers ::get_common_lcp_element
810+
*
811+
* @dataProvider data_provider_test_get_common_lcp_element
812+
*
813+
* @param OD_URL_Metric[] $url_metrics URL Metrics.
814+
* @param string|null $expected Expected.
728815
*/
729-
public function test_get_common_lcp_element(): void {
816+
public function test_get_common_lcp_element( array $url_metrics, ?string $expected ): void {
730817
$breakpoints = array( 480, 800 );
731818
$sample_size = 3;
732819
$current_etag = md5( '' );
733820
$group_collection = new OD_URL_Metric_Group_Collection(
734-
array(),
821+
$url_metrics,
735822
$current_etag,
736823
$breakpoints,
737824
$sample_size,
738825
HOUR_IN_SECONDS
739826
);
740827

741-
$lcp_element_xpath = '/*[1][self::HTML]/*[2][self::BODY]/*[1][self::IMG]/*[1]';
742-
743-
foreach ( array_merge( $breakpoints, array( 1000 ) ) as $viewport_width ) {
744-
for ( $i = 0; $i < $sample_size; $i++ ) {
745-
$group_collection->add_url_metric(
746-
$this->get_sample_url_metric(
747-
array(
748-
'viewport_width' => $viewport_width,
749-
'element' => array(
750-
'isLCP' => true,
751-
'xpath' => $lcp_element_xpath,
752-
),
753-
)
754-
)
755-
);
756-
}
757-
}
758-
759828
$this->assertCount( 3, $group_collection );
829+
760830
$common_lcp_element = $group_collection->get_common_lcp_element();
761-
$this->assertInstanceOf( OD_Element::class, $common_lcp_element );
762-
$this->assertSame( $lcp_element_xpath, $common_lcp_element['xpath'] );
831+
if ( is_string( $expected ) ) {
832+
$this->assertInstanceOf( OD_Element::class, $common_lcp_element );
833+
$this->assertSame( $expected, $common_lcp_element->get_xpath() );
834+
} else {
835+
$this->assertNull( $common_lcp_element );
836+
}
763837
}
764838

765839
/**

plugins/webp-uploads/helper.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,17 @@ function webp_uploads_is_fallback_enabled(): bool {
411411
return (bool) get_option( 'perflab_generate_webp_and_jpeg' );
412412
}
413413

414+
/**
415+
* Checks if the `perflab_generate_all_fallback_sizes` option is enabled.
416+
*
417+
* @since n.e.x.t
418+
*
419+
* @return bool Whether the option is enabled. Default is false.
420+
*/
421+
function webp_uploads_should_generate_all_fallback_sizes(): bool {
422+
return (bool) get_option( 'perflab_generate_all_fallback_sizes', 0 );
423+
}
424+
414425
/**
415426
* Retrieves the image URL for a specified MIME type from the attachment metadata.
416427
*

plugins/webp-uploads/hooks.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,3 +806,24 @@ function webp_uploads_opt_in_extra_image_sizes(): void {
806806
}
807807
}
808808
add_action( 'plugins_loaded', 'webp_uploads_opt_in_extra_image_sizes' );
809+
810+
/**
811+
* Enables additional MIME type support for all image sizes based on the generate all fallback sizes settings.
812+
*
813+
* @since n.e.x.t
814+
*
815+
* @param array<string, bool> $allowed_sizes A map of image size names and whether they are allowed to have additional MIME types.
816+
* @return array<string, bool> Modified map of image sizes with additional MIME type support.
817+
*/
818+
function webp_uploads_enable_additional_mime_type_support_for_all_sizes( array $allowed_sizes ): array {
819+
if ( ! webp_uploads_should_generate_all_fallback_sizes() ) {
820+
return $allowed_sizes;
821+
}
822+
823+
foreach ( array_keys( $allowed_sizes ) as $size ) {
824+
$allowed_sizes[ $size ] = true;
825+
}
826+
827+
return $allowed_sizes;
828+
}
829+
add_filter( 'webp_uploads_image_sizes_with_additional_mime_type_support', 'webp_uploads_enable_additional_mime_type_support_for_all_sizes' );

0 commit comments

Comments
 (0)