From 2892386b74f455fef225c0731f8b6fa7a6dfe699 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 9 Jan 2025 11:55:50 -0800 Subject: [PATCH 1/3] Flesh out inline phpdoc for od_init and od_register_tag_visitors actions --- plugins/optimization-detective/helper.php | 16 +++++ .../optimization-detective/optimization.php | 71 +++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/plugins/optimization-detective/helper.php b/plugins/optimization-detective/helper.php index 27073205d..2159e1874 100644 --- a/plugins/optimization-detective/helper.php +++ b/plugins/optimization-detective/helper.php @@ -19,6 +19,22 @@ function od_initialize_extensions(): void { /** * Fires when extensions to Optimization Detective can be loaded and initialized. * + * This action is useful for loading extension code that depends on Optimization Detective to be running. The version + * of the plugin is passed as the sole argument so that if the required version is not present, the callback can short circuit. + * + * Example: + * + * add_action( 'od_init', function ( string $version ) { + * if ( version_compare( $version, '1.0', '<' ) ) { + * add_action( 'admin_notices', 'my_plugin_warn_optimization_plugin_outdated' ); + * return; + * } + * + * // Bootstrap the Optimization Detective extension. + * require_once __DIR__ . '/functions.php'; + * // ... + * } ); + * * @since 0.7.0 * * @param string $version Optimization Detective version. diff --git a/plugins/optimization-detective/optimization.php b/plugins/optimization-detective/optimization.php index fa72a6194..de5c8c8d2 100644 --- a/plugins/optimization-detective/optimization.php +++ b/plugins/optimization-detective/optimization.php @@ -204,6 +204,77 @@ function od_optimize_template_output_buffer( string $buffer ): string { /** * Fires to register tag visitors before walking over the document to perform optimizations. * + * Once a page has finished rendering and the output buffer is processed, the page contents are loaded into + * an HTML Tag Processor instance. It then iterates over each tag in the document, and at each open tag it will + * invoke all registered tag visitors. A tag visitor is simply a callable (such as a regular function, closure, + * or even a class with an `__invoke` method defined). The tag visitor callback is invoked by passing an instance + * of the `OD_Tag_Visitor_Context` object which includes the following read-only properties: + * + * - `$processor` (`OD_HTML_Tag_Processor`): The processor with the cursor at the current tag. + * - `$url_metric_group_collection` (`OD_URL_Metric_Group_Collection`): The URL Metrics which may include information about the current tag to inform what optimizations the callback performs. + * - `$link_collection` (`OD_Link_Collection`): Collection of links which will be added to the `HEAD` when the page is served. This allows you to add preload links and preconnect links as needed. + * + * Note that you are free to call `next_tag()` in the callback (such as to walk over any child elements) since the + * cursor will be reset to the tag after the callback finishes. + * + * A tag visitor callback returns a boolean value. When it returns `true`, then Optimization Detective will mark the + * tag as needing to be included among the elements stored in URL Metrics. The element data includes properties such + * as intersectionRatio, intersectionRect, and boundingClientRect as well as whether it is the LCP element. If the + * current tag is not relevant for the tag visitor or if the tag visitor callback does not need to query the provided + * `OD_URL_Metric_Group_Collection` instance to apply the desired optimizations, it can just return `false`. An + * element will be tracked in URL Metrics if _any_ tag visitor callback returns `true` when visiting the tag. + * + * Here's an example tag visitor that depends on URL Metrics data: + * + * $tag_visitor_registry->register( + * 'lcp-img-fetchpriority-high', + * static function ( OD_Tag_Visitor_Context $context ): bool { + * if ( $context->processor->get_tag() !== 'IMG' ) { + * return false; // Tag is not relevant for this tag visitor. + * } + * + * // Make sure fetchpriority=high is added to LCP IMG elements. + * $common_lcp_element = $context->url_metric_group_collection->get_common_lcp_element(); + * if ( + * null !== $common_lcp_element + * && + * $common_lcp_element->get_xpath() === $context->processor->get_xpath() + * ) { + * $context->processor->set_attribute( 'fetchpriority', 'high' ); + * } + * + * // Must return true so that the tag is included among the elements stored in URL Metrics. + * return true; + * } + * ); + * + * Please note this implementation of setting `fetchpriority=high` on the LCP `IMG` element is simplified. Please + * see the Image Prioritizer extension for a more robust implementation. + * + * Here's an example tag visitor that does not depend on any URL Metrics data: + * + * $tag_visitor_registry->register( + * 'img-decoding-async', + * static function ( OD_Tag_Visitor_Context $context ): bool { + * if ( $context->processor->get_tag() !== 'IMG' ) { + * return false; // Tag is not relevant for this tag visitor. + * } + * + * // Set the decoding attribute if it is absent. + * if ( null === $context->processor->get_attribute( 'decoding' ) ) { + * $context->processor->set_attribute( 'decoding', 'async' ); + * } + * + * // There's no need to query OD_URL_Metric_Group_Collection, so this element + * // doesn't need to be tracked in URL Metrics and the callback can return false. + * return false; + * } + * ); + * + * Refer to [Image Prioritizer](https://github.com/WordPress/performance/tree/trunk/plugins/image-prioritizer) and + * [Embed Optimizer](https://github.com/WordPress/performance/tree/trunk/plugins/embed-optimizer) for additional + * examples of how tag visitors are used. + * * @since 0.3.0 * * @param OD_Tag_Visitor_Registry $tag_visitor_registry Tag visitor registry. From 9c938e14ac787570b2f91b7168844dae6e7fe234 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 9 Jan 2025 13:06:23 -0800 Subject: [PATCH 2/3] Remove private access tags for public interfaces --- .../class-od-data-validation-exception.php | 1 - plugins/optimization-detective/class-od-element.php | 1 - plugins/optimization-detective/class-od-html-tag-processor.php | 1 - plugins/optimization-detective/class-od-link-collection.php | 1 - plugins/optimization-detective/class-od-tag-visitor-context.php | 1 - plugins/optimization-detective/class-od-tag-visitor-registry.php | 1 - .../class-od-url-metric-group-collection.php | 1 - plugins/optimization-detective/class-od-url-metric-group.php | 1 - plugins/optimization-detective/class-od-url-metric.php | 1 - .../storage/class-od-url-metric-store-request-context.php | 1 - 10 files changed, 10 deletions(-) diff --git a/plugins/optimization-detective/class-od-data-validation-exception.php b/plugins/optimization-detective/class-od-data-validation-exception.php index 2efab6fc9..39539197f 100644 --- a/plugins/optimization-detective/class-od-data-validation-exception.php +++ b/plugins/optimization-detective/class-od-data-validation-exception.php @@ -15,6 +15,5 @@ * Exception thrown when failing to validate URL Metrics data. * * @since 0.1.0 - * @access private */ final class OD_Data_Validation_Exception extends Exception {} diff --git a/plugins/optimization-detective/class-od-element.php b/plugins/optimization-detective/class-od-element.php index c7f243d99..b08da9272 100644 --- a/plugins/optimization-detective/class-od-element.php +++ b/plugins/optimization-detective/class-od-element.php @@ -20,7 +20,6 @@ * @todo The above implements tag should account for additional undefined keys which can be supplied by extending the element schema. May depend on . * * @since 0.7.0 - * @access private */ class OD_Element implements ArrayAccess, JsonSerializable { diff --git a/plugins/optimization-detective/class-od-html-tag-processor.php b/plugins/optimization-detective/class-od-html-tag-processor.php index 48ad11d12..8f2c23a5c 100644 --- a/plugins/optimization-detective/class-od-html-tag-processor.php +++ b/plugins/optimization-detective/class-od-html-tag-processor.php @@ -15,7 +15,6 @@ * Extension to WP_HTML_Tag_Processor that supports injecting HTML and obtaining XPath for the current tag. * * @since 0.1.1 - * @access private */ final class OD_HTML_Tag_Processor extends WP_HTML_Tag_Processor { diff --git a/plugins/optimization-detective/class-od-link-collection.php b/plugins/optimization-detective/class-od-link-collection.php index 4e41a7af7..33eef580a 100644 --- a/plugins/optimization-detective/class-od-link-collection.php +++ b/plugins/optimization-detective/class-od-link-collection.php @@ -36,7 +36,6 @@ * * @since 0.3.0 * @since 0.4.0 Renamed from OD_Preload_Link_Collection. - * @access private */ final class OD_Link_Collection implements Countable { diff --git a/plugins/optimization-detective/class-od-tag-visitor-context.php b/plugins/optimization-detective/class-od-tag-visitor-context.php index 4dd1279f5..01dcde5a0 100644 --- a/plugins/optimization-detective/class-od-tag-visitor-context.php +++ b/plugins/optimization-detective/class-od-tag-visitor-context.php @@ -15,7 +15,6 @@ * Context for tag visitors invoked for each tag while walking over a document. * * @since 0.4.0 - * @access private * * @property-read OD_URL_Metric_Group_Collection $url_metrics_group_collection Deprecated property accessed via magic getter. Use the url_metric_group_collection property instead. */ diff --git a/plugins/optimization-detective/class-od-tag-visitor-registry.php b/plugins/optimization-detective/class-od-tag-visitor-registry.php index e6b57527c..bb16696bc 100644 --- a/plugins/optimization-detective/class-od-tag-visitor-registry.php +++ b/plugins/optimization-detective/class-od-tag-visitor-registry.php @@ -19,7 +19,6 @@ * @implements IteratorAggregate * * @since 0.3.0 - * @access private */ final class OD_Tag_Visitor_Registry implements Countable, IteratorAggregate { diff --git a/plugins/optimization-detective/class-od-url-metric-group-collection.php b/plugins/optimization-detective/class-od-url-metric-group-collection.php index 56d257402..7879473b9 100644 --- a/plugins/optimization-detective/class-od-url-metric-group-collection.php +++ b/plugins/optimization-detective/class-od-url-metric-group-collection.php @@ -17,7 +17,6 @@ * @implements IteratorAggregate * * @since 0.1.0 - * @access private */ final class OD_URL_Metric_Group_Collection implements Countable, IteratorAggregate, JsonSerializable { diff --git a/plugins/optimization-detective/class-od-url-metric-group.php b/plugins/optimization-detective/class-od-url-metric-group.php index 1e81641fd..6f6a46f0f 100644 --- a/plugins/optimization-detective/class-od-url-metric-group.php +++ b/plugins/optimization-detective/class-od-url-metric-group.php @@ -17,7 +17,6 @@ * @implements IteratorAggregate * * @since 0.1.0 - * @access private */ final class OD_URL_Metric_Group implements IteratorAggregate, Countable, JsonSerializable { diff --git a/plugins/optimization-detective/class-od-url-metric.php b/plugins/optimization-detective/class-od-url-metric.php index 0a164edc9..fda24ac51 100644 --- a/plugins/optimization-detective/class-od-url-metric.php +++ b/plugins/optimization-detective/class-od-url-metric.php @@ -46,7 +46,6 @@ * } * * @since 0.1.0 - * @access private */ class OD_URL_Metric implements JsonSerializable { diff --git a/plugins/optimization-detective/storage/class-od-url-metric-store-request-context.php b/plugins/optimization-detective/storage/class-od-url-metric-store-request-context.php index 8d89872ab..718154798 100644 --- a/plugins/optimization-detective/storage/class-od-url-metric-store-request-context.php +++ b/plugins/optimization-detective/storage/class-od-url-metric-store-request-context.php @@ -15,7 +15,6 @@ * Context for when a URL Metric is successfully stored via the REST API. * * @since 0.7.0 - * @access private */ final class OD_URL_Metric_Store_Request_Context { From 32a95ab68fef18e9bda385b7de708f08ea1341ae Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 9 Jan 2025 13:06:41 -0800 Subject: [PATCH 3/3] Remove redundant private access tags --- .../optimization-detective/storage/class-od-storage-lock.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/optimization-detective/storage/class-od-storage-lock.php b/plugins/optimization-detective/storage/class-od-storage-lock.php index d9c0d85dc..186dd9189 100644 --- a/plugins/optimization-detective/storage/class-od-storage-lock.php +++ b/plugins/optimization-detective/storage/class-od-storage-lock.php @@ -23,7 +23,6 @@ final class OD_Storage_Lock { * Gets the TTL (in seconds) for the URL Metric storage lock. * * @since 0.1.0 - * @access private * * @return int TTL in seconds, greater than or equal to zero. A value of zero means that the storage lock should be disabled and thus that transients must not be used. */ @@ -65,7 +64,6 @@ public static function get_transient_key(): string { * seconds. Otherwise, if the current TTL is zero, then any transient is deleted. * * @since 0.1.0 - * @access private */ public static function set_lock(): void { $ttl = self::get_ttl(); @@ -81,7 +79,6 @@ public static function set_lock(): void { * Checks whether URL Metric storage is locked (for the current IP). * * @since 0.1.0 - * @access private * * @return bool Whether locked. */