Automattic\WooCommerce\EmailEditor\Integrations\WooCommerce\Renderer\Blocks

Product_Collection::prepare_and_execute_queryprivateWC 1.0

Prepare and execute a query for the Product Collection block using the original QueryBuilder.

Method of the class: Product_Collection{}

No Hooks.

Returns

WP_Query.

Usage

// private - for code of main (parent) class only
$result = $this->prepare_and_execute_query( $parsed_block, $rendering_context ): WP_Query;
$parsed_block(array) (required)
Parsed block data.
$rendering_context(Rendering_Context) (required)
Rendering context.

Product_Collection::prepare_and_execute_query() code WC 10.8.1

private function prepare_and_execute_query( array $parsed_block, Rendering_Context $rendering_context ): WP_Query {
	$collection  = $parsed_block['attrs']['collection'] ?? '';
	$query_attrs = $parsed_block['attrs']['query'] ?? array();

	// Build a direct WP_Query for email rendering (not using ProductCollection QueryBuilder).
	// The QueryBuilder is designed for REST/frontend context, not email rendering.
	$query_args = array(
		'post_type'      => 'product',
		'post_status'    => 'publish',
		'posts_per_page' => (int) ( $query_attrs['perPage'] ?? 9 ),
		'orderby'        => sanitize_key( $query_attrs['orderBy'] ?? 'menu_order' ),
		'order'          => sanitize_key( $query_attrs['order'] ?? 'asc' ),
		'meta_query'     => array(), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
		'tax_query'      => array(), // phpcs:ignore WordPress.DB.SlowDBQuery
	);

	// Handle search.
	if ( ! empty( $query_attrs['search'] ) ) {
		$query_args['s'] = sanitize_text_field( (string) $query_attrs['search'] );
	}

	// Handle offset.
	if ( isset( $query_attrs['offset'] ) ) {
		$query_args['offset'] = (int) $query_attrs['offset'];
	}

	// Handle exclusions.
	if ( isset( $query_attrs['exclude'] ) && is_array( $query_attrs['exclude'] ) ) {
		$query_args['post__not_in'] = array_map(
			static function ( $id ) {
				return is_numeric( $id ) ? (int) $id : 0;
			},
			$query_attrs['exclude']
		);
	}

	// Handle handpicked products.
	if ( ! empty( $query_attrs['woocommerceHandPickedProducts'] ) ) {
		$query_args['post__in'] = array_map(
			static function ( $id ) {
				return is_numeric( $id ) ? (int) $id : 0;
			},
			$query_attrs['woocommerceHandPickedProducts']
		);
		$query_args['orderby']  = 'post__in';
	}

	// Handle featured products - use the WooCommerce way.
	$is_featured = $query_attrs['featured'] ?? false;
	if ( 'woocommerce/product-collection/featured' === $collection || $is_featured ) {
		// Use WooCommerce's built-in function to get featured products query.
		$featured_query = wc_get_product_visibility_term_ids();
		if ( isset( $featured_query['featured'] ) ) {
			$query_args['tax_query'][] = array(
				'taxonomy' => 'product_visibility',
				'field'    => 'term_taxonomy_id',
				'terms'    => array( (int) $featured_query['featured'] ),
				'operator' => 'IN',
			);
		}
	}

	// Handle on-sale products.
	$is_on_sale = $query_attrs['woocommerceOnSale'] ?? false;
	if ( 'woocommerce/product-collection/on-sale' === $collection || $is_on_sale ) {
		$query_args['meta_query'][] = array(
			'relation' => 'OR',
			array(
				'key'     => '_sale_price',
				'value'   => '',
				'compare' => '!=',
			),
		);
	}

	// Handle stock status (only if not all statuses are selected).
	$stock_status = $query_attrs['woocommerceStockStatus'] ?? array();
	if ( ! empty( $stock_status ) && ! $this->is_all_stock_statuses( $stock_status ) ) {
		$query_args['meta_query'][] = array(
			'key'     => '_stock_status',
			'value'   => $stock_status,
			'compare' => 'IN',
		);
	}

	// Handle taxonomies (categories, tags, etc.).
	if ( ! empty( $query_attrs['taxQuery'] ) ) {
		$tax_queries             = $this->build_tax_query( $query_attrs['taxQuery'] );
		$query_args['tax_query'] = array_merge( $query_args['tax_query'], $tax_queries ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
	}

	// Handle product attributes.
	if ( ! empty( $query_attrs['woocommerceAttributes'] ) ) {
		$attribute_queries       = $this->build_attribute_query( $query_attrs['woocommerceAttributes'] );
		$query_args['tax_query'] = array_merge( $query_args['tax_query'], $attribute_queries ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
	}

	// Handle special collections: upsells, cross-sells, related, cart-contents.
	$product_ids_to_include = $this->get_collection_specific_product_ids( $collection, $parsed_block, $rendering_context );
	if ( ! empty( $product_ids_to_include ) ) {
		$query_args['post__in'] = $product_ids_to_include;
	}

	// Set tax_query relation if multiple tax queries.
	if ( count( $query_args['tax_query'] ) > 1 ) {
		$query_args['tax_query']['relation'] = 'AND';
	}

	$wp_query = new WP_Query( $query_args );

	return $wp_query;
}