Skip to content

Commit 082bf01

Browse files
authored
Merge pull request #1821 from WordPress/add/track-tag-method
Introduce `OD_Tag_Visitor_Context::track_tag()` method as alternative for returning `true` in tag visitor callback
2 parents b7c4475 + cb89ea6 commit 082bf01

File tree

9 files changed

+197
-8
lines changed

9 files changed

+197
-8
lines changed

plugins/optimization-detective/class-od-tag-visitor-context.php

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
* Context for tag visitors invoked for each tag while walking over a document.
1717
*
1818
* @since 0.4.0
19-
* @access private
2019
*
2120
* @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.
2221
*/
@@ -25,6 +24,7 @@ final class OD_Tag_Visitor_Context {
2524
/**
2625
* HTML tag processor.
2726
*
27+
* @since 0.4.0
2828
* @var OD_HTML_Tag_Processor
2929
* @readonly
3030
*/
@@ -33,6 +33,7 @@ final class OD_Tag_Visitor_Context {
3333
/**
3434
* URL Metric group collection.
3535
*
36+
* @since 0.4.0
3637
* @var OD_URL_Metric_Group_Collection
3738
* @readonly
3839
*/
@@ -41,22 +42,46 @@ final class OD_Tag_Visitor_Context {
4142
/**
4243
* Link collection.
4344
*
45+
* @since 0.4.0
4446
* @var OD_Link_Collection
4547
* @readonly
4648
*/
4749
public $link_collection;
4850

51+
/**
52+
* Visited tag state.
53+
*
54+
* @since n.e.x.t
55+
* @var OD_Visited_Tag_State
56+
*/
57+
private $visited_tag_state;
58+
4959
/**
5060
* Constructor.
5161
*
62+
* @since 0.4.0
63+
*
5264
* @param OD_HTML_Tag_Processor $processor HTML tag processor.
5365
* @param OD_URL_Metric_Group_Collection $url_metric_group_collection URL Metric group collection.
5466
* @param OD_Link_Collection $link_collection Link collection.
67+
* @param OD_Visited_Tag_State $visited_tag_state Visited tag state.
5568
*/
56-
public function __construct( OD_HTML_Tag_Processor $processor, OD_URL_Metric_Group_Collection $url_metric_group_collection, OD_Link_Collection $link_collection ) {
69+
public function __construct( OD_HTML_Tag_Processor $processor, OD_URL_Metric_Group_Collection $url_metric_group_collection, OD_Link_Collection $link_collection, OD_Visited_Tag_State $visited_tag_state ) {
5770
$this->processor = $processor;
5871
$this->url_metric_group_collection = $url_metric_group_collection;
5972
$this->link_collection = $link_collection;
73+
$this->visited_tag_state = $visited_tag_state;
74+
}
75+
76+
/**
77+
* Marks the tag for being tracked in URL Metrics.
78+
*
79+
* Calling this method from a tag visitor has the same effect as a tag visitor returning `true`.
80+
*
81+
* @since n.e.x.t
82+
*/
83+
public function track_tag(): void {
84+
$this->visited_tag_state->track_tag();
6085
}
6186

6287
/**

plugins/optimization-detective/class-od-tag-visitor-registry.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
/**
1616
* Registry for tag visitors invoked for each tag while walking over a document.
1717
*
18-
* @phpstan-type TagVisitorCallback callable( OD_Tag_Visitor_Context ): bool
18+
* @phpstan-type TagVisitorCallback callable( OD_Tag_Visitor_Context ): ( bool | void )
1919
*
2020
* @implements IteratorAggregate<string, TagVisitorCallback>
2121
*
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
/**
3+
* Optimization Detective: OD_Visited_Tag_State class
4+
*
5+
* @package optimization-detective
6+
* @since n.e.x.t
7+
*/
8+
9+
// @codeCoverageIgnoreStart
10+
if ( ! defined( 'ABSPATH' ) ) {
11+
exit; // Exit if accessed directly.
12+
}
13+
// @codeCoverageIgnoreEnd
14+
15+
/**
16+
* State for a tag visitation when visited by tag visitors while walking over a document.
17+
*
18+
* @since n.e.x.t
19+
* @access private
20+
*/
21+
final class OD_Visited_Tag_State {
22+
23+
/**
24+
* Whether the tag should be tracked among the elements in URL Metrics.
25+
*
26+
* @since n.e.x.t
27+
* @var bool
28+
*/
29+
private $should_track_tag;
30+
31+
/**
32+
* Constructor.
33+
*/
34+
public function __construct() {
35+
$this->reset();
36+
}
37+
38+
/**
39+
* Marks the tag for being tracked in URL Metrics.
40+
*
41+
* @since n.e.x.t
42+
*/
43+
public function track_tag(): void {
44+
$this->should_track_tag = true;
45+
}
46+
47+
/**
48+
* Whether the tag should be tracked among the elements in URL Metrics.
49+
*
50+
* @since n.e.x.t
51+
* @return bool Whether tracked.
52+
*/
53+
public function is_tag_tracked(): bool {
54+
return $this->should_track_tag;
55+
}
56+
57+
/**
58+
* Resets state.
59+
*
60+
* This should be called after tag visitors have been invoked on a tag.
61+
*
62+
* @since n.e.x.t
63+
*/
64+
public function reset(): void {
65+
$this->should_track_tag = false;
66+
}
67+
}

plugins/optimization-detective/load.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class_alias( OD_URL_Metric_Group_Collection::class, 'OD_URL_Metrics_Group_Collec
123123
// Optimization logic.
124124
require_once __DIR__ . '/class-od-link-collection.php';
125125
require_once __DIR__ . '/class-od-tag-visitor-registry.php';
126+
require_once __DIR__ . '/class-od-visited-tag-state.php';
126127
require_once __DIR__ . '/class-od-tag-visitor-context.php';
127128
require_once __DIR__ . '/optimization.php';
128129

plugins/optimization-detective/optimization.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ function od_optimize_template_output_buffer( string $buffer ): string {
220220
od_get_url_metric_freshness_ttl()
221221
);
222222
$link_collection = new OD_Link_Collection();
223-
$tag_visitor_context = new OD_Tag_Visitor_Context( $processor, $group_collection, $link_collection );
223+
$visited_tag_state = new OD_Visited_Tag_State();
224+
$tag_visitor_context = new OD_Tag_Visitor_Context( $processor, $group_collection, $link_collection, $visited_tag_state );
224225
$current_tag_bookmark = 'optimization_detective_current_tag';
225226
$visitors = iterator_to_array( $tag_visitor_registry );
226227

@@ -237,8 +238,11 @@ function od_optimize_template_output_buffer( string $buffer ): string {
237238
$processor->set_bookmark( $current_tag_bookmark ); // TODO: Should we break if this returns false?
238239
239240
foreach ( $visitors as $visitor ) {
240-
$cursor_move_count = $processor->get_cursor_move_count();
241-
$tracked_in_url_metrics = $visitor( $tag_visitor_context ) || $tracked_in_url_metrics;
241+
$cursor_move_count = $processor->get_cursor_move_count();
242+
$visitor_return_value = $visitor( $tag_visitor_context );
243+
if ( true === $visitor_return_value ) {
244+
$tracked_in_url_metrics = true;
245+
}
242246

243247
// If the visitor traversed HTML tags, we need to go back to this tag so that in the next iteration any
244248
// relevant tag visitors may apply, in addition to properly setting the data-od-xpath on this tag below.
@@ -248,11 +252,17 @@ function od_optimize_template_output_buffer( string $buffer ): string {
248252
}
249253
$processor->release_bookmark( $current_tag_bookmark );
250254

255+
if ( $visited_tag_state->is_tag_tracked() ) {
256+
$tracked_in_url_metrics = true;
257+
}
258+
251259
if ( $tracked_in_url_metrics && $needs_detection ) {
252260
// TODO: Replace get_stored_xpath with get_xpath once the transitional period is over.
253261
$xpath = $processor->get_stored_xpath();
254262
$processor->set_meta_attribute( 'xpath', $xpath );
255263
}
264+
265+
$visited_tag_state->reset();
256266
} while ( $processor->next_open_tag() );
257267

258268
// Send any preload links in a Link response header and in a LINK tag injected at the end of the HEAD.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<html lang="en">
2+
<head>
3+
<meta charset="utf-8">
4+
<title>...</title>
5+
</head>
6+
<body>
7+
<div id="page">
8+
<div id="not-tracked-by-any"></div>
9+
<div id="tracked-by-return-true"></div>
10+
<div id="tracked-by-track-tag-method"></div>
11+
<div id="tracked-by-return-value-and-track-tag-method"></div>
12+
</div>
13+
</body>
14+
</html>

plugins/optimization-detective/tests/test-cases/tag-track-opt-in/expected.html

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
return static function (): void {
3+
add_action(
4+
'od_register_tag_visitors',
5+
static function ( OD_Tag_Visitor_Registry $registry ): void {
6+
$registry->register(
7+
'not-tracking-anything-return-false',
8+
static function (): bool {
9+
return false;
10+
}
11+
);
12+
13+
$registry->register(
14+
'not-tracking-anything-return-void',
15+
static function ( OD_Tag_Visitor_Context $context ): void {}
16+
);
17+
18+
$registry->register(
19+
'track-by-return-true',
20+
static function ( OD_Tag_Visitor_Context $context ): bool {
21+
return in_array(
22+
$context->processor->get_attribute( 'id' ),
23+
array(
24+
'tracked-by-return-true',
25+
'tracked-by-return-value-and-track-tag-method',
26+
),
27+
true
28+
);
29+
}
30+
);
31+
32+
$registry->register(
33+
'track-by-track-tag-method',
34+
static function ( OD_Tag_Visitor_Context $context ): void {
35+
$should_track = in_array(
36+
$context->processor->get_attribute( 'id' ),
37+
array(
38+
'tracked-by-track-tag-method',
39+
'tracked-by-return-value-and-track-tag-method',
40+
),
41+
true
42+
);
43+
if ( $should_track ) {
44+
$context->track_tag();
45+
}
46+
}
47+
);
48+
}
49+
);
50+
};

plugins/optimization-detective/tests/test-optimization.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,11 @@ public function data_provider_test_od_optimize_template_output_buffer(): array {
337337
* @covers ::od_is_response_html_content_type
338338
* @covers OD_Tag_Visitor_Context::__construct
339339
* @covers OD_Tag_Visitor_Context::__get
340+
* @covers OD_Tag_Visitor_Context::track_tag
341+
* @covers OD_Visited_Tag_State::__construct
342+
* @covers OD_Visited_Tag_State::track_tag
343+
* @covers OD_Visited_Tag_State::is_tag_tracked
344+
* @covers OD_Visited_Tag_State::reset
340345
*
341346
* @dataProvider data_provider_test_od_optimize_template_output_buffer
342347
*
@@ -379,9 +384,11 @@ function ( OD_Tag_Visitor_Context $context ): bool {
379384
function ( OD_Tag_Visitor_Registry $tag_visitor_registry ): void {
380385
$tag_visitor_registry->register(
381386
'video',
382-
function ( OD_Tag_Visitor_Context $context ): bool {
387+
function ( OD_Tag_Visitor_Context $context ): void {
383388
$this->assertFalse( $context->processor->is_tag_closer() );
384-
return $context->processor->get_tag() === 'VIDEO';
389+
if ( $context->processor->get_tag() === 'VIDEO' ) {
390+
$context->track_tag();
391+
}
385392
}
386393
);
387394
}

0 commit comments

Comments
 (0)