Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce OD_Element class and improve PHP API #1585

Merged
merged 21 commits into from
Oct 18, 2024
Merged

Conversation

westonruter
Copy link
Member

@westonruter westonruter commented Oct 9, 2024

See https://github.com/WordPress/performance/pull/1373/files#r1792652840:

See note below on the get_all_denormalized_elements() method that I'd like to instead have $element be an OD_Element class instance which has a $url_metric property to access the OD_URL_Metric instance if is a part of. In the same way, the OD_URL_Metric class can have a $group property to indicate the OD_URL_Metric_Group it is a part of. This would eliminate the need to pass back an array of tuples and instead. So instead, to get the $group this code could do $element->url_metric->group.

The OD_Element class implements ArrayAccess so it is fully backwards-compatible with using values as arrays. So where existing plugins may do $element['isLCP'] this will still continue to work, although $element->is_lcp() would now be preferable. There is also a $element->get() method which allows accessing extended element data. This is closely related to #1492 which did the same for OD_URL_Metric.

@westonruter westonruter added the [Plugin] Optimization Detective Issues for the Optimization Detective plugin label Oct 9, 2024
*/
public function get_all_denormalized_elements(): array {
public function get_all_elements(): array {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like the get_all_elements name. It's more like get_elements_grouped_by_xpath.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about get_all_elements_by_xpath()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works, but then it would seem like you could pass an $xpath to get just the elements with the given XPath.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like document.getElementById()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair, though I'm not sure how including the word grouped would clarify that. FWIW to me that all helps to clarify this will return "all" elements, not just the elements filtered by something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about get_xpath_elements_map()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 98d3fd8

@westonruter westonruter added the [Type] Enhancement A suggestion for improvement of an existing feature label Oct 9, 2024
Base automatically changed from add/embed-optimizer-min-height-reservation to trunk October 14, 2024 17:38
@westonruter westonruter marked this pull request as ready for review October 16, 2024 21:09
Copy link

github-actions bot commented Oct 16, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: westonruter <[email protected]>
Co-authored-by: felixarntz <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@westonruter
Copy link
Member Author

@felixarntz Thoughts on this?

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@westonruter This looks great so far. Only a few points of feedback.

Comment on lines 219 to 233
$resized_bounding_client_rect = $element->get( 'resizedBoundingClientRect' );
if ( ! is_array( $resized_bounding_client_rect ) ) {
continue;
}
$group = $element->url_metric->group;
$group_min_width = $group->get_minimum_viewport_width();
if ( ! isset( $minimums[ $group_min_width ] ) ) {
$minimums[ $group_min_width ] = array(
'group' => $group,
'height' => $element['resizedBoundingClientRect']['height'],
'height' => $resized_bounding_client_rect['height'],
);
} else {
$minimums[ $group_min_width ]['height'] = min(
$minimums[ $group_min_width ]['height'],
$element['resizedBoundingClientRect']['height']
$resized_bounding_client_rect['height']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious: Wouldn't all this marked code also have worked in the way it was before this change, given OD_Element implements ArrayAccess?

Copy link
Member Author

@westonruter westonruter Oct 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it would have worked the same. I made this change because of a PHPStan issue where attempting to access $element['resizedBoundingClientRect']['height'] results in a PHPStan error:

phpstan: Cannot access offset 'height' on array{width: float, height: float, x: float, y: float, top: float, right: float, bottom: float, left: float}|bool|float|non-empty-string.

PHPStan isn't constraining the type based on the type of $element['resizedBoundingClientRect'] based on the key resizedBoundingClientRect so the possible types are a union of all values in ElementData, which also doesn't necessarily include this extended resizedBoundingClientRect key's type (although here it is a DOMRect).

This goes back to wanting to be able to provide richer typing in PHPStan for getters like this, but in the meantime resorting to using OD_Element::get() which returns mixed and then checking the return value as being an array avoids the PHPStan error.

Although I'm a bit surprised it's not complaining that the $resized_bounding_client_rect['height'] key may not be defined since if I do PHPStan\dumpType($resized_bounding_client_rect) it is typed as just array. But this appears to be as expected: https://phpstan.org/r/bc084e48-691a-4232-be15-7b806fda8b3e. I recall there was some PHPStan extension to make checks even more strict than strict rules mandate all array keys be checked as well, but I can't find how to do that off hand.

plugins/optimization-detective/class-od-element.php Outdated Show resolved Hide resolved
plugins/optimization-detective/class-od-element.php Outdated Show resolved Hide resolved
*/
public function get_all_denormalized_elements(): array {
public function get_all_elements(): array {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about get_all_elements_by_xpath()?

* @var OD_URL_Metric
* @readonly
*/
public $url_metric;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not use a public property, as we wouldn't want this to be writable (the annotation is not enough). Can you instead add e.g. a get_url_metric() method? For convenience, you may even want to add a get_url_metric_group() or get_group() method as a shorthand, given that $group was previously easily accessible in the return value of the get_all_denormalized_elements() method.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the public $group property on OD_URL_Metric? It has to be mutable since \OD_URL_Metric_Group::add_url_metric() needs to be able to assign it to the group when it is added.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must have missed that one before. Better to use a setter then for OD_URL_Metric::$group.

For this one though, would we even need to set it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I don't think there is a need for a set_url_metric(). I'll add a getter for both and a setter for one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 344d6e1

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@westonruter Thanks, LGTM!

@westonruter westonruter merged commit 810673d into trunk Oct 18, 2024
13 checks passed
@westonruter westonruter deleted the add/od-element-class branch October 18, 2024 15:43
@westonruter westonruter changed the title Introduce OD_Element class Introduce OD_Element class and improve PHP API Oct 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Plugin] Optimization Detective Issues for the Optimization Detective plugin [Type] Enhancement A suggestion for improvement of an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants