WC_API_Coupons

The WooCommerce WC API Coupons class.

Defined (3)

The class is defined in the following location(s).

/includes/api/legacy/v1/class-wc-api-coupons.php  
  1. class WC_API_Coupons extends WC_API_Resource { 
  2.  
  3. /** @var string $base the route base */ 
  4. protected $base = '/coupons'; 
  5.  
  6. /** 
  7. * Register the routes for this class 
  8. * GET /coupons 
  9. * GET /coupons/count 
  10. * GET /coupons/<id> 
  11. * @since 2.1 
  12. * @param array $routes 
  13. * @return array 
  14. */ 
  15. public function register_routes( $routes ) { 
  16.  
  17. # GET /coupons 
  18. $routes[ $this->base ] = array( 
  19. array( array( $this, 'get_coupons' ), WC_API_Server::READABLE ),  
  20. ); 
  21.  
  22. # GET /coupons/count 
  23. $routes[ $this->base . '/count'] = array( 
  24. array( array( $this, 'get_coupons_count' ), WC_API_Server::READABLE ),  
  25. ); 
  26.  
  27. # GET /coupons/<id> 
  28. $routes[ $this->base . '/(?P<id>\d+)' ] = array( 
  29. array( array( $this, 'get_coupon' ), WC_API_Server::READABLE ),  
  30. ); 
  31.  
  32. # GET /coupons/code/<code>, note that coupon codes can contain spaces, dashes and underscores 
  33. $routes[ $this->base . '/code/(?P<code>\w[\w\s\-]*)' ] = array( 
  34. array( array( $this, 'get_coupon_by_code' ), WC_API_Server::READABLE ),  
  35. ); 
  36.  
  37. return $routes; 
  38.  
  39. /** 
  40. * Get all coupons 
  41. * @since 2.1 
  42. * @param string $fields 
  43. * @param array $filter 
  44. * @param int $page 
  45. * @return array 
  46. */ 
  47. public function get_coupons( $fields = null, $filter = array(), $page = 1 ) { 
  48.  
  49. $filter['page'] = $page; 
  50.  
  51. $query = $this->query_coupons( $filter ); 
  52.  
  53. $coupons = array(); 
  54.  
  55. foreach( $query->posts as $coupon_id ) { 
  56.  
  57. if ( ! $this->is_readable( $coupon_id ) ) 
  58. continue; 
  59.  
  60. $coupons[] = current( $this->get_coupon( $coupon_id, $fields ) ); 
  61.  
  62. $this->server->add_pagination_headers( $query ); 
  63.  
  64. return array( 'coupons' => $coupons ); 
  65.  
  66. /** 
  67. * Get the coupon for the given ID 
  68. * @since 2.1 
  69. * @param int $id the coupon ID 
  70. * @param string $fields fields to include in response 
  71. * @return array|WP_Error 
  72. */ 
  73. public function get_coupon( $id, $fields = null ) { 
  74. global $wpdb; 
  75.  
  76. $id = $this->validate_request( $id, 'shop_coupon', 'read' ); 
  77.  
  78. if ( is_wp_error( $id ) ) 
  79. return $id; 
  80.  
  81. // get the coupon code 
  82. $code = $wpdb->get_var( $wpdb->prepare( "SELECT post_title FROM $wpdb->posts WHERE id = %s AND post_type = 'shop_coupon' AND post_status = 'publish'", $id ) ); 
  83.  
  84. if ( is_null( $code ) ) 
  85. return new WP_Error( 'woocommerce_api_invalid_coupon_id', __( 'Invalid coupon ID', 'woocommerce' ), array( 'status' => 404 ) ); 
  86.  
  87. $coupon = new WC_Coupon( $code ); 
  88.  
  89. $coupon_post = get_post( $coupon->id ); 
  90.  
  91. $coupon_data = array( 
  92. 'id' => $coupon->id,  
  93. 'code' => $coupon->code,  
  94. 'type' => $coupon->type,  
  95. 'created_at' => $this->server->format_datetime( $coupon_post->post_date_gmt ),  
  96. 'updated_at' => $this->server->format_datetime( $coupon_post->post_modified_gmt ),  
  97. 'amount' => wc_format_decimal( $coupon->amount, 2 ),  
  98. 'individual_use' => ( 'yes' === $coupon->individual_use ),  
  99. 'product_ids' => array_map( 'absint', (array) $coupon->product_ids ),  
  100. 'exclude_product_ids' => array_map( 'absint', (array) $coupon->exclude_product_ids ),  
  101. 'usage_limit' => ( ! empty( $coupon->usage_limit ) ) ? $coupon->usage_limit : null,  
  102. 'usage_limit_per_user' => ( ! empty( $coupon->usage_limit_per_user ) ) ? $coupon->usage_limit_per_user : null,  
  103. 'limit_usage_to_x_items' => (int) $coupon->limit_usage_to_x_items,  
  104. 'usage_count' => (int) $coupon->usage_count,  
  105. 'expiry_date' => $this->server->format_datetime( $coupon->expiry_date ),  
  106. 'enable_free_shipping' => $coupon->enable_free_shipping(),  
  107. 'product_category_ids' => array_map( 'absint', (array) $coupon->product_categories ),  
  108. 'exclude_product_category_ids' => array_map( 'absint', (array) $coupon->exclude_product_categories ),  
  109. 'exclude_sale_items' => $coupon->exclude_sale_items(),  
  110. 'minimum_amount' => wc_format_decimal( $coupon->minimum_amount, 2 ),  
  111. 'customer_emails' => $coupon->customer_email,  
  112. ); 
  113.  
  114. return array( 'coupon' => apply_filters( 'woocommerce_api_coupon_response', $coupon_data, $coupon, $fields, $this->server ) ); 
  115.  
  116. /** 
  117. * Get the total number of coupons 
  118. * @since 2.1 
  119. * @param array $filter 
  120. * @return array 
  121. */ 
  122. public function get_coupons_count( $filter = array() ) { 
  123.  
  124. $query = $this->query_coupons( $filter ); 
  125.  
  126. if ( ! current_user_can( 'read_private_shop_coupons' ) ) 
  127. return new WP_Error( 'woocommerce_api_user_cannot_read_coupons_count', __( 'You do not have permission to read the coupons count', 'woocommerce' ), array( 'status' => 401 ) ); 
  128.  
  129. return array( 'count' => (int) $query->found_posts ); 
  130.  
  131. /** 
  132. * Get the coupon for the given code 
  133. * @since 2.1 
  134. * @param string $code the coupon code 
  135. * @param string $fields fields to include in response 
  136. * @return int|WP_Error 
  137. */ 
  138. public function get_coupon_by_code( $code, $fields = null ) { 
  139. global $wpdb; 
  140.  
  141. $id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC LIMIT 1;", $code ) ); 
  142.  
  143. if ( is_null( $id ) ) 
  144. return new WP_Error( 'woocommerce_api_invalid_coupon_code', __( 'Invalid coupon code', 'woocommerce' ), array( 'status' => 404 ) ); 
  145.  
  146. return $this->get_coupon( $id, $fields ); 
  147.  
  148. /** 
  149. * Create a coupon 
  150. * @TODO implement in 2.2 
  151. * @param array $data 
  152. * @return array 
  153. */ 
  154. public function create_coupon( $data ) { 
  155.  
  156. return array(); 
  157.  
  158. /** 
  159. * Edit a coupon 
  160. * @TODO implement in 2.2 
  161. * @param int $id the coupon ID 
  162. * @param array $data 
  163. * @return array 
  164. */ 
  165. public function edit_coupon( $id, $data ) { 
  166.  
  167. $id = $this->validate_request( $id, 'shop_coupon', 'edit' ); 
  168.  
  169. if ( is_wp_error( $id ) ) 
  170. return $id; 
  171.  
  172. return $this->get_coupon( $id ); 
  173.  
  174. /** 
  175. * Delete a coupon 
  176. * @TODO enable along with PUT/POST in 2.2 
  177. * @param int $id the coupon ID 
  178. * @param bool $force true to permanently delete coupon, false to move to trash 
  179. * @return array 
  180. */ 
  181. public function delete_coupon( $id, $force = false ) { 
  182.  
  183. $id = $this->validate_request( $id, 'shop_coupon', 'delete' ); 
  184.  
  185. if ( is_wp_error( $id ) ) 
  186. return $id; 
  187.  
  188. return $this->delete( $id, 'shop_coupon', ( 'true' === $force ) ); 
  189.  
  190. /** 
  191. * Helper method to get coupon post objects 
  192. * @since 2.1 
  193. * @param array $args request arguments for filtering query 
  194. * @return WP_Query 
  195. */ 
  196. private function query_coupons( $args ) { 
  197.  
  198. // set base query arguments 
  199. $query_args = array( 
  200. 'fields' => 'ids',  
  201. 'post_type' => 'shop_coupon',  
  202. 'post_status' => 'publish',  
  203. ); 
  204.  
  205. $query_args = $this->merge_query_args( $query_args, $args ); 
  206.  
  207. return new WP_Query( $query_args ); 
  208.  
/includes/api/legacy/v2/class-wc-api-coupons.php  
  1. class WC_API_Coupons extends WC_API_Resource { 
  2.  
  3. /** @var string $base the route base */ 
  4. protected $base = '/coupons'; 
  5.  
  6. /** 
  7. * Register the routes for this class 
  8. * GET /coupons 
  9. * GET /coupons/count 
  10. * GET /coupons/<id> 
  11. * @since 2.1 
  12. * @param array $routes 
  13. * @return array 
  14. */ 
  15. public function register_routes( $routes ) { 
  16.  
  17. # GET/POST /coupons 
  18. $routes[ $this->base ] = array( 
  19. array( array( $this, 'get_coupons' ), WC_API_Server::READABLE ),  
  20. array( array( $this, 'create_coupon' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),  
  21. ); 
  22.  
  23. # GET /coupons/count 
  24. $routes[ $this->base . '/count'] = array( 
  25. array( array( $this, 'get_coupons_count' ), WC_API_Server::READABLE ),  
  26. ); 
  27.  
  28. # GET/PUT/DELETE /coupons/<id> 
  29. $routes[ $this->base . '/(?P<id>\d+)' ] = array( 
  30. array( array( $this, 'get_coupon' ), WC_API_Server::READABLE ),  
  31. array( array( $this, 'edit_coupon' ), WC_API_SERVER::EDITABLE | WC_API_SERVER::ACCEPT_DATA ),  
  32. array( array( $this, 'delete_coupon' ), WC_API_SERVER::DELETABLE ),  
  33. ); 
  34.  
  35. # GET /coupons/code/<code>, note that coupon codes can contain spaces, dashes and underscores 
  36. $routes[ $this->base . '/code/(?P<code>\w[\w\s\-]*)' ] = array( 
  37. array( array( $this, 'get_coupon_by_code' ), WC_API_Server::READABLE ),  
  38. ); 
  39.  
  40. # POST|PUT /coupons/bulk 
  41. $routes[ $this->base . '/bulk' ] = array( 
  42. array( array( $this, 'bulk' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),  
  43. ); 
  44.  
  45. return $routes; 
  46.  
  47. /** 
  48. * Get all coupons 
  49. * @since 2.1 
  50. * @param string $fields 
  51. * @param array $filter 
  52. * @param int $page 
  53. * @return array 
  54. */ 
  55. public function get_coupons( $fields = null, $filter = array(), $page = 1 ) { 
  56.  
  57. $filter['page'] = $page; 
  58.  
  59. $query = $this->query_coupons( $filter ); 
  60.  
  61. $coupons = array(); 
  62.  
  63. foreach ( $query->posts as $coupon_id ) { 
  64.  
  65. if ( ! $this->is_readable( $coupon_id ) ) { 
  66. continue; 
  67.  
  68. $coupons[] = current( $this->get_coupon( $coupon_id, $fields ) ); 
  69.  
  70. $this->server->add_pagination_headers( $query ); 
  71.  
  72. return array( 'coupons' => $coupons ); 
  73.  
  74. /** 
  75. * Get the coupon for the given ID 
  76. * @since 2.1 
  77. * @param int $id the coupon ID 
  78. * @param string $fields fields to include in response 
  79. * @return array|WP_Error 
  80. */ 
  81. public function get_coupon( $id, $fields = null ) { 
  82. global $wpdb; 
  83.  
  84. try { 
  85.  
  86. $id = $this->validate_request( $id, 'shop_coupon', 'read' ); 
  87.  
  88. if ( is_wp_error( $id ) ) { 
  89. return $id; 
  90.  
  91. // get the coupon code 
  92. $code = $wpdb->get_var( $wpdb->prepare( "SELECT post_title FROM $wpdb->posts WHERE id = %s AND post_type = 'shop_coupon' AND post_status = 'publish'", $id ) ); 
  93.  
  94. if ( is_null( $code ) ) { 
  95. throw new WC_API_Exception( 'woocommerce_api_invalid_coupon_id', __( 'Invalid coupon ID', 'woocommerce' ), 404 ); 
  96.  
  97. $coupon = new WC_Coupon( $code ); 
  98. $coupon_post = get_post( $coupon->id ); 
  99. $coupon_data = array( 
  100. 'id' => $coupon->id,  
  101. 'code' => $coupon->code,  
  102. 'type' => $coupon->type,  
  103. 'created_at' => $this->server->format_datetime( $coupon_post->post_date_gmt ),  
  104. 'updated_at' => $this->server->format_datetime( $coupon_post->post_modified_gmt ),  
  105. 'amount' => wc_format_decimal( $coupon->coupon_amount, 2 ),  
  106. 'individual_use' => ( 'yes' === $coupon->individual_use ),  
  107. 'product_ids' => array_map( 'absint', (array) $coupon->product_ids ),  
  108. 'exclude_product_ids' => array_map( 'absint', (array) $coupon->exclude_product_ids ),  
  109. 'usage_limit' => ( ! empty( $coupon->usage_limit ) ) ? $coupon->usage_limit : null,  
  110. 'usage_limit_per_user' => ( ! empty( $coupon->usage_limit_per_user ) ) ? $coupon->usage_limit_per_user : null,  
  111. 'limit_usage_to_x_items' => (int) $coupon->limit_usage_to_x_items,  
  112. 'usage_count' => (int) $coupon->usage_count,  
  113. 'expiry_date' => ( ! empty( $coupon->expiry_date ) ) ? $this->server->format_datetime( $coupon->expiry_date ) : null,  
  114. 'enable_free_shipping' => $coupon->enable_free_shipping(),  
  115. 'product_category_ids' => array_map( 'absint', (array) $coupon->product_categories ),  
  116. 'exclude_product_category_ids' => array_map( 'absint', (array) $coupon->exclude_product_categories ),  
  117. 'exclude_sale_items' => $coupon->exclude_sale_items(),  
  118. 'minimum_amount' => wc_format_decimal( $coupon->minimum_amount, 2 ),  
  119. 'maximum_amount' => wc_format_decimal( $coupon->maximum_amount, 2 ),  
  120. 'customer_emails' => $coupon->customer_email,  
  121. 'description' => $coupon_post->post_excerpt,  
  122. ); 
  123.  
  124. return array( 'coupon' => apply_filters( 'woocommerce_api_coupon_response', $coupon_data, $coupon, $fields, $this->server ) ); 
  125. } catch ( WC_API_Exception $e ) { 
  126. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  127.  
  128. /** 
  129. * Get the total number of coupons 
  130. * @since 2.1 
  131. * @param array $filter 
  132. * @return array 
  133. */ 
  134. public function get_coupons_count( $filter = array() ) { 
  135. try { 
  136. if ( ! current_user_can( 'read_private_shop_coupons' ) ) { 
  137. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_coupons_count', __( 'You do not have permission to read the coupons count', 'woocommerce' ), 401 ); 
  138.  
  139. $query = $this->query_coupons( $filter ); 
  140.  
  141. return array( 'count' => (int) $query->found_posts ); 
  142. } catch ( WC_API_Exception $e ) { 
  143. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  144.  
  145. /** 
  146. * Get the coupon for the given code 
  147. * @since 2.1 
  148. * @param string $code the coupon code 
  149. * @param string $fields fields to include in response 
  150. * @return int|WP_Error 
  151. */ 
  152. public function get_coupon_by_code( $code, $fields = null ) { 
  153. global $wpdb; 
  154.  
  155. try { 
  156. $id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC LIMIT 1;", $code ) ); 
  157.  
  158. if ( is_null( $id ) ) { 
  159. throw new WC_API_Exception( 'woocommerce_api_invalid_coupon_code', __( 'Invalid coupon code', 'woocommerce' ), 404 ); 
  160.  
  161. return $this->get_coupon( $id, $fields ); 
  162. } catch ( WC_API_Exception $e ) { 
  163. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  164.  
  165. /** 
  166. * Create a coupon 
  167. * @since 2.2 
  168. * @param array $data 
  169. * @return array 
  170. */ 
  171. public function create_coupon( $data ) { 
  172. global $wpdb; 
  173.  
  174. try { 
  175. if ( ! isset( $data['coupon'] ) ) { 
  176. throw new WC_API_Exception( 'woocommerce_api_missing_coupon_data', sprintf( __( 'No %1$s data specified to create %1$s', 'woocommerce' ), 'coupon' ), 400 ); 
  177.  
  178. $data = $data['coupon']; 
  179.  
  180. // Check user permission 
  181. if ( ! current_user_can( 'publish_shop_coupons' ) ) { 
  182. throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_coupon', __( 'You do not have permission to create coupons', 'woocommerce' ), 401 ); 
  183.  
  184. $data = apply_filters( 'woocommerce_api_create_coupon_data', $data, $this ); 
  185.  
  186. // Check if coupon code is specified 
  187. if ( ! isset( $data['code'] ) ) { 
  188. throw new WC_API_Exception( 'woocommerce_api_missing_coupon_code', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'code' ), 400 ); 
  189.  
  190. $coupon_code = apply_filters( 'woocommerce_coupon_code', $data['code'] ); 
  191.  
  192. // Check for duplicate coupon codes 
  193. $coupon_found = $wpdb->get_var( $wpdb->prepare( " 
  194. SELECT $wpdb->posts.ID 
  195. FROM $wpdb->posts 
  196. WHERE $wpdb->posts.post_type = 'shop_coupon' 
  197. AND $wpdb->posts.post_status = 'publish' 
  198. AND $wpdb->posts.post_title = '%s' 
  199. ", $coupon_code ) ); 
  200.  
  201. if ( $coupon_found ) { 
  202. throw new WC_API_Exception( 'woocommerce_api_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ), 400 ); 
  203.  
  204. $defaults = array( 
  205. 'type' => 'fixed_cart',  
  206. 'amount' => 0,  
  207. 'individual_use' => false,  
  208. 'product_ids' => array(),  
  209. 'exclude_product_ids' => array(),  
  210. 'usage_limit' => '',  
  211. 'usage_limit_per_user' => '',  
  212. 'limit_usage_to_x_items' => '',  
  213. 'usage_count' => '',  
  214. 'expiry_date' => '',  
  215. 'enable_free_shipping' => false,  
  216. 'product_category_ids' => array(),  
  217. 'exclude_product_category_ids' => array(),  
  218. 'exclude_sale_items' => false,  
  219. 'minimum_amount' => '',  
  220. 'maximum_amount' => '',  
  221. 'customer_emails' => array(),  
  222. 'description' => '' 
  223. ); 
  224.  
  225. $coupon_data = wp_parse_args( $data, $defaults ); 
  226.  
  227. // Validate coupon types 
  228. if ( ! in_array( wc_clean( $coupon_data['type'] ), array_keys( wc_get_coupon_types() ) ) ) { 
  229. throw new WC_API_Exception( 'woocommerce_api_invalid_coupon_type', sprintf( __( 'Invalid coupon type - the coupon type must be any of these: %s', 'woocommerce' ), implode( ', ', array_keys( wc_get_coupon_types() ) ) ), 400 ); 
  230.  
  231. $new_coupon = array( 
  232. 'post_title' => $coupon_code,  
  233. 'post_content' => '',  
  234. 'post_status' => 'publish',  
  235. 'post_author' => get_current_user_id(),  
  236. 'post_type' => 'shop_coupon',  
  237. 'post_excerpt' => $coupon_data['description'] 
  238. ); 
  239.  
  240. $id = wp_insert_post( $new_coupon, true ); 
  241.  
  242. if ( is_wp_error( $id ) ) { 
  243. throw new WC_API_Exception( 'woocommerce_api_cannot_create_coupon', $id->get_error_message(), 400 ); 
  244.  
  245. // Set coupon meta 
  246. update_post_meta( $id, 'discount_type', $coupon_data['type'] ); 
  247. update_post_meta( $id, 'coupon_amount', wc_format_decimal( $coupon_data['amount'] ) ); 
  248. update_post_meta( $id, 'individual_use', ( true === $coupon_data['individual_use'] ) ? 'yes' : 'no' ); 
  249. update_post_meta( $id, 'product_ids', implode( ', ', array_filter( array_map( 'intval', $coupon_data['product_ids'] ) ) ) ); 
  250. update_post_meta( $id, 'exclude_product_ids', implode( ', ', array_filter( array_map( 'intval', $coupon_data['exclude_product_ids'] ) ) ) ); 
  251. update_post_meta( $id, 'usage_limit', absint( $coupon_data['usage_limit'] ) ); 
  252. update_post_meta( $id, 'usage_limit_per_user', absint( $coupon_data['usage_limit_per_user'] ) ); 
  253. update_post_meta( $id, 'limit_usage_to_x_items', absint( $coupon_data['limit_usage_to_x_items'] ) ); 
  254. update_post_meta( $id, 'usage_count', absint( $coupon_data['usage_count'] ) ); 
  255. update_post_meta( $id, 'expiry_date', $this->get_coupon_expiry_date( wc_clean( $coupon_data['expiry_date'] ) ) ); 
  256. update_post_meta( $id, 'free_shipping', ( true === $coupon_data['enable_free_shipping'] ) ? 'yes' : 'no' ); 
  257. update_post_meta( $id, 'product_categories', array_filter( array_map( 'intval', $coupon_data['product_category_ids'] ) ) ); 
  258. update_post_meta( $id, 'exclude_product_categories', array_filter( array_map( 'intval', $coupon_data['exclude_product_category_ids'] ) ) ); 
  259. update_post_meta( $id, 'exclude_sale_items', ( true === $coupon_data['exclude_sale_items'] ) ? 'yes' : 'no' ); 
  260. update_post_meta( $id, 'minimum_amount', wc_format_decimal( $coupon_data['minimum_amount'] ) ); 
  261. update_post_meta( $id, 'maximum_amount', wc_format_decimal( $coupon_data['maximum_amount'] ) ); 
  262. update_post_meta( $id, 'customer_email', array_filter( array_map( 'sanitize_email', $coupon_data['customer_emails'] ) ) ); 
  263.  
  264. do_action( 'woocommerce_api_create_coupon', $id, $data ); 
  265.  
  266. $this->server->send_status( 201 ); 
  267.  
  268. return $this->get_coupon( $id ); 
  269. } catch ( WC_API_Exception $e ) { 
  270. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  271.  
  272. /** 
  273. * Edit a coupon 
  274. * @since 2.2 
  275. * @param int $id the coupon ID 
  276. * @param array $data 
  277. * @return array 
  278. */ 
  279. public function edit_coupon( $id, $data ) { 
  280.  
  281. try { 
  282. if ( ! isset( $data['coupon'] ) ) { 
  283. throw new WC_API_Exception( 'woocommerce_api_missing_coupon_data', sprintf( __( 'No %1$s data specified to edit %1$s', 'woocommerce' ), 'coupon' ), 400 ); 
  284.  
  285. $data = $data['coupon']; 
  286.  
  287. $id = $this->validate_request( $id, 'shop_coupon', 'edit' ); 
  288.  
  289. if ( is_wp_error( $id ) ) { 
  290. return $id; 
  291.  
  292. $data = apply_filters( 'woocommerce_api_edit_coupon_data', $data, $id, $this ); 
  293.  
  294. if ( isset( $data['code'] ) ) { 
  295. global $wpdb; 
  296.  
  297. $coupon_code = apply_filters( 'woocommerce_coupon_code', $data['code'] ); 
  298.  
  299. // Check for duplicate coupon codes 
  300. $coupon_found = $wpdb->get_var( $wpdb->prepare( " 
  301. SELECT $wpdb->posts.ID 
  302. FROM $wpdb->posts 
  303. WHERE $wpdb->posts.post_type = 'shop_coupon' 
  304. AND $wpdb->posts.post_status = 'publish' 
  305. AND $wpdb->posts.post_title = '%s' 
  306. AND $wpdb->posts.ID != %s 
  307. ", $coupon_code, $id ) ); 
  308.  
  309. if ( $coupon_found ) { 
  310. throw new WC_API_Exception( 'woocommerce_api_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ), 400 ); 
  311.  
  312. $updated = wp_update_post( array( 'ID' => intval( $id ), 'post_title' => $coupon_code ) ); 
  313.  
  314. if ( 0 === $updated ) { 
  315. throw new WC_API_Exception( 'woocommerce_api_cannot_update_coupon', __( 'Failed to update coupon', 'woocommerce' ), 400 ); 
  316.  
  317. if ( isset( $data['description'] ) ) { 
  318. $updated = wp_update_post( array( 'ID' => intval( $id ), 'post_excerpt' => $data['description'] ) ); 
  319.  
  320. if ( 0 === $updated ) { 
  321. throw new WC_API_Exception( 'woocommerce_api_cannot_update_coupon', __( 'Failed to update coupon', 'woocommerce' ), 400 ); 
  322.  
  323. if ( isset( $data['type'] ) ) { 
  324. // Validate coupon types 
  325. if ( ! in_array( wc_clean( $data['type'] ), array_keys( wc_get_coupon_types() ) ) ) { 
  326. throw new WC_API_Exception( 'woocommerce_api_invalid_coupon_type', sprintf( __( 'Invalid coupon type - the coupon type must be any of these: %s', 'woocommerce' ), implode( ', ', array_keys( wc_get_coupon_types() ) ) ), 400 ); 
  327. update_post_meta( $id, 'discount_type', $data['type'] ); 
  328.  
  329. if ( isset( $data['amount'] ) ) { 
  330. update_post_meta( $id, 'coupon_amount', wc_format_decimal( $data['amount'] ) ); 
  331.  
  332. if ( isset( $data['individual_use'] ) ) { 
  333. update_post_meta( $id, 'individual_use', ( true === $data['individual_use'] ) ? 'yes' : 'no' ); 
  334.  
  335. if ( isset( $data['product_ids'] ) ) { 
  336. update_post_meta( $id, 'product_ids', implode( ', ', array_filter( array_map( 'intval', $data['product_ids'] ) ) ) ); 
  337.  
  338. if ( isset( $data['exclude_product_ids'] ) ) { 
  339. update_post_meta( $id, 'exclude_product_ids', implode( ', ', array_filter( array_map( 'intval', $data['exclude_product_ids'] ) ) ) ); 
  340.  
  341. if ( isset( $data['usage_limit'] ) ) { 
  342. update_post_meta( $id, 'usage_limit', absint( $data['usage_limit'] ) ); 
  343.  
  344. if ( isset( $data['usage_limit_per_user'] ) ) { 
  345. update_post_meta( $id, 'usage_limit_per_user', absint( $data['usage_limit_per_user'] ) ); 
  346.  
  347. if ( isset( $data['limit_usage_to_x_items'] ) ) { 
  348. update_post_meta( $id, 'limit_usage_to_x_items', absint( $data['limit_usage_to_x_items'] ) ); 
  349.  
  350. if ( isset( $data['usage_count'] ) ) { 
  351. update_post_meta( $id, 'usage_count', absint( $data['usage_count'] ) ); 
  352.  
  353. if ( isset( $data['expiry_date'] ) ) { 
  354. update_post_meta( $id, 'expiry_date', $this->get_coupon_expiry_date( wc_clean( $data['expiry_date'] ) ) ); 
  355.  
  356. if ( isset( $data['enable_free_shipping'] ) ) { 
  357. update_post_meta( $id, 'free_shipping', ( true === $data['enable_free_shipping'] ) ? 'yes' : 'no' ); 
  358.  
  359. if ( isset( $data['product_category_ids'] ) ) { 
  360. update_post_meta( $id, 'product_categories', array_filter( array_map( 'intval', $data['product_category_ids'] ) ) ); 
  361.  
  362. if ( isset( $data['exclude_product_category_ids'] ) ) { 
  363. update_post_meta( $id, 'exclude_product_categories', array_filter( array_map( 'intval', $data['exclude_product_category_ids'] ) ) ); 
  364.  
  365. if ( isset( $data['exclude_sale_items'] ) ) { 
  366. update_post_meta( $id, 'exclude_sale_items', ( true === $data['exclude_sale_items'] ) ? 'yes' : 'no' ); 
  367.  
  368. if ( isset( $data['minimum_amount'] ) ) { 
  369. update_post_meta( $id, 'minimum_amount', wc_format_decimal( $data['minimum_amount'] ) ); 
  370.  
  371. if ( isset( $data['maximum_amount'] ) ) { 
  372. update_post_meta( $id, 'maximum_amount', wc_format_decimal( $data['maximum_amount'] ) ); 
  373.  
  374. if ( isset( $data['customer_emails'] ) ) { 
  375. update_post_meta( $id, 'customer_email', array_filter( array_map( 'sanitize_email', $data['customer_emails'] ) ) ); 
  376.  
  377. do_action( 'woocommerce_api_edit_coupon', $id, $data ); 
  378.  
  379. return $this->get_coupon( $id ); 
  380. } catch ( WC_API_Exception $e ) { 
  381. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  382.  
  383. /** 
  384. * Delete a coupon 
  385. * @since 2.2 
  386. * @param int $id the coupon ID 
  387. * @param bool $force true to permanently delete coupon, false to move to trash 
  388. * @return array 
  389. */ 
  390. public function delete_coupon( $id, $force = false ) { 
  391.  
  392. $id = $this->validate_request( $id, 'shop_coupon', 'delete' ); 
  393.  
  394. if ( is_wp_error( $id ) ) { 
  395. return $id; 
  396.  
  397. do_action( 'woocommerce_api_delete_coupon', $id, $this ); 
  398.  
  399. return $this->delete( $id, 'shop_coupon', ( 'true' === $force ) ); 
  400.  
  401. /** 
  402. * expiry_date format 
  403. * @since 2.3.0 
  404. * @param string $expiry_date 
  405. * @return string 
  406. */ 
  407. protected function get_coupon_expiry_date( $expiry_date ) { 
  408. if ( '' != $expiry_date ) { 
  409. return date( 'Y-m-d', strtotime( $expiry_date ) ); 
  410.  
  411. return ''; 
  412.  
  413. /** 
  414. * Helper method to get coupon post objects 
  415. * @since 2.1 
  416. * @param array $args request arguments for filtering query 
  417. * @return WP_Query 
  418. */ 
  419. private function query_coupons( $args ) { 
  420.  
  421. // set base query arguments 
  422. $query_args = array( 
  423. 'fields' => 'ids',  
  424. 'post_type' => 'shop_coupon',  
  425. 'post_status' => 'publish',  
  426. ); 
  427.  
  428. $query_args = $this->merge_query_args( $query_args, $args ); 
  429.  
  430. return new WP_Query( $query_args ); 
  431.  
  432. /** 
  433. * Bulk update or insert coupons 
  434. * Accepts an array with coupons in the formats supported by 
  435. * WC_API_Coupons->create_coupon() and WC_API_Coupons->edit_coupon() 
  436. * @since 2.4.0 
  437. * @param array $data 
  438. * @return array 
  439. */ 
  440. public function bulk( $data ) { 
  441.  
  442. try { 
  443. if ( ! isset( $data['coupons'] ) ) { 
  444. throw new WC_API_Exception( 'woocommerce_api_missing_coupons_data', sprintf( __( 'No %1$s data specified to create/edit %1$s', 'woocommerce' ), 'coupons' ), 400 ); 
  445.  
  446. $data = $data['coupons']; 
  447. $limit = apply_filters( 'woocommerce_api_bulk_limit', 100, 'coupons' ); 
  448.  
  449. // Limit bulk operation 
  450. if ( count( $data ) > $limit ) { 
  451. throw new WC_API_Exception( 'woocommerce_api_coupons_request_entity_too_large', sprintf( __( 'Unable to accept more than %s items for this request', 'woocommerce' ), $limit ), 413 ); 
  452.  
  453. $coupons = array(); 
  454.  
  455. foreach ( $data as $_coupon ) { 
  456. $coupon_id = 0; 
  457.  
  458. // Try to get the coupon ID 
  459. if ( isset( $_coupon['id'] ) ) { 
  460. $coupon_id = intval( $_coupon['id'] ); 
  461.  
  462. // Coupon exists / edit coupon 
  463. if ( $coupon_id ) { 
  464. $edit = $this->edit_coupon( $coupon_id, array( 'coupon' => $_coupon ) ); 
  465.  
  466. if ( is_wp_error( $edit ) ) { 
  467. $coupons[] = array( 
  468. 'id' => $coupon_id,  
  469. 'error' => array( 'code' => $edit->get_error_code(), 'message' => $edit->get_error_message() ) 
  470. ); 
  471. } else { 
  472. $coupons[] = $edit['coupon']; 
  473.  
  474. // Coupon don't exists / create coupon 
  475. else { 
  476. $new = $this->create_coupon( array( 'coupon' => $_coupon ) ); 
  477.  
  478. if ( is_wp_error( $new ) ) { 
  479. $coupons[] = array( 
  480. 'id' => $coupon_id,  
  481. 'error' => array( 'code' => $new->get_error_code(), 'message' => $new->get_error_message() ) 
  482. ); 
  483. } else { 
  484. $coupons[] = $new['coupon']; 
  485.  
  486. return array( 'coupons' => apply_filters( 'woocommerce_api_coupons_bulk_response', $coupons, $this ) ); 
  487. } catch ( WC_API_Exception $e ) { 
  488. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
/includes/api/legacy/v3/class-wc-api-coupons.php  
  1. class WC_API_Coupons extends WC_API_Resource { 
  2.  
  3. /** @var string $base the route base */ 
  4. protected $base = '/coupons'; 
  5.  
  6. /** 
  7. * Register the routes for this class 
  8. * GET /coupons 
  9. * GET /coupons/count 
  10. * GET /coupons/<id> 
  11. * @since 2.1 
  12. * @param array $routes 
  13. * @return array 
  14. */ 
  15. public function register_routes( $routes ) { 
  16.  
  17. # GET/POST /coupons 
  18. $routes[ $this->base ] = array( 
  19. array( array( $this, 'get_coupons' ), WC_API_Server::READABLE ),  
  20. array( array( $this, 'create_coupon' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),  
  21. ); 
  22.  
  23. # GET /coupons/count 
  24. $routes[ $this->base . '/count'] = array( 
  25. array( array( $this, 'get_coupons_count' ), WC_API_Server::READABLE ),  
  26. ); 
  27.  
  28. # GET/PUT/DELETE /coupons/<id> 
  29. $routes[ $this->base . '/(?P<id>\d+)' ] = array( 
  30. array( array( $this, 'get_coupon' ), WC_API_Server::READABLE ),  
  31. array( array( $this, 'edit_coupon' ), WC_API_SERVER::EDITABLE | WC_API_SERVER::ACCEPT_DATA ),  
  32. array( array( $this, 'delete_coupon' ), WC_API_SERVER::DELETABLE ),  
  33. ); 
  34.  
  35. # GET /coupons/code/<code>, note that coupon codes can contain spaces, dashes and underscores 
  36. $routes[ $this->base . '/code/(?P<code>\w[\w\s\-]*)' ] = array( 
  37. array( array( $this, 'get_coupon_by_code' ), WC_API_Server::READABLE ),  
  38. ); 
  39.  
  40. # POST|PUT /coupons/bulk 
  41. $routes[ $this->base . '/bulk' ] = array( 
  42. array( array( $this, 'bulk' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),  
  43. ); 
  44.  
  45. return $routes; 
  46.  
  47. /** 
  48. * Get all coupons 
  49. * @since 2.1 
  50. * @param string $fields 
  51. * @param array $filter 
  52. * @param int $page 
  53. * @return array 
  54. */ 
  55. public function get_coupons( $fields = null, $filter = array(), $page = 1 ) { 
  56.  
  57. $filter['page'] = $page; 
  58.  
  59. $query = $this->query_coupons( $filter ); 
  60.  
  61. $coupons = array(); 
  62.  
  63. foreach ( $query->posts as $coupon_id ) { 
  64.  
  65. if ( ! $this->is_readable( $coupon_id ) ) { 
  66. continue; 
  67.  
  68. $coupons[] = current( $this->get_coupon( $coupon_id, $fields ) ); 
  69.  
  70. $this->server->add_pagination_headers( $query ); 
  71.  
  72. return array( 'coupons' => $coupons ); 
  73.  
  74. /** 
  75. * Get the coupon for the given ID 
  76. * @since 2.1 
  77. * @param int $id the coupon ID 
  78. * @param string $fields fields to include in response 
  79. * @return array|WP_Error 
  80. */ 
  81. public function get_coupon( $id, $fields = null ) { 
  82. global $wpdb; 
  83.  
  84. try { 
  85.  
  86. $id = $this->validate_request( $id, 'shop_coupon', 'read' ); 
  87.  
  88. if ( is_wp_error( $id ) ) { 
  89. return $id; 
  90.  
  91. // get the coupon code 
  92. $code = $wpdb->get_var( $wpdb->prepare( "SELECT post_title FROM $wpdb->posts WHERE id = %s AND post_type = 'shop_coupon' AND post_status = 'publish'", $id ) ); 
  93.  
  94. if ( is_null( $code ) ) { 
  95. throw new WC_API_Exception( 'woocommerce_api_invalid_coupon_id', __( 'Invalid coupon ID', 'woocommerce' ), 404 ); 
  96.  
  97. $coupon = new WC_Coupon( $code ); 
  98. $coupon_post = get_post( $coupon->id ); 
  99. $coupon_data = array( 
  100. 'id' => $coupon->id,  
  101. 'code' => $coupon->code,  
  102. 'type' => $coupon->type,  
  103. 'created_at' => $this->server->format_datetime( $coupon_post->post_date_gmt ),  
  104. 'updated_at' => $this->server->format_datetime( $coupon_post->post_modified_gmt ),  
  105. 'amount' => wc_format_decimal( $coupon->coupon_amount, 2 ),  
  106. 'individual_use' => ( 'yes' === $coupon->individual_use ),  
  107. 'product_ids' => array_map( 'absint', (array) $coupon->product_ids ),  
  108. 'exclude_product_ids' => array_map( 'absint', (array) $coupon->exclude_product_ids ),  
  109. 'usage_limit' => ( ! empty( $coupon->usage_limit ) ) ? $coupon->usage_limit : null,  
  110. 'usage_limit_per_user' => ( ! empty( $coupon->usage_limit_per_user ) ) ? $coupon->usage_limit_per_user : null,  
  111. 'limit_usage_to_x_items' => (int) $coupon->limit_usage_to_x_items,  
  112. 'usage_count' => (int) $coupon->usage_count,  
  113. 'expiry_date' => ( ! empty( $coupon->expiry_date ) ) ? $this->server->format_datetime( $coupon->expiry_date ) : null,  
  114. 'enable_free_shipping' => $coupon->enable_free_shipping(),  
  115. 'product_category_ids' => array_map( 'absint', (array) $coupon->product_categories ),  
  116. 'exclude_product_category_ids' => array_map( 'absint', (array) $coupon->exclude_product_categories ),  
  117. 'exclude_sale_items' => $coupon->exclude_sale_items(),  
  118. 'minimum_amount' => wc_format_decimal( $coupon->minimum_amount, 2 ),  
  119. 'maximum_amount' => wc_format_decimal( $coupon->maximum_amount, 2 ),  
  120. 'customer_emails' => $coupon->customer_email,  
  121. 'description' => $coupon_post->post_excerpt,  
  122. ); 
  123.  
  124. return array( 'coupon' => apply_filters( 'woocommerce_api_coupon_response', $coupon_data, $coupon, $fields, $this->server ) ); 
  125. } catch ( WC_API_Exception $e ) { 
  126. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  127.  
  128. /** 
  129. * Get the total number of coupons 
  130. * @since 2.1 
  131. * @param array $filter 
  132. * @return array 
  133. */ 
  134. public function get_coupons_count( $filter = array() ) { 
  135. try { 
  136. if ( ! current_user_can( 'read_private_shop_coupons' ) ) { 
  137. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_coupons_count', __( 'You do not have permission to read the coupons count', 'woocommerce' ), 401 ); 
  138.  
  139. $query = $this->query_coupons( $filter ); 
  140.  
  141. return array( 'count' => (int) $query->found_posts ); 
  142. } catch ( WC_API_Exception $e ) { 
  143. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  144.  
  145. /** 
  146. * Get the coupon for the given code 
  147. * @since 2.1 
  148. * @param string $code the coupon code 
  149. * @param string $fields fields to include in response 
  150. * @return int|WP_Error 
  151. */ 
  152. public function get_coupon_by_code( $code, $fields = null ) { 
  153. global $wpdb; 
  154.  
  155. try { 
  156. $id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC LIMIT 1;", $code ) ); 
  157.  
  158. if ( is_null( $id ) ) { 
  159. throw new WC_API_Exception( 'woocommerce_api_invalid_coupon_code', __( 'Invalid coupon code', 'woocommerce' ), 404 ); 
  160.  
  161. return $this->get_coupon( $id, $fields ); 
  162. } catch ( WC_API_Exception $e ) { 
  163. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  164.  
  165. /** 
  166. * Create a coupon 
  167. * @since 2.2 
  168. * @param array $data 
  169. * @return array 
  170. */ 
  171. public function create_coupon( $data ) { 
  172. global $wpdb; 
  173.  
  174. try { 
  175. if ( ! isset( $data['coupon'] ) ) { 
  176. throw new WC_API_Exception( 'woocommerce_api_missing_coupon_data', sprintf( __( 'No %1$s data specified to create %1$s', 'woocommerce' ), 'coupon' ), 400 ); 
  177.  
  178. $data = $data['coupon']; 
  179.  
  180. // Check user permission 
  181. if ( ! current_user_can( 'publish_shop_coupons' ) ) { 
  182. throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_coupon', __( 'You do not have permission to create coupons', 'woocommerce' ), 401 ); 
  183.  
  184. $data = apply_filters( 'woocommerce_api_create_coupon_data', $data, $this ); 
  185.  
  186. // Check if coupon code is specified 
  187. if ( ! isset( $data['code'] ) ) { 
  188. throw new WC_API_Exception( 'woocommerce_api_missing_coupon_code', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'code' ), 400 ); 
  189.  
  190. $coupon_code = apply_filters( 'woocommerce_coupon_code', $data['code'] ); 
  191.  
  192. // Check for duplicate coupon codes 
  193. $coupon_found = $wpdb->get_var( $wpdb->prepare( " 
  194. SELECT $wpdb->posts.ID 
  195. FROM $wpdb->posts 
  196. WHERE $wpdb->posts.post_type = 'shop_coupon' 
  197. AND $wpdb->posts.post_status = 'publish' 
  198. AND $wpdb->posts.post_title = '%s' 
  199. ", $coupon_code ) ); 
  200.  
  201. if ( $coupon_found ) { 
  202. throw new WC_API_Exception( 'woocommerce_api_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ), 400 ); 
  203.  
  204. $defaults = array( 
  205. 'type' => 'fixed_cart',  
  206. 'amount' => 0,  
  207. 'individual_use' => false,  
  208. 'product_ids' => array(),  
  209. 'exclude_product_ids' => array(),  
  210. 'usage_limit' => '',  
  211. 'usage_limit_per_user' => '',  
  212. 'limit_usage_to_x_items' => '',  
  213. 'usage_count' => '',  
  214. 'expiry_date' => '',  
  215. 'enable_free_shipping' => false,  
  216. 'product_category_ids' => array(),  
  217. 'exclude_product_category_ids' => array(),  
  218. 'exclude_sale_items' => false,  
  219. 'minimum_amount' => '',  
  220. 'maximum_amount' => '',  
  221. 'customer_emails' => array(),  
  222. 'description' => '' 
  223. ); 
  224.  
  225. $coupon_data = wp_parse_args( $data, $defaults ); 
  226.  
  227. // Validate coupon types 
  228. if ( ! in_array( wc_clean( $coupon_data['type'] ), array_keys( wc_get_coupon_types() ) ) ) { 
  229. throw new WC_API_Exception( 'woocommerce_api_invalid_coupon_type', sprintf( __( 'Invalid coupon type - the coupon type must be any of these: %s', 'woocommerce' ), implode( ', ', array_keys( wc_get_coupon_types() ) ) ), 400 ); 
  230.  
  231. $new_coupon = array( 
  232. 'post_title' => $coupon_code,  
  233. 'post_content' => '',  
  234. 'post_status' => 'publish',  
  235. 'post_author' => get_current_user_id(),  
  236. 'post_type' => 'shop_coupon',  
  237. 'post_excerpt' => $coupon_data['description'] 
  238. ); 
  239.  
  240. $id = wp_insert_post( $new_coupon, true ); 
  241.  
  242. if ( is_wp_error( $id ) ) { 
  243. throw new WC_API_Exception( 'woocommerce_api_cannot_create_coupon', $id->get_error_message(), 400 ); 
  244.  
  245. // Set coupon meta 
  246. update_post_meta( $id, 'discount_type', $coupon_data['type'] ); 
  247. update_post_meta( $id, 'coupon_amount', wc_format_decimal( $coupon_data['amount'] ) ); 
  248. update_post_meta( $id, 'individual_use', ( true === $coupon_data['individual_use'] ) ? 'yes' : 'no' ); 
  249. update_post_meta( $id, 'product_ids', implode( ', ', array_filter( array_map( 'intval', $coupon_data['product_ids'] ) ) ) ); 
  250. update_post_meta( $id, 'exclude_product_ids', implode( ', ', array_filter( array_map( 'intval', $coupon_data['exclude_product_ids'] ) ) ) ); 
  251. update_post_meta( $id, 'usage_limit', absint( $coupon_data['usage_limit'] ) ); 
  252. update_post_meta( $id, 'usage_limit_per_user', absint( $coupon_data['usage_limit_per_user'] ) ); 
  253. update_post_meta( $id, 'limit_usage_to_x_items', absint( $coupon_data['limit_usage_to_x_items'] ) ); 
  254. update_post_meta( $id, 'usage_count', absint( $coupon_data['usage_count'] ) ); 
  255. update_post_meta( $id, 'expiry_date', $this->get_coupon_expiry_date( wc_clean( $coupon_data['expiry_date'] ) ) ); 
  256. update_post_meta( $id, 'free_shipping', ( true === $coupon_data['enable_free_shipping'] ) ? 'yes' : 'no' ); 
  257. update_post_meta( $id, 'product_categories', array_filter( array_map( 'intval', $coupon_data['product_category_ids'] ) ) ); 
  258. update_post_meta( $id, 'exclude_product_categories', array_filter( array_map( 'intval', $coupon_data['exclude_product_category_ids'] ) ) ); 
  259. update_post_meta( $id, 'exclude_sale_items', ( true === $coupon_data['exclude_sale_items'] ) ? 'yes' : 'no' ); 
  260. update_post_meta( $id, 'minimum_amount', wc_format_decimal( $coupon_data['minimum_amount'] ) ); 
  261. update_post_meta( $id, 'maximum_amount', wc_format_decimal( $coupon_data['maximum_amount'] ) ); 
  262. update_post_meta( $id, 'customer_email', array_filter( array_map( 'sanitize_email', $coupon_data['customer_emails'] ) ) ); 
  263.  
  264. do_action( 'woocommerce_api_create_coupon', $id, $data ); 
  265.  
  266. $this->server->send_status( 201 ); 
  267.  
  268. return $this->get_coupon( $id ); 
  269. } catch ( WC_API_Exception $e ) { 
  270. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  271.  
  272. /** 
  273. * Edit a coupon 
  274. * @since 2.2 
  275. * @param int $id the coupon ID 
  276. * @param array $data 
  277. * @return array 
  278. */ 
  279. public function edit_coupon( $id, $data ) { 
  280.  
  281. try { 
  282. if ( ! isset( $data['coupon'] ) ) { 
  283. throw new WC_API_Exception( 'woocommerce_api_missing_coupon_data', sprintf( __( 'No %1$s data specified to edit %1$s', 'woocommerce' ), 'coupon' ), 400 ); 
  284.  
  285. $data = $data['coupon']; 
  286.  
  287. $id = $this->validate_request( $id, 'shop_coupon', 'edit' ); 
  288.  
  289. if ( is_wp_error( $id ) ) { 
  290. return $id; 
  291.  
  292. $data = apply_filters( 'woocommerce_api_edit_coupon_data', $data, $id, $this ); 
  293.  
  294. if ( isset( $data['code'] ) ) { 
  295. global $wpdb; 
  296.  
  297. $coupon_code = apply_filters( 'woocommerce_coupon_code', $data['code'] ); 
  298.  
  299. // Check for duplicate coupon codes 
  300. $coupon_found = $wpdb->get_var( $wpdb->prepare( " 
  301. SELECT $wpdb->posts.ID 
  302. FROM $wpdb->posts 
  303. WHERE $wpdb->posts.post_type = 'shop_coupon' 
  304. AND $wpdb->posts.post_status = 'publish' 
  305. AND $wpdb->posts.post_title = '%s' 
  306. AND $wpdb->posts.ID != %s 
  307. ", $coupon_code, $id ) ); 
  308.  
  309. if ( $coupon_found ) { 
  310. throw new WC_API_Exception( 'woocommerce_api_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ), 400 ); 
  311.  
  312. $updated = wp_update_post( array( 'ID' => intval( $id ), 'post_title' => $coupon_code ) ); 
  313.  
  314. if ( 0 === $updated ) { 
  315. throw new WC_API_Exception( 'woocommerce_api_cannot_update_coupon', __( 'Failed to update coupon', 'woocommerce' ), 400 ); 
  316.  
  317. if ( isset( $data['description'] ) ) { 
  318. $updated = wp_update_post( array( 'ID' => intval( $id ), 'post_excerpt' => $data['description'] ) ); 
  319.  
  320. if ( 0 === $updated ) { 
  321. throw new WC_API_Exception( 'woocommerce_api_cannot_update_coupon', __( 'Failed to update coupon', 'woocommerce' ), 400 ); 
  322.  
  323. if ( isset( $data['type'] ) ) { 
  324. // Validate coupon types 
  325. if ( ! in_array( wc_clean( $data['type'] ), array_keys( wc_get_coupon_types() ) ) ) { 
  326. throw new WC_API_Exception( 'woocommerce_api_invalid_coupon_type', sprintf( __( 'Invalid coupon type - the coupon type must be any of these: %s', 'woocommerce' ), implode( ', ', array_keys( wc_get_coupon_types() ) ) ), 400 ); 
  327. update_post_meta( $id, 'discount_type', $data['type'] ); 
  328.  
  329. if ( isset( $data['amount'] ) ) { 
  330. update_post_meta( $id, 'coupon_amount', wc_format_decimal( $data['amount'] ) ); 
  331.  
  332. if ( isset( $data['individual_use'] ) ) { 
  333. update_post_meta( $id, 'individual_use', ( true === $data['individual_use'] ) ? 'yes' : 'no' ); 
  334.  
  335. if ( isset( $data['product_ids'] ) ) { 
  336. update_post_meta( $id, 'product_ids', implode( ', ', array_filter( array_map( 'intval', $data['product_ids'] ) ) ) ); 
  337.  
  338. if ( isset( $data['exclude_product_ids'] ) ) { 
  339. update_post_meta( $id, 'exclude_product_ids', implode( ', ', array_filter( array_map( 'intval', $data['exclude_product_ids'] ) ) ) ); 
  340.  
  341. if ( isset( $data['usage_limit'] ) ) { 
  342. update_post_meta( $id, 'usage_limit', absint( $data['usage_limit'] ) ); 
  343.  
  344. if ( isset( $data['usage_limit_per_user'] ) ) { 
  345. update_post_meta( $id, 'usage_limit_per_user', absint( $data['usage_limit_per_user'] ) ); 
  346.  
  347. if ( isset( $data['limit_usage_to_x_items'] ) ) { 
  348. update_post_meta( $id, 'limit_usage_to_x_items', absint( $data['limit_usage_to_x_items'] ) ); 
  349.  
  350. if ( isset( $data['usage_count'] ) ) { 
  351. update_post_meta( $id, 'usage_count', absint( $data['usage_count'] ) ); 
  352.  
  353. if ( isset( $data['expiry_date'] ) ) { 
  354. update_post_meta( $id, 'expiry_date', $this->get_coupon_expiry_date( wc_clean( $data['expiry_date'] ) ) ); 
  355.  
  356. if ( isset( $data['enable_free_shipping'] ) ) { 
  357. update_post_meta( $id, 'free_shipping', ( true === $data['enable_free_shipping'] ) ? 'yes' : 'no' ); 
  358.  
  359. if ( isset( $data['product_category_ids'] ) ) { 
  360. update_post_meta( $id, 'product_categories', array_filter( array_map( 'intval', $data['product_category_ids'] ) ) ); 
  361.  
  362. if ( isset( $data['exclude_product_category_ids'] ) ) { 
  363. update_post_meta( $id, 'exclude_product_categories', array_filter( array_map( 'intval', $data['exclude_product_category_ids'] ) ) ); 
  364.  
  365. if ( isset( $data['exclude_sale_items'] ) ) { 
  366. update_post_meta( $id, 'exclude_sale_items', ( true === $data['exclude_sale_items'] ) ? 'yes' : 'no' ); 
  367.  
  368. if ( isset( $data['minimum_amount'] ) ) { 
  369. update_post_meta( $id, 'minimum_amount', wc_format_decimal( $data['minimum_amount'] ) ); 
  370.  
  371. if ( isset( $data['maximum_amount'] ) ) { 
  372. update_post_meta( $id, 'maximum_amount', wc_format_decimal( $data['maximum_amount'] ) ); 
  373.  
  374. if ( isset( $data['customer_emails'] ) ) { 
  375. update_post_meta( $id, 'customer_email', array_filter( array_map( 'sanitize_email', $data['customer_emails'] ) ) ); 
  376.  
  377. do_action( 'woocommerce_api_edit_coupon', $id, $data ); 
  378.  
  379. return $this->get_coupon( $id ); 
  380. } catch ( WC_API_Exception $e ) { 
  381. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  382.  
  383. /** 
  384. * Delete a coupon 
  385. * @since 2.2 
  386. * @param int $id the coupon ID 
  387. * @param bool $force true to permanently delete coupon, false to move to trash 
  388. * @return array 
  389. */ 
  390. public function delete_coupon( $id, $force = false ) { 
  391.  
  392. $id = $this->validate_request( $id, 'shop_coupon', 'delete' ); 
  393.  
  394. if ( is_wp_error( $id ) ) { 
  395. return $id; 
  396.  
  397. do_action( 'woocommerce_api_delete_coupon', $id, $this ); 
  398.  
  399. return $this->delete( $id, 'shop_coupon', ( 'true' === $force ) ); 
  400.  
  401. /** 
  402. * expiry_date format 
  403. * @since 2.3.0 
  404. * @param string $expiry_date 
  405. * @return string 
  406. */ 
  407. protected function get_coupon_expiry_date( $expiry_date ) { 
  408. if ( '' != $expiry_date ) { 
  409. return date( 'Y-m-d', strtotime( $expiry_date ) ); 
  410.  
  411. return ''; 
  412.  
  413. /** 
  414. * Helper method to get coupon post objects 
  415. * @since 2.1 
  416. * @param array $args request arguments for filtering query 
  417. * @return WP_Query 
  418. */ 
  419. private function query_coupons( $args ) { 
  420.  
  421. // set base query arguments 
  422. $query_args = array( 
  423. 'fields' => 'ids',  
  424. 'post_type' => 'shop_coupon',  
  425. 'post_status' => 'publish',  
  426. ); 
  427.  
  428. $query_args = $this->merge_query_args( $query_args, $args ); 
  429.  
  430. return new WP_Query( $query_args ); 
  431.  
  432. /** 
  433. * Bulk update or insert coupons 
  434. * Accepts an array with coupons in the formats supported by 
  435. * WC_API_Coupons->create_coupon() and WC_API_Coupons->edit_coupon() 
  436. * @since 2.4.0 
  437. * @param array $data 
  438. * @return array 
  439. */ 
  440. public function bulk( $data ) { 
  441.  
  442. try { 
  443. if ( ! isset( $data['coupons'] ) ) { 
  444. throw new WC_API_Exception( 'woocommerce_api_missing_coupons_data', sprintf( __( 'No %1$s data specified to create/edit %1$s', 'woocommerce' ), 'coupons' ), 400 ); 
  445.  
  446. $data = $data['coupons']; 
  447. $limit = apply_filters( 'woocommerce_api_bulk_limit', 100, 'coupons' ); 
  448.  
  449. // Limit bulk operation 
  450. if ( count( $data ) > $limit ) { 
  451. throw new WC_API_Exception( 'woocommerce_api_coupons_request_entity_too_large', sprintf( __( 'Unable to accept more than %s items for this request', 'woocommerce' ), $limit ), 413 ); 
  452.  
  453. $coupons = array(); 
  454.  
  455. foreach ( $data as $_coupon ) { 
  456. $coupon_id = 0; 
  457.  
  458. // Try to get the coupon ID 
  459. if ( isset( $_coupon['id'] ) ) { 
  460. $coupon_id = intval( $_coupon['id'] ); 
  461.  
  462. // Coupon exists / edit coupon 
  463. if ( $coupon_id ) { 
  464. $edit = $this->edit_coupon( $coupon_id, array( 'coupon' => $_coupon ) ); 
  465.  
  466. if ( is_wp_error( $edit ) ) { 
  467. $coupons[] = array( 
  468. 'id' => $coupon_id,  
  469. 'error' => array( 'code' => $edit->get_error_code(), 'message' => $edit->get_error_message() ) 
  470. ); 
  471. } else { 
  472. $coupons[] = $edit['coupon']; 
  473.  
  474. // Coupon don't exists / create coupon 
  475. else { 
  476. $new = $this->create_coupon( array( 'coupon' => $_coupon ) ); 
  477.  
  478. if ( is_wp_error( $new ) ) { 
  479. $coupons[] = array( 
  480. 'id' => $coupon_id,  
  481. 'error' => array( 'code' => $new->get_error_code(), 'message' => $new->get_error_message() ) 
  482. ); 
  483. } else { 
  484. $coupons[] = $new['coupon']; 
  485.  
  486. return array( 'coupons' => apply_filters( 'woocommerce_api_coupons_bulk_response', $coupons, $this ) ); 
  487. } catch ( WC_API_Exception $e ) { 
  488. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );