2018-12-12 13:35:56 +00:00
< ? php
/**
* REST API Products Controller
*
* Handles requests to / products /*
*
* @ package WooCommerce Admin / API
*/
defined ( 'ABSPATH' ) || exit ;
/**
* Products controller .
*
* @ package WooCommerce Admin / API
* @ extends WC_REST_Products_Controller
*/
class WC_Admin_REST_Products_Controller extends WC_REST_Products_Controller {
2019-01-18 02:52:58 +00:00
/**
* Endpoint namespace .
*
* @ var string
*/
protected $namespace = 'wc/v4' ;
2018-12-12 13:35:56 +00:00
/**
* Adds properties that can be embed via ? _embed = 1.
*
* @ return array
*/
public function get_item_schema () {
$schema = parent :: get_item_schema ();
$properties_to_embed = array (
'id' ,
'name' ,
'slug' ,
'permalink' ,
'images' ,
'description' ,
'short_description' ,
);
foreach ( $properties_to_embed as $property ) {
$schema [ 'properties' ][ $property ][ 'context' ][] = 'embed' ;
}
return $schema ;
}
2019-02-27 08:49:21 +00:00
/**
* Get the query params for collections .
*
* @ return array
*/
public function get_collection_params () {
2019-03-29 02:45:19 +00:00
$params = parent :: get_collection_params ();
$params [ 'low_in_stock' ] = array (
'description' => __ ( 'Limit result set to products that are low or out of stock.' , 'woocommerce-admin' ),
'type' => 'boolean' ,
'default' => false ,
'sanitize_callback' => 'wc_string_to_bool' ,
);
$params [ 'search' ] = array (
2019-03-18 03:31:02 +00:00
'description' => __ ( 'Search by similar product name or sku.' , 'woocommerce-admin' ),
2019-02-27 08:49:21 +00:00
'type' => 'string' ,
'validate_callback' => 'rest_validate_request_arg' ,
);
return $params ;
}
2019-03-18 03:31:02 +00:00
2019-02-27 08:49:21 +00:00
/**
2019-03-18 03:31:02 +00:00
* Add product name and sku filtering to the WC API .
2019-02-27 08:49:21 +00:00
*
* @ param WP_REST_Request $request Request data .
* @ return array
*/
protected function prepare_objects_query ( $request ) {
$args = parent :: prepare_objects_query ( $request );
2019-03-18 03:31:02 +00:00
if ( ! empty ( $request [ 'search' ] ) ) {
2019-03-29 02:45:19 +00:00
$args [ 'search' ] = trim ( $request [ 'search' ] );
2019-03-18 03:31:02 +00:00
unset ( $args [ 's' ] );
2019-02-27 08:49:21 +00:00
}
2019-03-29 02:45:19 +00:00
if ( ! empty ( $request [ 'low_in_stock' ] ) ) {
$args [ 'low_in_stock' ] = $request [ 'low_in_stock' ];
2019-04-02 17:37:24 +00:00
$args [ 'post_type' ] = array ( 'product' , 'product_variation' );
2019-03-29 02:45:19 +00:00
}
2019-02-27 08:49:21 +00:00
return $args ;
}
/**
* Get a collection of posts and add the post title filter option to WP_Query .
*
* @ param WP_REST_Request $request Full details about the request .
* @ return WP_Error | WP_REST_Response
*/
public function get_items ( $request ) {
2019-03-29 02:45:19 +00:00
add_filter ( 'posts_where' , array ( __CLASS__ , 'add_wp_query_filter' ), 10 , 2 );
add_filter ( 'posts_join' , array ( __CLASS__ , 'add_wp_query_join' ), 10 , 2 );
add_filter ( 'posts_groupby' , array ( __CLASS__ , 'add_wp_query_group_by' ), 10 , 2 );
2019-02-27 08:49:21 +00:00
$response = parent :: get_items ( $request );
2019-03-29 02:45:19 +00:00
remove_filter ( 'posts_where' , array ( __CLASS__ , 'add_wp_query_filter' ), 10 );
remove_filter ( 'posts_join' , array ( __CLASS__ , 'add_wp_query_join' ), 10 );
remove_filter ( 'posts_groupby' , array ( __CLASS__ , 'add_wp_query_group_by' ), 10 );
2019-02-27 08:49:21 +00:00
return $response ;
}
/**
2019-03-29 02:45:19 +00:00
* Add in conditional search filters for products .
2019-02-27 08:49:21 +00:00
*
* @ param string $where Where clause used to search posts .
* @ param object $wp_query WP_Query object .
* @ return string
*/
2019-03-29 02:45:19 +00:00
public static function add_wp_query_filter ( $where , $wp_query ) {
2019-02-27 08:49:21 +00:00
global $wpdb ;
2019-03-29 02:45:19 +00:00
$search = $wp_query -> get ( 'search' );
2019-03-18 03:31:02 +00:00
if ( $search ) {
$search = $wpdb -> esc_like ( $search );
$search = " '% " . $search . " %' " ;
2019-03-29 02:45:19 +00:00
$where .= " AND ( { $wpdb -> posts } .post_title LIKE { $search } " ;
2019-05-08 13:05:35 +00:00
$where .= wc_product_sku_enabled () ? ' OR wc_product_meta_lookup.sku LIKE ' . $search . ')' : ')' ;
2019-02-27 08:49:21 +00:00
}
2019-03-29 02:45:19 +00:00
if ( $wp_query -> get ( 'low_in_stock' ) ) {
$low_stock_amount = absint ( max ( get_option ( 'woocommerce_notify_low_stock_amount' ), 1 ) );
2019-05-08 12:43:25 +00:00
$where .= "
2019-05-08 13:05:35 +00:00
AND wc_product_meta_lookup . stock_quantity IS NOT NULL
2019-05-09 09:28:28 +00:00
AND wc_product_meta_lookup . stock_status = 'instock'
2019-03-29 02:45:19 +00:00
AND (
2019-05-08 12:43:25 +00:00
(
low_stock_amount_meta . meta_value > ''
2019-05-08 13:05:35 +00:00
AND wc_product_meta_lookup . stock_quantity <= CAST ( low_stock_amount_meta . meta_value AS SIGNED )
2019-05-08 12:43:25 +00:00
)
OR (
2019-05-08 13:05:35 +00:00
(
low_stock_amount_meta . meta_value IS NULL OR low_stock_amount_meta . meta_value <= ''
)
AND wc_product_meta_lookup . stock_quantity <= { $low_stock_amount }
2019-05-08 12:43:25 +00:00
)
2019-03-29 02:45:19 +00:00
) " ;
}
2019-02-27 08:49:21 +00:00
return $where ;
}
2019-03-18 03:31:02 +00:00
/**
2019-03-29 02:45:19 +00:00
* Join posts meta tables when product search or low stock query is present .
2019-03-18 03:31:02 +00:00
*
* @ param string $join Join clause used to search posts .
* @ param object $wp_query WP_Query object .
* @ return string
*/
2019-03-29 02:45:19 +00:00
public static function add_wp_query_join ( $join , $wp_query ) {
2019-03-18 03:31:02 +00:00
global $wpdb ;
2019-03-29 02:45:19 +00:00
$search = $wp_query -> get ( 'search' );
2019-03-18 03:31:02 +00:00
if ( $search && wc_product_sku_enabled () ) {
2019-05-08 13:05:35 +00:00
$join = self :: append_product_sorting_table_join ( $join );
2019-03-29 02:45:19 +00:00
}
if ( $wp_query -> get ( 'low_in_stock' ) ) {
2019-05-08 13:05:35 +00:00
$join = self :: append_product_sorting_table_join ( $join );
$join .= " LEFT JOIN { $wpdb -> postmeta } AS low_stock_amount_meta ON { $wpdb -> posts } .ID = low_stock_amount_meta.post_id AND low_stock_amount_meta.meta_key = '_low_stock_amount' " ;
2019-03-18 03:31:02 +00:00
}
return $join ;
}
2019-05-08 13:05:35 +00:00
/**
* Join wc_product_meta_lookup to posts if not already joined .
*
* @ param string $sql SQL join .
* @ return string
*/
protected static function append_product_sorting_table_join ( $sql ) {
global $wpdb ;
if ( ! strstr ( $sql , 'wc_product_meta_lookup' ) ) {
$sql .= " LEFT JOIN { $wpdb -> wc_product_meta_lookup } wc_product_meta_lookup ON $wpdb->posts .ID = wc_product_meta_lookup.product_id " ;
}
return $sql ;
}
2019-03-19 03:36:47 +00:00
/**
* Group by post ID to prevent duplicates .
*
* @ param string $groupby Group by clause used to organize posts .
* @ param object $wp_query WP_Query object .
* @ return string
*/
2019-03-29 02:45:19 +00:00
public static function add_wp_query_group_by ( $groupby , $wp_query ) {
2019-03-19 03:36:47 +00:00
global $wpdb ;
2019-03-29 02:45:19 +00:00
$search = $wp_query -> get ( 'search' );
$low_in_stock = $wp_query -> get ( 'low_in_stock' );
if ( empty ( $groupby ) && ( $search || $low_in_stock ) ) {
2019-03-19 03:36:47 +00:00
$groupby = $wpdb -> posts . '.ID' ;
}
return $groupby ;
}
2018-12-12 13:35:56 +00:00
}