Automattic\WooCommerce\StoreApi\Utilities

ProductQuery::prepare_objects_query()publicWC 1.0

Prepare query args to pass to WP_Query for a REST API request.

Method of the class: ProductQuery{}

No Hooks.

Return

Array.

Usage

$ProductQuery = new ProductQuery();
$ProductQuery->prepare_objects_query( $request );
$request(\WP_REST_Request) (required)
Request data.

ProductQuery::prepare_objects_query() code WC 8.7.0

public function prepare_objects_query( $request ) {
	$args = [
		'offset'              => $request['offset'],
		'order'               => $request['order'],
		'orderby'             => $request['orderby'],
		'paged'               => $request['page'],
		'post__in'            => $request['include'],
		'post__not_in'        => $request['exclude'],
		'posts_per_page'      => $request['per_page'] ? $request['per_page'] : -1,
		'post_parent__in'     => $request['parent'],
		'post_parent__not_in' => $request['parent_exclude'],
		'search'              => $request['search'], // This uses search rather than s intentionally to handle searches internally.
		'slug'                => $request['slug'],
		'fields'              => 'ids',
		'ignore_sticky_posts' => true,
		'post_status'         => 'publish',
		'date_query'          => [],
		'post_type'           => 'product',
	];

	// If searching for a specific SKU or slug, allow any post type.
	if ( ! empty( $request['sku'] ) || ! empty( $request['slug'] ) ) {
		$args['post_type'] = [ 'product', 'product_variation' ];
	}

	// Taxonomy query to filter products by type, category, tag, shipping class, and attribute.
	$tax_query = [];

	// Filter product type by slug.
	if ( ! empty( $request['type'] ) ) {
		if ( 'variation' === $request['type'] ) {
			$args['post_type'] = 'product_variation';
		} else {
			$args['post_type'] = 'product';
			$tax_query[]       = [
				'taxonomy' => 'product_type',
				'field'    => 'slug',
				'terms'    => $request['type'],
			];
		}
	}

	if ( 'date' === $args['orderby'] ) {
		$args['orderby'] = 'date ID';
	}

	// Set before into date query. Date query must be specified as an array of an array.
	if ( isset( $request['before'] ) ) {
		$args['date_query'][0]['before'] = $request['before'];
	}

	// Set after into date query. Date query must be specified as an array of an array.
	if ( isset( $request['after'] ) ) {
		$args['date_query'][0]['after'] = $request['after'];
	}

	// Set date query column. Defaults to post_date.
	if ( isset( $request['date_column'] ) && ! empty( $args['date_query'][0] ) ) {
		$args['date_query'][0]['column'] = 'post_' . $request['date_column'];
	}

	// Set custom args to handle later during clauses.
	$custom_keys = [
		'sku',
		'min_price',
		'max_price',
		'stock_status',
	];

	foreach ( $custom_keys as $key ) {
		if ( ! empty( $request[ $key ] ) ) {
			$args[ $key ] = $request[ $key ];
		}
	}

	$operator_mapping = [
		'in'     => 'IN',
		'not_in' => 'NOT IN',
		'and'    => 'AND',
	];

	// Gets all registered product taxonomies and prefixes them with `tax_`.
	// This is needed to avoid situations where a user registers a new product taxonomy with the same name as default field.
	// eg an `sku` taxonomy will be mapped to `tax_sku`.
	$all_product_taxonomies = array_map(
		function ( $value ) {
			return '_unstable_tax_' . $value;
		},
		get_taxonomies( array( 'object_type' => array( 'product' ) ), 'names' )
	);

	// Map between taxonomy name and arg key.
	$default_taxonomies = [
		'product_cat' => 'category',
		'product_tag' => 'tag',
	];

	$taxonomies = array_merge( $all_product_taxonomies, $default_taxonomies );

	// Set tax_query for each passed arg.
	foreach ( $taxonomies as $taxonomy => $key ) {
		if ( ! empty( $request[ $key ] ) ) {
			$operator    = $request->get_param( $key . '_operator' ) && isset( $operator_mapping[ $request->get_param( $key . '_operator' ) ] ) ? $operator_mapping[ $request->get_param( $key . '_operator' ) ] : 'IN';
			$tax_query[] = [
				'taxonomy' => $taxonomy,
				'field'    => 'term_id',
				'terms'    => $request[ $key ],
				'operator' => $operator,
			];
		}
	}

	// Filter by attributes.
	if ( ! empty( $request['attributes'] ) ) {
		$att_queries = [];

		foreach ( $request['attributes'] as $attribute ) {
			if ( empty( $attribute['term_id'] ) && empty( $attribute['slug'] ) ) {
				continue;
			}
			if ( in_array( $attribute['attribute'], wc_get_attribute_taxonomy_names(), true ) ) {
				$operator      = isset( $attribute['operator'], $operator_mapping[ $attribute['operator'] ] ) ? $operator_mapping[ $attribute['operator'] ] : 'IN';
				$att_queries[] = [
					'taxonomy' => $attribute['attribute'],
					'field'    => ! empty( $attribute['term_id'] ) ? 'term_id' : 'slug',
					'terms'    => ! empty( $attribute['term_id'] ) ? $attribute['term_id'] : $attribute['slug'],
					'operator' => $operator,
				];
			}
		}

		if ( 1 < count( $att_queries ) ) {
			// Add relation arg when using multiple attributes.
			$relation    = $request->get_param( 'attribute_relation' ) && isset( $operator_mapping[ $request->get_param( 'attribute_relation' ) ] ) ? $operator_mapping[ $request->get_param( 'attribute_relation' ) ] : 'IN';
			$tax_query[] = [
				'relation' => $relation,
				$att_queries,
			];
		} else {
			$tax_query = array_merge( $tax_query, $att_queries );
		}
	}

	// Build tax_query if taxonomies are set.
	if ( ! empty( $tax_query ) && 'product_variation' !== $args['post_type'] ) {
		if ( ! empty( $args['tax_query'] ) ) {
			$args['tax_query'] = array_merge( $tax_query, $args['tax_query'] ); // phpcs:ignore
		} else {
			$args['tax_query'] = $tax_query; // phpcs:ignore
		}
	} else {
		// For product_variantions we need to convert the tax_query to a meta_query.
		if ( ! empty( $args['tax_query'] ) ) {
			$args['meta_query'] = $this->convert_tax_query_to_meta_query( array_merge( $tax_query, $args['tax_query'] ) ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
		} else {
			$args['meta_query'] = $this->convert_tax_query_to_meta_query( $tax_query ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
		}
	}

	// Filter featured.
	if ( is_bool( $request['featured'] ) ) {
		$args['tax_query'][] = [
			'taxonomy' => 'product_visibility',
			'field'    => 'name',
			'terms'    => 'featured',
			'operator' => true === $request['featured'] ? 'IN' : 'NOT IN',
		];
	}

	// Filter by on sale products.
	if ( is_bool( $request['on_sale'] ) ) {
		$on_sale_key = $request['on_sale'] ? 'post__in' : 'post__not_in';
		$on_sale_ids = wc_get_product_ids_on_sale();

		// Use 0 when there's no on sale products to avoid return all products.
		$on_sale_ids = empty( $on_sale_ids ) ? [ 0 ] : $on_sale_ids;

		$args[ $on_sale_key ] += $on_sale_ids;
	}

	$catalog_visibility = $request->get_param( 'catalog_visibility' );
	$rating             = $request->get_param( 'rating' );
	$visibility_options = wc_get_product_visibility_options();

	if ( in_array( $catalog_visibility, array_keys( $visibility_options ), true ) ) {
		$exclude_from_catalog = 'search' === $catalog_visibility ? '' : 'exclude-from-catalog';
		$exclude_from_search  = 'catalog' === $catalog_visibility ? '' : 'exclude-from-search';

		$args['tax_query'][] = [
			'taxonomy'      => 'product_visibility',
			'field'         => 'name',
			'terms'         => [ $exclude_from_catalog, $exclude_from_search ],
			'operator'      => 'hidden' === $catalog_visibility ? 'AND' : 'NOT IN',
			'rating_filter' => true,
		];
	}

	if ( $rating ) {
		$rating_terms = [];
		foreach ( $rating as $value ) {
			$rating_terms[] = 'rated-' . $value;
		}
		$args['tax_query'][] = [
			'taxonomy' => 'product_visibility',
			'field'    => 'name',
			'terms'    => $rating_terms,
		];
	}

	$orderby = $request->get_param( 'orderby' );
	$order   = $request->get_param( 'order' );

	$ordering_args   = wc()->query->get_catalog_ordering_args( $orderby, $order );
	$args['orderby'] = $ordering_args['orderby'];
	$args['order']   = $ordering_args['order'];

	if ( 'include' === $orderby ) {
		$args['orderby'] = 'post__in';
	} elseif ( 'id' === $orderby ) {
		$args['orderby'] = 'ID'; // ID must be capitalized.
	} elseif ( 'slug' === $orderby ) {
		$args['orderby'] = 'name';
	}

	if ( $ordering_args['meta_key'] ) {
		$args['meta_key'] = $ordering_args['meta_key']; // phpcs:ignore
	}

	return $args;
}