-
Notifications
You must be signed in to change notification settings - Fork 218
[Product Query] Add support for the Filter Products By Attributes block #7186
Conversation
The release ZIP for this PR is accessible via:
|
Size Change: 0 B Total Size: 992 kB ℹ️ View Unchanged
|
8fe6700
to
166bd49
Compare
166bd49
to
a9fa429
Compare
Product Query - Add support for the Filter By Attributes block
a9fa429
to
926f62c
Compare
…erce/woocommerce-blocks into add/price_filter_support
…erce/woocommerce-blocks into add/attribute_filter_support
…commerce/woocommerce-blocks into add/attribute_filter_support
c771df8
to
0be510e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incredible work! I left a few comments, but nothing major. I just think the code could be slightly improved on the readability side.
src/BlockTypes/ProductQuery.php
Outdated
add_filter( 'query_vars', array( $this, 'set_query_vars' ) ); | ||
// Set this so that our product filters can detect if it's a PHP template. | ||
$this->asset_data_registry->add( 'has_filterable_products', true, true ); | ||
$this->asset_data_registry->add( 'is_rendering_php_template', true, true ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't exactly know how this works, but should we always set this to true
even when not rendering PHP templates? Or should we wrap this into a condition of some sort?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed this in the previous PR #7162
src/BlockTypes/ProductQuery.php
Outdated
'tax_query' => array(), | ||
); | ||
|
||
$queries_attributes = $this->get_queries_by_attributes( $variation_props ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function seems to return a list of queries, right? So perhaps let's call this variable something different? Like $queries_by_attributes
is the obvious one. Or just $custom_queries
.
src/BlockTypes/ProductQuery.php
Outdated
); | ||
|
||
$queries_attributes = $this->get_queries_by_attributes( $variation_props ); | ||
$queries_filters = $this->get_queries_by_applied_filters(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same idea as above. Maybe let's call this $filters_queries
if you wanna keep it similar to this. But AFAIU this returns the queries from the filters, and not filters themselves, right? So it'd be a bit more semantically appropriate, I feel.
src/BlockTypes/ProductQuery.php
Outdated
if ( isset( $query['post__in'] ) ) { | ||
$acc['post__in'] = isset( $acc['post__in'] ) ? array_merge( $acc['post__in'], $query['post__in'] ) : $query['post__in']; | ||
} | ||
// Ignoring the warning of not using meta queries. | ||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query | ||
$acc['meta_query'] = isset( $query['meta_query'] ) ? array_merge( $acc['meta_query'], array( $query['meta_query'] ) ) : $acc['meta_query']; | ||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query | ||
$acc['tax_query'] = isset( $query['tax_query'] ) ? array_merge( $acc['tax_query'], array( $query['tax_query'] ) ) : $acc['tax_query']; | ||
return $acc; | ||
}, | ||
$common_query_values |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest we add post__in
in $common_query_values
as an empty array. In this way we can remove all the ternary operators in this function, I think, making it a bit easier to read. In the end, it's a super simple function, but it looks complicated honestly.
src/BlockTypes/AttributeFilter.php
Outdated
const FILTER_QUERY_VAR = 'filter_'; | ||
const QUERY_TYPE_QUERY_VAR = 'query_type_'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think these need to be part of the AttributeFilter
class? In the end, they only get used by our class, so maybe it makes more sense to move them there? Not sure though. What do you think?
I'd also rename them to something like FILTER_QUERY_VAR_PREFIX
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did the same thing for the `PriceFilter.php≠. These constants indicate the query arguments that are added to the URL when the filters are applied. For me, it makes sense, keeping them scoped with the filters.
src/BlockTypes/ProductQuery.php
Outdated
* @return array | ||
*/ | ||
private function get_filter_by_attributes_query_vars() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are empty lines at the beginning of the functions a thing we do or was this a typo?
src/BlockTypes/ProductQuery.php
Outdated
function( $acc, $attribute ) { | ||
$acc[ $attribute->attribute_name ] = array( | ||
'filter' => AttributeFilter::FILTER_QUERY_VAR . $attribute->attribute_name, | ||
'query_type' => AttributeFilter::QUERY_TYPE_QUERY_VAR . $attribute->attribute_name, | ||
); | ||
return $acc; | ||
}, | ||
array() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably refactor this function as it's own thing. Not so much because it will be reused, but to make things a bit clearer. Like generate_attribute_filters
or something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mmm, I don't see any advantages to creating a dedicated function. This function is pretty easy to understand and also the class is already huge.
src/BlockTypes/ProductQuery.php
Outdated
$attribute_name_value = explode( ',', $attribute_name_value ); | ||
|
||
$acc[] = array( | ||
'taxonomy' => str_replace( AttributeFilter::FILTER_QUERY_VAR, 'pa_', $attribute_name ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does pa_
stand for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question... the pa
is the prefix for custom attributes:
We do a similar thing here
src/BlockTypes/ProductQuery.php
Outdated
$attribute_name_value = get_query_var( $attribute_name ); | ||
$attribute_query_type_value = get_query_var( $attribute_query_type ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd put just $attribute_value
and $attribute_query
.
src/BlockTypes/ProductQuery.php
Outdated
return $acc; | ||
} | ||
|
||
$attribute_name_value = explode( ',', $attribute_name_value ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add some comments as to why we explode it here?
…ocks into add/attribute_filter_support
This PR has been marked as If deemed still relevant, the pr can be kept active by ensuring it's up to date with the main branch and removing the stale label - otherwise it will automatically be closed after 10 days. |
Script Dependencies ReportThe
This comment was automatically generated by the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It works like a charm! I mean… it's exactly the experience we had expected (and I hope we don't decide to go to production with this version), but it works as specced so far.
Thanks for addressing my previous comments. I've left a few more, but they are minor. I'm pre-approving.
$attributes_filter_query_args = array_reduce( | ||
array_values( $this->get_filter_by_attributes_query_vars() ), | ||
function( $acc, $array ) { | ||
return array_merge( array_values( $array ), $acc ); | ||
}, | ||
array() | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks great now, thanks! It helps a lot actually to follow what's the expected shape… until we get TypePHP 😬
return $acc; | ||
} | ||
|
||
// It is necessary explode the value because $attribute_value can be a string with multiple values (e.g. "red,blue"). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this comment!
src/BlockTypes/ProductQuery.php
Outdated
} | ||
|
||
/** | ||
* Intersect arrays when both are not empty, otherwise merge them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a little grammar fix
* Intersect arrays when both are not empty, otherwise merge them. | |
* Intersect arrays when neither of them are empty, otherwise merge them. |
src/BlockTypes/ProductQuery.php
Outdated
* @param array $array1 Array. | ||
* @param array $array2 Array. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You know from the other PR how I feel about these kind of names, but I don't want to be too obnoxious. Again, if we want to keep two args, I'd go for $a
and $b
, but my suggestion would be to mimic the signature of both array_merge
and array_intersect
and accept any number of arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the function. Before merging the PR, I prefer that you take a last check :)
…ocks into add/attribute_filter_support
…commerce/woocommerce-blocks into add/attribute_filter_support
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it! Thank you a lot!
…ck (woocommerce#7186) * Product Query: Fix pagination issue * Product Query - Add support for the Filter By Price Block woocommerce#6790 Product Query - Add support for the Filter By Price Block * fix query relation * fix on sale query * Product Query - Add support for the Filter By Attributes block woocommerce#6790 Product Query - Add support for the Filter By Attributes block * fix bugged pagination and on-sale filter after refactor * address feedback * address feedback
This PR adds support for the Filter By Attributes block. This PR is blocked by #7162.
#6790
Screenshots
Testing
Automated Tests
User Facing Testing
WooCommerce Visibility
Performance Impact
Changelog