<?php
/**
* WooCommerce API Products Class
*
* Handles requests to the /products endpoint
*
* @author WooThemes
* @category API
* @package WooCommerce/API
* @since 2.1
* @version 3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
class WC_API_Products extends WC_API_Resource {
/** @var string $base the route base */
protected $base = '/products';
/**
* Register the routes for this class
*
* GET/POST /products
* GET /products/count
* GET/PUT/DELETE /products/<id>
* GET /products/<id>/reviews
*
* @since 2.1
* @param array $routes
* @return array
*/
public function register_routes( $routes ) {
# GET/POST /products
$routes[ $this->base ] = array(
array( array( $this, 'get_products' ), WC_API_Server::READABLE ),
array( array( $this, 'create_product' ), WC_API_SERVER::CREATABLE | WC_API_Server::ACCEPT_DATA ),
);
# GET /products/count
$routes[ $this->base . '/count' ] = array(
array( array( $this, 'get_products_count' ), WC_API_Server::READABLE ),
);
# GET/PUT/DELETE /products/<id>
$routes[ $this->base . '/(?P<id>\d+)' ] = array(
array( array( $this, 'get_product' ), WC_API_Server::READABLE ),
array( array( $this, 'edit_product' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
array( array( $this, 'delete_product' ), WC_API_Server::DELETABLE ),
);
# GET /products/<id>/reviews
$routes[ $this->base . '/(?P<id>\d+)/reviews' ] = array(
array( array( $this, 'get_product_reviews' ), WC_API_Server::READABLE ),
);
# GET /products/<id>/orders
$routes[ $this->base . '/(?P<id>\d+)/orders' ] = array(
array( array( $this, 'get_product_orders' ), WC_API_Server::READABLE ),
);
# GET/POST /products/categories
$routes[ $this->base . '/categories' ] = array(
array( array( $this, 'get_product_categories' ), WC_API_Server::READABLE ),
array( array( $this, 'create_product_category' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),
);
# GET/PUT/DELETE /products/categories/<id>
$routes[ $this->base . '/categories/(?P<id>\d+)' ] = array(
array( array( $this, 'get_product_category' ), WC_API_Server::READABLE ),
array( array( $this, 'edit_product_category' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
array( array( $this, 'delete_product_category' ), WC_API_Server::DELETABLE ),
);
# GET/POST /products/tags
$routes[ $this->base . '/tags' ] = array(
array( array( $this, 'get_product_tags' ), WC_API_Server::READABLE ),
array( array( $this, 'create_product_tag' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),
);
# GET/PUT/DELETE /products/tags/<id>
$routes[ $this->base . '/tags/(?P<id>\d+)' ] = array(
array( array( $this, 'get_product_tag' ), WC_API_Server::READABLE ),
array( array( $this, 'edit_product_tag' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
array( array( $this, 'delete_product_tag' ), WC_API_Server::DELETABLE ),
);
# GET/POST /products/shipping_classes
$routes[ $this->base . '/shipping_classes' ] = array(
array( array( $this, 'get_product_shipping_classes' ), WC_API_Server::READABLE ),
array( array( $this, 'create_product_shipping_class' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),
);
# GET/PUT/DELETE /products/shipping_classes/<id>
$routes[ $this->base . '/shipping_classes/(?P<id>\d+)' ] = array(
array( array( $this, 'get_product_shipping_class' ), WC_API_Server::READABLE ),
array( array( $this, 'edit_product_shipping_class' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
array( array( $this, 'delete_product_shipping_class' ), WC_API_Server::DELETABLE ),
);
# GET/POST /products/attributes
$routes[ $this->base . '/attributes' ] = array(
array( array( $this, 'get_product_attributes' ), WC_API_Server::READABLE ),
array( array( $this, 'create_product_attribute' ), WC_API_SERVER::CREATABLE | WC_API_Server::ACCEPT_DATA ),
);
# GET/PUT/DELETE /products/attributes/<id>
$routes[ $this->base . '/attributes/(?P<id>\d+)' ] = array(
array( array( $this, 'get_product_attribute' ), WC_API_Server::READABLE ),
array( array( $this, 'edit_product_attribute' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
array( array( $this, 'delete_product_attribute' ), WC_API_Server::DELETABLE ),
);
# GET/POST /products/attributes/<attribute_id>/terms
$routes[ $this->base . '/attributes/(?P<attribute_id>\d+)/terms' ] = array(
array( array( $this, 'get_product_attribute_terms' ), WC_API_Server::READABLE ),
array( array( $this, 'create_product_attribute_term' ), WC_API_SERVER::CREATABLE | WC_API_Server::ACCEPT_DATA ),
);
# GET/PUT/DELETE /products/attributes/<attribute_id>/terms/<id>
$routes[ $this->base . '/attributes/(?P<attribute_id>\d+)/terms/(?P<id>\d+)' ] = array(
array( array( $this, 'get_product_attribute_term' ), WC_API_Server::READABLE ),
array( array( $this, 'edit_product_attribute_term' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
array( array( $this, 'delete_product_attribute_term' ), WC_API_Server::DELETABLE ),
);
# POST|PUT /products/bulk
$routes[ $this->base . '/bulk' ] = array(
array( array( $this, 'bulk' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
);
return $routes;
}
/**
* Get all products
*
* @since 2.1
* @param string $fields
* @param string $type
* @param array $filter
* @param int $page
* @return array
*/
public function get_products( $fields = null, $type = null, $filter = array(), $page = 1 ) {
if ( ! empty( $type ) ) {
$filter['type'] = $type;
}
$filter['page'] = $page;
$query = $this->query_products( $filter );
$products = array();
foreach ( $query->posts as $product_id ) {
if ( ! $this->is_readable( $product_id ) ) {
continue;
}
$products[] = current( $this->get_product( $product_id, $fields ) );
}
$this->server->add_pagination_headers( $query );
return array( 'products' => $products );
}
/**
* Get the product for the given ID
*
* @since 2.1
* @param int $id the product ID
* @param string $fields
* @return array|WP_Error
*/
public function get_product( $id, $fields = null ) {
$id = $this->validate_request( $id, 'product', 'read' );
if ( is_wp_error( $id ) ) {
return $id;
}
$product = wc_get_product( $id );
// add data that applies to every product type
$product_data = $this->get_product_data( $product );
// add variations to variable products
if ( $product->is_type( 'variable' ) && $product->has_child() ) {
$product_data['variations'] = $this->get_variation_data( $product );
}
// add the parent product data to an individual variation
if ( $product->is_type( 'variation' ) && $product->get_parent_id() ) {
$product_data['parent'] = $this->get_product_data( $product->get_parent_id() );
}
// Add grouped products data
if ( $product->is_type( 'grouped' ) && $product->has_child() ) {
$product_data['grouped_products'] = $this->get_grouped_products_data( $product );
}
if ( $product->is_type( 'simple' ) ) {
$parent_id = $product->get_parent_id();
if ( ! empty( $parent_id ) ) {
$_product = wc_get_product( $parent_id );
$product_data['parent'] = $this->get_product_data( $_product );
}
}
return array( 'product' => apply_filters( 'woocommerce_api_product_response', $product_data, $product, $fields, $this->server ) );
}
/**
* Get the total number of products
*
* @since 2.1
*
* @param string $type
* @param array $filter
*
* @return array|WP_Error
*/
public function get_products_count( $type = null, $filter = array() ) {
try {
if ( ! current_user_can( 'read_private_products' ) ) {
throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_products_count', __( 'You do not have permission to read the products count', 'woocommerce' ), 401 );
}
if ( ! empty( $type ) ) {