Skip to content

Commit

Permalink
Move docs from phpdoc to docs/hooks.md
Browse files Browse the repository at this point in the history
  • Loading branch information
westonruter committed Feb 16, 2025
1 parent 16a96a4 commit 9722b3c
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 108 deletions.
108 changes: 87 additions & 21 deletions plugins/optimization-detective/docs/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,104 @@

### Action: `od_init` (argument: plugin version)

Fires when the Optimization Detective is initializing. 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.
Fires when the Optimization Detective is initializing.

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:

```php
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';
// ...
} );
```

### Action: `od_register_tag_visitors` (argument: `OD_Tag_Visitor_Registry`)

Fires to register tag visitors before walking over the document to perform optimizations.

For example, to register a new tag visitor that targets `H1` elements:
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 open 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.
- `$url_metrics_id` (`positive-int|null`): The post ID for the `od_url_metrics` post from which the URL Metrics were loaded (if any). For advanced usage.

Note that you are free to call `$processor->next_tag()` in the callback (such as to walk over any child elements)
since the tag processor's cursor will be reset to the tag after the callback finishes.

When a tag visitor sees it is at a relevant open tag (e.g. by checking `$processor->get_tag()`), it can call the
`$context->track_tag()` method to indicate that the tag should be measured during detection. This will cause the
tag to be included among the `elements` in the stored URL Metrics. The element data includes properties such
as `intersectionRatio`, `intersectionRect`, and `boundingClientRect` (provided by an `IntersectionObserver`) as
well as whether the tag is the LCP element (`isLCP`) or LCP element candidate (`isLCPCandidate`). This method
should not be called 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. (In
addition to calling the `$context->track_tag()`, a callback may also return `true` to indicate the tag should be
tracked.)

Here's an example tag visitor that depends on URL Metrics data:

```php
add_action(
'od_register_tag_visitors',
static function ( OD_Tag_Visitor_Registry $registry ) {
$registry->register(
'my-plugin/h1',
static function ( OD_Tag_Visitor_Context $context ): bool {
if ( $context->processor->get_tag() !== 'H1' ) {
return false;
}
// Now optimize based on stored URL Metrics in $context->url_metric_group_collection.
// ...

// Returning true causes the tag to be tracked in URL Metrics. If there is no need
// for this, as in there is no reference to $context->url_metric_group_collection
// in a tag visitor, then this can instead return false.
return true;
}
);
$tag_visitor_registry->register(
'lcp-img-fetchpriority-high',
static function ( OD_Tag_Visitor_Context $context ): void {
if ( $context->processor->get_tag() !== 'IMG' ) {
return; // Tag is not relevant for this tag visitor.
}

// Mark the tag for measurement during detection so it is included among the elements stored in URL Metrics.
$context->track_tag();

// Make sure fetchpriority=high is added to LCP IMG elements based on the captured URL Metrics.
$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' );
}
}
);
````

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:

```php
$tag_visitor_registry->register(
'img-decoding-async',
static function ( OD_Tag_Visitor_Context $context ): bool {
if ( $context->processor->get_tag() !== 'IMG' ) {
return; // 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' );
}
}
);
```

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 real world examples of how tag visitors are used. Registered tag visitors need only be callables, so in addition to providing a closure you may provide a `callable-string` or even a class which has an `__invoke()` method.
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.

### Action: `od_url_metric_stored` (argument: `OD_URL_Metric_Store_Request_Context`)

Expand Down
16 changes: 0 additions & 16 deletions plugins/optimization-detective/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,6 @@ 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.
Expand Down
71 changes: 0 additions & 71 deletions plugins/optimization-detective/optimization.php
Original file line number Diff line number Diff line change
Expand Up @@ -253,77 +253,6 @@ 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 open 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.
* - `$url_metrics_id` (`positive-int|null`): The post ID for the `od_url_metrics` post from which the URL Metrics were loaded (if any). For advanced usage.
*
* Note that you are free to call `$processor->next_tag()` in the callback (such as to walk over any child elements)
* since the tag processor's cursor will be reset to the tag after the callback finishes.
*
* When a tag visitor sees it is at a relevant open tag (e.g. by checking `$processor->get_tag()`), it can call the
* `$context->track_tag()` method to indicate that the tag should be measured during detection. This will cause the
* tag to be included among the `elements` in the stored URL Metrics. The element data includes properties such
* as `intersectionRatio`, `intersectionRect`, and `boundingClientRect` (provided by an `IntersectionObserver`) as
* well as whether the tag is the LCP element (`isLCP`) or LCP element candidate (`isLCPCandidate`). This method
* should not be called 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. (In
* addition to calling the `$context->track_tag()`, a callback may also return `true` to indicate the tag should be
* tracked.)
*
* 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 ): void {
* if ( $context->processor->get_tag() !== 'IMG' ) {
* return; // Tag is not relevant for this tag visitor.
* }
*
* // Mark the tag for measurement during detection so it is included among the elements stored in URL Metrics.
* $context->track_tag();
*
* // Make sure fetchpriority=high is added to LCP IMG elements based on the captured URL Metrics.
* $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' );
* }
* }
* );
*
* 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; // 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' );
* }
* }
* );
*
* 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.
Expand Down

0 comments on commit 9722b3c

Please sign in to comment.