Merge pull request #12214 from woocommerce/product-crud-wc_get_products

[Product CRUD] Add a wc_get_products wrapper
This commit is contained in:
Justin Shreve 2016-10-30 08:11:44 -07:00 committed by GitHub
commit b037108c93
2 changed files with 277 additions and 27 deletions

View File

@ -14,6 +14,153 @@ if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Products wrapper for get_posts.
*
* This function should be used for product retrieval so that we have a data agnostic
* way to get a list of products.
*
* Args:
* status array|string List of statuses to find. Default: any. Options: any, draft, pending, private and publish.
* type array|string Product type, e.g. Default: all. Options: all, simple, external, variable, variation, grouped.
* parent int post/product parent
* skus array Limit result set to products with specific SKUs.
* categories array Limit result set to products assigned a specific category, e.g. 9,14.
* tags array Limit result set to products assigned a specific tag, e.g. 9,14.
* limit int Maximum of products to retrieve.
* offset int Offset of products to retrieve.
* page int Page of products to retrieve. Ignored when using the 'offset' arg.
* exclude array Product IDs to exclude from the query.
* orderby string Order by date, title, id, modified, rand etc
* order string ASC or DESC
* return string Type of data to return. Allowed values:
* ids array of Product ids
* objects array of product objects (default)
* paginate bool If true, the return value will be an array with values:
* 'products' => array of data (return value above),
* 'total' => total number of products matching the query
* 'max_num_pages' => max number of pages found
*
* @since 2.7.0
* @param array $args Array of args (above)
* @return array|stdClass Number of pages and an array of product objects if
* paginate is true, or just an array of values.
*/
function wc_get_products( $args ) {
$args = wp_parse_args( $args, array(
'status' => array( 'draft', 'pending', 'private', 'publish' ),
'type' => array_merge( array_keys( wc_get_product_types() ), array( 'variation' ) ),
'parent' => null,
'sku' => '',
'category' => array(),
'tag' => array(),
'limit' => get_option( 'posts_per_page' ),
'offset' => null,
'page' => 1,
'exclude' => array(),
'orderby' => 'date',
'order' => 'DESC',
'return' => 'objects',
'paginate' => false,
) );
// Handle some BW compatibility arg names where wp_query args differ in naming.
$map_legacy = array(
'numberposts' => 'limit',
'post_status' => 'status',
'post_parent' => 'parent',
'posts_per_page' => 'limit',
'paged' => 'page',
);
foreach ( $map_legacy as $from => $to ) {
if ( isset( $args[ $from ] ) ) {
$args[ $to ] = $args[ $from ];
}
}
/**
* Generate WP_Query args.
*/
$wp_query_args = array(
'post_type' => array( 'product', 'product_variation' ),
'post_status' => $args['status'],
'posts_per_page' => $args['limit'],
'meta_query' => array(),
'fields' => 'ids',
'orderby' => $args['orderby'],
'order' => $args['order'],
'tax_query' => array(
array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => $args['type'],
)
)
);
if ( ! empty( $args['sku'] ) ) {
$wp_query_args['meta_query'][] = array(
'key' => '_sku',
'value' => $args['sku'],
'compare' => 'LIKE',
);
}
if ( ! empty( $args['category'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_cat',
'field' => 'term_id',
'terms' => $args['category'],
);
}
if ( ! empty( $args['tag'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_tag',
'field' => 'term_id',
'terms' => $args['tag'],
);
}
if ( ! is_null( $args['parent'] ) ) {
$wp_query_args['post_parent'] = absint( $args['parent'] );
}
if ( ! is_null( $args['offset'] ) ) {
$wp_query_args['offset'] = absint( $args['offset'] );
} else {
$wp_query_args['paged'] = absint( $args['page'] );
}
if ( ! empty( $args['exclude'] ) ) {
$wp_query_args['post__not_in'] = array_map( 'absint', $args['exclude'] );
}
if ( ! $args['paginate'] ) {
$wp_query_args['no_found_rows'] = true;
}
// Get results.
$products = new WP_Query( $wp_query_args );
if ( 'objects' === $args['return'] ) {
$return = array_map( 'wc_get_product', $products->posts );
} else {
$return = $products->posts;
}
if ( $args['paginate'] ) {
return (object) array(
'products' => $return,
'total' => $products->found_posts,
'max_num_pages' => $procuts->max_num_pages,
);
} else {
return $return;
}
}
/**
* Main function for returning products, uses the WC_Product_Factory class.
*

View File

@ -7,6 +7,103 @@
*/
class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
/**
* Tests wc_get_products().
*
* @since 2.7.0
*/
public function test_wc_get_products() {
$test_cat_1 = wp_insert_term( 'Testing 1', 'product_cat' );
$test_tag_1 = wp_insert_term( 'Tag 1', 'product_tag' );
$test_tag_2 = wp_insert_term( 'Tag 2', 'product_tag' );
$product = WC_Helper_Product::create_simple_product();
$product->set_tag_ids( array( $test_tag_1['term_id'] ) );
$product->set_category_ids( array( $test_cat_1['term_id'] ) );
$product->set_sku( 'GET TEST SKU SIMPLE' );
$product->save();
$product_2 = WC_Helper_Product::create_simple_product();
$product_2->set_category_ids( array( $test_cat_1['term_id'] ) );
$product_2->save();
$external = WC_Helper_Product::create_simple_product();
$external->set_category_ids( array( $test_cat_1['term_id'] ) );
$external->set_sku( 'GET TEST SKU EXTERNAL' );
$external->save();
$external_2 = WC_Helper_Product::create_simple_product();
$external_2->set_tag_ids( array( $test_tag_2['term_id'] ) );
$external_2->save();
$grouped = WC_Helper_Product::create_grouped_product();
$variation = WC_Helper_Product::create_variation_product();
$variation->set_tag_ids( array( $test_tag_1['term_id'] ) );
$variation->save();
$draft = WC_Helper_Product::create_simple_product();
$draft->set_status( 'draft' );
$draft->save();
$this->assertEquals( 10, count( wc_get_products( array( 'return' => 'ids' ) ) ) );
// test status
$products = wc_get_products( array( 'return' => 'ids', 'status' => 'draft' ) );
$this->assertEquals( array( $draft->get_id() ), $products );
// test type
$products = wc_get_products( array( 'return' => 'ids', 'type' => array( 'variable', 'variation' ) ) );
$this->assertEquals( 3, count( $products ) );
$this->assertContains( $variation->get_id(), $products );
// test parent
$products = wc_get_products( array( 'return' => 'ids', 'parent' => $variation->get_id() ) );
$this->assertEquals( 2, count( $products ) );
// test skus
$products = wc_get_products( array( 'return' => 'ids', 'sku' => 'GET TEST SKU' ) );
$this->assertEquals( 2, count( $products ) );
$this->assertContains( $product->get_id(), $products );
$this->assertContains( $external->get_id(), $products );
// test categories
$products = wc_get_products( array( 'return' => 'ids', 'category' => array( $test_cat_1['term_id'] ) ) );
$this->assertEquals( 3, count( $products ) );
// test tags
$products = wc_get_products( array( 'return' => 'ids', 'tag' => array( $test_tag_1['term_id'] ) ) );
$this->assertEquals( 2, count( $products ) );
$products = wc_get_products( array( 'return' => 'ids', 'tag' => array( $test_tag_2['term_id'] ) ) );
$this->assertEquals( 1, count( $products ) );
$products = wc_get_products( array( 'return' => 'ids', 'tag' => array( $test_tag_1['term_id'], $test_tag_2['term_id'] ) ) );
$this->assertEquals( 3, count( $products ) );
// test limit
$products = wc_get_products( array( 'return' => 'ids', 'limit' => 5 ) );
$this->assertEquals( 5, count( $products ) );
// test offset
$products = wc_get_products( array( 'return' => 'ids', 'limit' => 5 ) );
$products_offset = wc_get_products( array( 'return' => 'ids', 'limit' => 5, 'offset' => 5 ) );
$this->assertEquals( 5, count( $products ) );
$this->assertEquals( 5, count( $products_offset ) );
$this->assertNotEquals( $products, $products_offset );
// test page
$products_page_1 = wc_get_products( array( 'return' => 'ids', 'limit' => 5 ) );
$products_page_2 = wc_get_products( array( 'return' => 'ids', 'limit' => 5, 'page' => 2 ) );
$this->assertEquals( 5, count( $products_page_1 ) );
$this->assertEquals( 5, count( $products_page_2 ) );
$this->assertNotEquals( $products_page_1, $products_page_2 );
// test exclude
$products = wc_get_products( array( 'return' => 'ids', 'limit' => 200, 'exclude' => array( $product->get_id() ) ) );
$this->assertNotContains( $product->get_id(), $products );
}
/**
* Test wc_get_product().
*
@ -17,12 +114,12 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
// Create product
$product = WC_Helper_Product::create_simple_product();
$product_copy = wc_get_product( $product->id );
$product_copy = wc_get_product( $product->get_id() );
$this->assertEquals( $product->id, $product_copy->id );
$this->assertEquals( $product->get_id(), $product_copy->get_id() );
// Delete Product
WC_Helper_Product::delete_product( $product->id );
WC_Helper_Product::delete_product( $product->get_id() );
}
/**
@ -34,13 +131,15 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
// Create product
$product = WC_Helper_Product::create_simple_product();
update_post_meta( $product->id, '_manage_stock', 'yes' );
update_post_meta( $product->get_id(), '_manage_stock', 'yes' );
wc_update_product_stock( $product->id, 5 );
$this->assertEquals( 5, $product->stock );
wc_update_product_stock( $product->get_id(), 5 );
$product = new WC_Product_Simple( $product->get_id() );
$this->assertEquals( 5, $product->get_stock_quantity() );
// Delete Product
WC_Helper_Product::delete_product( $product->id );
WC_Helper_Product::delete_product( $product->get_id() );
}
/**
@ -52,10 +151,10 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
// Create product
$product = WC_Helper_Product::create_simple_product();
update_post_meta( $product->id, '_regular_price', wc_format_decimal( 10 ) );
update_post_meta( $product->id, '_price', wc_format_decimal( 5 ) );
update_post_meta( $product->id, '_sale_price', wc_format_decimal( 5 ) );
update_post_meta( $product->id, '_featured', 'yes' );
update_post_meta( $product->get_id(), '_regular_price', wc_format_decimal( 10 ) );
update_post_meta( $product->get_id(), '_price', wc_format_decimal( 5 ) );
update_post_meta( $product->get_id(), '_sale_price', wc_format_decimal( 5 ) );
update_post_meta( $product->get_id(), '_featured', 'yes' );
wc_get_product_ids_on_sale(); // Creates the transient for on sale products
wc_get_featured_product_ids(); // Creates the transient for featured products
@ -65,7 +164,7 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
$this->assertFalse( get_transient( 'wc_products_onsale' ) );
$this->assertFalse( get_transient( 'wc_featured_products' ) );
WC_Helper_Product::delete_product( $product->id );
WC_Helper_Product::delete_product( $product->get_id() );
}
/**
@ -81,14 +180,14 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
// Create product
$product = WC_Helper_Product::create_simple_product();
update_post_meta( $product->id, '_regular_price', wc_format_decimal( 10 ) );
update_post_meta( $product->id, '_price', wc_format_decimal( 5 ) );
update_post_meta( $product->id, '_sale_price', wc_format_decimal( 5 ) );
update_post_meta( $product->get_id(), '_regular_price', wc_format_decimal( 10 ) );
update_post_meta( $product->get_id(), '_price', wc_format_decimal( 5 ) );
update_post_meta( $product->get_id(), '_sale_price', wc_format_decimal( 5 ) );
$this->assertEquals( array( $product->id ), wc_get_product_ids_on_sale() );
$this->assertEquals( array( $product->get_id() ), wc_get_product_ids_on_sale() );
// Delete Product
WC_Helper_Product::delete_product( $product->id );
WC_Helper_Product::delete_product( $product->get_id() );
}
/**
@ -104,12 +203,12 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
// Create product
$product = WC_Helper_Product::create_simple_product();
update_post_meta( $product->id, '_featured', 'yes' );
update_post_meta( $product->get_id(), '_featured', 'yes' );
$this->assertEquals( array( $product->id ), wc_get_featured_product_ids() );
$this->assertEquals( array( $product->get_id() ), wc_get_featured_product_ids() );
// Delete Product
WC_Helper_Product::delete_product( $product->id );
WC_Helper_Product::delete_product( $product->get_id() );
}
/**
@ -157,16 +256,20 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
public function test_wc_product_has_unique_sku() {
$product_1 = WC_Helper_Product::create_simple_product();
$this->assertEquals( true, wc_product_has_unique_sku( $product_1->id, $product_1->sku ) );
$this->assertEquals( true, wc_product_has_unique_sku( $product_1->get_id(), $product_1->get_sku() ) );
$product_2 = WC_Helper_Product::create_simple_product();
$this->assertEquals( false, wc_product_has_unique_sku( $product_2->id, $product_2->sku ) );
// we need to manually set a sku, because WC_Product now uses wc_product_has_unique_sku before setting
// so we need to manually set it to test the functionality.
update_post_meta( $product_2->get_id(), '_sku', $product_1->get_sku() );
WC_Helper_Product::delete_product( $product_1->id );
$this->assertEquals( false, wc_product_has_unique_sku( $product_2->get_id(), $product_1->get_sku() ) );
$this->assertEquals( true, wc_product_has_unique_sku( $product_2->id, $product_2->sku ) );
WC_Helper_Product::delete_product( $product_1->get_id() );
WC_Helper_Product::delete_product( $product_2->id );
$this->assertEquals( true, wc_product_has_unique_sku( $product_2->get_id(), $product_2->get_sku() ) );
WC_Helper_Product::delete_product( $product_2->get_id() );
}
/**
@ -178,9 +281,9 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
// Create product
$product = WC_Helper_Product::create_simple_product();
$this->assertEquals( $product->id, wc_get_product_id_by_sku( $product->sku ) );
$this->assertEquals( $product->get_id(), wc_get_product_id_by_sku( $product->get_sku() ) );
// Delete Product
WC_Helper_Product::delete_product( $product->id );
WC_Helper_Product::delete_product( $product->get_id() );
}
}