Switched implementation of variation query parameters in the API from SQL query adjustment to one extra parent query.

This commit is contained in:
Peter Fabian 2018-07-09 17:14:12 +02:00
parent 4a42e2a7fc
commit 2839dba7d2
1 changed files with 39 additions and 57 deletions

View File

@ -258,47 +258,6 @@ class WC_REST_Product_Variations_Controller extends WC_REST_Products_Controller
return apply_filters( "woocommerce_rest_prepare_{$this->post_type}_object", $response, $object, $request );
}
/**
* Update JOIN part of WP_Query with parent table and taxonomies, if needed.
*
* @param string $join JOIN clause from WP_Query.
* @param WP_Query $wp_query WP_Query object.
*
* @return string
*/
public function parent_product_taxonomies_query_join( $join, $wp_query ) {
global $wpdb;
// TODO: add some more checks here, probably only run in case one of the following filters are active:
// category, prod type, visibility, tag, shipping class, attribute; post_type == product_variation.
if ( isset( $wp_query->query_vars['post_parent'] ) && isset( $wp_query->query_vars['meta_query'] )
&& isset( $wp_query->query_vars['post_type'] ) && 'product_variation' === $wp_query->query_vars['post_type'] ) {
$join .= " LEFT JOIN {$wpdb->posts} AS {$this->parent_product_table_name} ON ({$wpdb->posts}.post_parent = {$this->parent_product_table_name}.ID) ";
$join .= $this->clauses['join'];
}
return $join;
}
/**
* Update WHERE part of WP_Query to match parent product with taxonomies, if needed.
*
* @param string $where WHERE clause from WP_Query.
* @param WP_Query $wp_query WP_Query object.
*
* @return string
*/
public function parent_product_taxonomies_query_where( $where, $wp_query ) {
// TODO: add some more checks here, probably only run in case one of the following filters are active:
// category, prod type, visibility, tag, shipping class, attribute; post_type == product_variation.
if ( isset( $wp_query->query_vars['post_parent'] )
&& isset( $wp_query->query_vars['post_type'] ) && 'product_variation' === $wp_query->query_vars['post_type'] ) {
$where .= $this->clauses['where'];
}
return $where;
}
/**
* Prepare objects query.
*
@ -310,32 +269,55 @@ class WC_REST_Product_Variations_Controller extends WC_REST_Products_Controller
$args = parent::prepare_objects_query( $request );
$args['post_parent'] = $request['product_id'];
// TODO: check if WC_Product_Data_Store_CPT::find_matching_product_variation could not be used...
// fix the filtering, otherwise taxonomy is not mapped correctly to variable product.
$taxonomies = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
// maybe do this only if there are taxonomies as categories etc, not attributes and terms?
$query_for_parent = new WP_Query( $args );
$query_for_parent->parse_tax_query( $query_for_parent->query_vars );
$this->clauses = $query_for_parent->tax_query->get_sql( $this->parent_product_table_name, 'ID' );
$parent_query = new WC_REST_Products_Controller();
$parent_request = clone $request;
$parent_request['include'] = array( $request['product_id'] );
// Shipping class can be set separately for variations and parent product. Unlike for attributes, the parent
// does not have all shipping classes of the variations assigned to it, so the parent filtering should ignore
// shipping class.
$parent_request['shipping_class'] = '';
$query_args = $parent_query->prepare_objects_query( $parent_request );
$query_results = $parent_query->get_objects( $query_args );
// this does not work anyway as these are not assigned to variation.
// In case the parent does not fulfil the constraints, no variations should be returned.
if ( 0 === $query_results['total'] ) {
$args['post_parent'] = 0;
}
// Ignore taxonomy queries, as they were already matched against parent (or will be transformed to meta query
// later on).
unset( $args['tax_query'] );
// these properties should filter parent product:
// - product_type, _visibility_, cat, tag, shipping_class
// this will run a bit later.
add_filter( 'posts_where', array( $this, 'parent_product_taxonomies_query_where' ), 10, 2 );
add_filter( 'posts_join', array( $this, 'parent_product_taxonomies_query_join' ), 10, 2 );
$GLOBALS['wpdb']->query( 'SET SESSION SQL_BIG_SELECTS=1' );
// These properties needs to be transformed to meta query.
// Attributes needs to be transformed to meta query, shipping class to taxonomy.
foreach ( $taxonomies as $taxonomy ) {
if ( in_array( $taxonomy['taxonomy'], array( 'product_type', 'product_visibility', 'product_cat', 'product_tag', 'product_shipping_class' ), true ) ) {
// Ignore taxonomies tied to parent product.
if ( in_array( $taxonomy['taxonomy'], array( 'product_type', 'product_visibility', 'product_cat', 'product_tag' ), true ) ) {
continue;
}
// Shipping class can be associated with either the parent or the individual variation.
if ( 'product_shipping_class' === $taxonomy['taxonomy'] ) {
// If requested shipping class is different from parent's shipping class, it's assigned to variation,
// so passing the taxonomy query forward to check against variations.
if ( $query_results['total'] > 0 && $taxonomy['terms'][0] !== $query_results['objects'][0]->get_shipping_class_id() ) {
$args['tax_query'][] = $taxonomy;
continue;
} else {
// In case the request should to return variations with shipping class equal to parent's shipping class,
// there are no records in taxonomy relationship table.
$args['tax_query'][] = array(
'taxonomy' => 'product_shipping_class',
'operator' => 'NOT EXISTS',
);
continue;
}
}
// Attributes switched to meta query.
if ( 'term_id' === $taxonomy['field'] ) {
$terms = wc_get_product_terms( 10, $taxonomy['taxonomy'], array( 'fields' => 'slugs' ) );
$terms = wc_get_product_terms( $request['product_id'], $taxonomy['taxonomy'], array( 'fields' => 'slugs' ) );
$value = isset( $terms[ $taxonomy['terms'][0] ] ) ? $terms[ $taxonomy['terms'][0] ] : null;
} else {
$value = $taxonomy['terms'][0];