WC_API_Customers

The WooCommerce WC API Customers class.

Defined (3)

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

/includes/api/legacy/v1/class-wc-api-customers.php  
  1. class WC_API_Customers extends WC_API_Resource { 
  2.  
  3. /** @var string $base the route base */ 
  4. protected $base = '/customers'; 
  5.  
  6. /** @var string $created_at_min for date filtering */ 
  7. private $created_at_min = null; 
  8.  
  9. /** @var string $created_at_max for date filtering */ 
  10. private $created_at_max = null; 
  11.  
  12. /** 
  13. * Setup class, overridden to provide customer data to order response 
  14. * @since 2.1 
  15. * @param WC_API_Server $server 
  16. * @return WC_API_Customers 
  17. */ 
  18. public function __construct( WC_API_Server $server ) { 
  19.  
  20. parent::__construct( $server ); 
  21.  
  22. // add customer data to order responses 
  23. add_filter( 'woocommerce_api_order_response', array( $this, 'add_customer_data' ), 10, 2 ); 
  24.  
  25. // modify WP_User_Query to support created_at date filtering 
  26. add_action( 'pre_user_query', array( $this, 'modify_user_query' ) ); 
  27.  
  28. /** 
  29. * Register the routes for this class 
  30. * GET /customers 
  31. * GET /customers/count 
  32. * GET /customers/<id> 
  33. * GET /customers/<id>/orders 
  34. * @since 2.1 
  35. * @param array $routes 
  36. * @return array 
  37. */ 
  38. public function register_routes( $routes ) { 
  39.  
  40. # GET /customers 
  41. $routes[ $this->base ] = array( 
  42. array( array( $this, 'get_customers' ), WC_API_SERVER::READABLE ),  
  43. ); 
  44.  
  45. # GET /customers/count 
  46. $routes[ $this->base . '/count'] = array( 
  47. array( array( $this, 'get_customers_count' ), WC_API_SERVER::READABLE ),  
  48. ); 
  49.  
  50. # GET /customers/<id> 
  51. $routes[ $this->base . '/(?P<id>\d+)' ] = array( 
  52. array( array( $this, 'get_customer' ), WC_API_SERVER::READABLE ),  
  53. ); 
  54.  
  55. # GET /customers/<id>/orders 
  56. $routes[ $this->base . '/(?P<id>\d+)/orders' ] = array( 
  57. array( array( $this, 'get_customer_orders' ), WC_API_SERVER::READABLE ),  
  58. ); 
  59.  
  60. return $routes; 
  61.  
  62. /** 
  63. * Get all customers 
  64. * @since 2.1 
  65. * @param array $fields 
  66. * @param array $filter 
  67. * @param int $page 
  68. * @return array 
  69. */ 
  70. public function get_customers( $fields = null, $filter = array(), $page = 1 ) { 
  71.  
  72. $filter['page'] = $page; 
  73.  
  74. $query = $this->query_customers( $filter ); 
  75.  
  76. $customers = array(); 
  77.  
  78. foreach( $query->get_results() as $user_id ) { 
  79.  
  80. if ( ! $this->is_readable( $user_id ) ) 
  81. continue; 
  82.  
  83. $customers[] = current( $this->get_customer( $user_id, $fields ) ); 
  84.  
  85. $this->server->add_pagination_headers( $query ); 
  86.  
  87. return array( 'customers' => $customers ); 
  88.  
  89. /** 
  90. * Get the customer for the given ID 
  91. * @since 2.1 
  92. * @param int $id the customer ID 
  93. * @param string $fields 
  94. * @return array 
  95. */ 
  96. public function get_customer( $id, $fields = null ) { 
  97. global $wpdb; 
  98.  
  99. $id = $this->validate_request( $id, 'customer', 'read' ); 
  100.  
  101. if ( is_wp_error( $id ) ) 
  102. return $id; 
  103.  
  104. $customer = new WP_User( $id ); 
  105.  
  106. // get info about user's last order 
  107. $last_order = $wpdb->get_row( "SELECT id, post_date_gmt 
  108. FROM $wpdb->posts AS posts 
  109. LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id 
  110. WHERE meta.meta_key = '_customer_user' 
  111. AND meta.meta_value = {$customer->ID} 
  112. AND posts.post_type = 'shop_order' 
  113. AND posts.post_status IN ( '" . implode( "', '", array_keys( wc_get_order_statuses() ) ) . "' ) 
  114. " ); 
  115.  
  116. $customer_data = array( 
  117. 'id' => $customer->ID,  
  118. 'created_at' => $this->server->format_datetime( $customer->user_registered ),  
  119. 'email' => $customer->user_email,  
  120. 'first_name' => $customer->first_name,  
  121. 'last_name' => $customer->last_name,  
  122. 'username' => $customer->user_login,  
  123. 'last_order_id' => is_object( $last_order ) ? $last_order->id : null,  
  124. 'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->post_date_gmt ) : null,  
  125. 'orders_count' => (int) $customer->_order_count,  
  126. 'total_spent' => wc_format_decimal( $customer->_money_spent, 2 ),  
  127. 'avatar_url' => $this->get_avatar_url( $customer->customer_email ),  
  128. 'billing_address' => array( 
  129. 'first_name' => $customer->billing_first_name,  
  130. 'last_name' => $customer->billing_last_name,  
  131. 'company' => $customer->billing_company,  
  132. 'address_1' => $customer->billing_address_1,  
  133. 'address_2' => $customer->billing_address_2,  
  134. 'city' => $customer->billing_city,  
  135. 'state' => $customer->billing_state,  
  136. 'postcode' => $customer->billing_postcode,  
  137. 'country' => $customer->billing_country,  
  138. 'email' => $customer->billing_email,  
  139. 'phone' => $customer->billing_phone,  
  140. ),  
  141. 'shipping_address' => array( 
  142. 'first_name' => $customer->shipping_first_name,  
  143. 'last_name' => $customer->shipping_last_name,  
  144. 'company' => $customer->shipping_company,  
  145. 'address_1' => $customer->shipping_address_1,  
  146. 'address_2' => $customer->shipping_address_2,  
  147. 'city' => $customer->shipping_city,  
  148. 'state' => $customer->shipping_state,  
  149. 'postcode' => $customer->shipping_postcode,  
  150. 'country' => $customer->shipping_country,  
  151. ),  
  152. ); 
  153.  
  154. return array( 'customer' => apply_filters( 'woocommerce_api_customer_response', $customer_data, $customer, $fields, $this->server ) ); 
  155.  
  156. /** 
  157. * Get the total number of customers 
  158. * @since 2.1 
  159. * @param array $filter 
  160. * @return array 
  161. */ 
  162. public function get_customers_count( $filter = array() ) { 
  163.  
  164. $query = $this->query_customers( $filter ); 
  165.  
  166. if ( ! current_user_can( 'list_users' ) ) 
  167. return new WP_Error( 'woocommerce_api_user_cannot_read_customers_count', __( 'You do not have permission to read the customers count', 'woocommerce' ), array( 'status' => 401 ) ); 
  168.  
  169. return array( 'count' => count( $query->get_results() ) ); 
  170.  
  171.  
  172. /** 
  173. * Create a customer 
  174. * @TODO implement in 2.2 with woocommerce_create_new_customer() 
  175. * @param array $data 
  176. * @return array 
  177. */ 
  178. public function create_customer( $data ) { 
  179.  
  180. if ( ! current_user_can( 'create_users' ) ) 
  181. return new WP_Error( 'woocommerce_api_user_cannot_create_customer', __( 'You do not have permission to create this customer', 'woocommerce' ), array( 'status' => 401 ) ); 
  182.  
  183. return array(); 
  184.  
  185. /** 
  186. * Edit a customer 
  187. * @TODO implement in 2.2 
  188. * @param int $id the customer ID 
  189. * @param array $data 
  190. * @return array 
  191. */ 
  192. public function edit_customer( $id, $data ) { 
  193.  
  194. $id = $this->validate_request( $id, 'customer', 'edit' ); 
  195.  
  196. if ( ! is_wp_error( $id ) ) 
  197. return $id; 
  198.  
  199. return $this->get_customer( $id ); 
  200.  
  201. /** 
  202. * Delete a customer 
  203. * @TODO enable along with PUT/POST in 2.2 
  204. * @param int $id the customer ID 
  205. * @return array 
  206. */ 
  207. public function delete_customer( $id ) { 
  208.  
  209. $id = $this->validate_request( $id, 'customer', 'delete' ); 
  210.  
  211. if ( ! is_wp_error( $id ) ) 
  212. return $id; 
  213.  
  214. return $this->delete( $id, 'customer' ); 
  215.  
  216. /** 
  217. * Get the orders for a customer 
  218. * @since 2.1 
  219. * @param int $id the customer ID 
  220. * @param string $fields fields to include in response 
  221. * @return array 
  222. */ 
  223. public function get_customer_orders( $id, $fields = null ) { 
  224. global $wpdb; 
  225.  
  226. $id = $this->validate_request( $id, 'customer', 'read' ); 
  227.  
  228. if ( is_wp_error( $id ) ) 
  229. return $id; 
  230.  
  231. $order_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id 
  232. FROM $wpdb->posts AS posts 
  233. LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id 
  234. WHERE meta.meta_key = '_customer_user' 
  235. AND meta.meta_value = '%s' 
  236. AND posts.post_type = 'shop_order' 
  237. AND posts.post_status = IN ( '" . implode( "', '", array_keys( wc_get_order_statuses() ) ) . "' ) 
  238. ", $id ) ); 
  239.  
  240. if ( empty( $order_ids ) ) 
  241. return array( 'orders' => array() ); 
  242.  
  243. $orders = array(); 
  244.  
  245. foreach ( $order_ids as $order_id ) { 
  246. $orders[] = current( WC()->api->WC_API_Orders->get_order( $order_id, $fields ) ); 
  247.  
  248. return array( 'orders' => apply_filters( 'woocommerce_api_customer_orders_response', $orders, $id, $fields, $order_ids, $this->server ) ); 
  249.  
  250. /** 
  251. * Helper method to get customer user objects 
  252. * Note that WP_User_Query does not have built-in pagination so limit & offset are used to provide limited 
  253. * pagination support 
  254. * @since 2.1 
  255. * @param array $args request arguments for filtering query 
  256. * @return WP_User_Query 
  257. */ 
  258. private function query_customers( $args = array() ) { 
  259.  
  260. // default users per page 
  261. $users_per_page = get_option( 'posts_per_page' ); 
  262.  
  263. // set base query arguments 
  264. $query_args = array( 
  265. 'fields' => 'ID',  
  266. 'role' => 'customer',  
  267. 'orderby' => 'registered',  
  268. 'number' => $users_per_page,  
  269. ); 
  270.  
  271. // search 
  272. if ( ! empty( $args['q'] ) ) { 
  273. $query_args['search'] = $args['q']; 
  274.  
  275. // limit number of users returned 
  276. if ( ! empty( $args['limit'] ) ) { 
  277.  
  278. $query_args['number'] = absint( $args['limit'] ); 
  279.  
  280. $users_per_page = absint( $args['limit'] ); 
  281.  
  282. // page 
  283. $page = ( isset( $args['page'] ) ) ? absint( $args['page'] ) : 1; 
  284.  
  285. // offset 
  286. if ( ! empty( $args['offset'] ) ) { 
  287. $query_args['offset'] = absint( $args['offset'] ); 
  288. } else { 
  289. $query_args['offset'] = $users_per_page * ( $page - 1 ); 
  290.  
  291. // created date 
  292. if ( ! empty( $args['created_at_min'] ) ) { 
  293. $this->created_at_min = $this->server->parse_datetime( $args['created_at_min'] ); 
  294.  
  295. if ( ! empty( $args['created_at_max'] ) ) { 
  296. $this->created_at_max = $this->server->parse_datetime( $args['created_at_max'] ); 
  297.  
  298. $query = new WP_User_Query( $query_args ); 
  299.  
  300. // helper members for pagination headers 
  301. $query->total_pages = ceil( $query->get_total() / $users_per_page ); 
  302. $query->page = $page; 
  303.  
  304. return $query; 
  305.  
  306. /** 
  307. * Add customer data to orders 
  308. * @since 2.1 
  309. * @param $order_data 
  310. * @param $order 
  311. * @return array 
  312. */ 
  313. public function add_customer_data( $order_data, $order ) { 
  314.  
  315. if ( 0 == $order->customer_user ) { 
  316.  
  317. // add customer data from order 
  318. $order_data['customer'] = array( 
  319. 'id' => 0,  
  320. 'email' => $order->billing_email,  
  321. 'first_name' => $order->billing_first_name,  
  322. 'last_name' => $order->billing_last_name,  
  323. 'billing_address' => array( 
  324. 'first_name' => $order->billing_first_name,  
  325. 'last_name' => $order->billing_last_name,  
  326. 'company' => $order->billing_company,  
  327. 'address_1' => $order->billing_address_1,  
  328. 'address_2' => $order->billing_address_2,  
  329. 'city' => $order->billing_city,  
  330. 'state' => $order->billing_state,  
  331. 'postcode' => $order->billing_postcode,  
  332. 'country' => $order->billing_country,  
  333. 'email' => $order->billing_email,  
  334. 'phone' => $order->billing_phone,  
  335. ),  
  336. 'shipping_address' => array( 
  337. 'first_name' => $order->shipping_first_name,  
  338. 'last_name' => $order->shipping_last_name,  
  339. 'company' => $order->shipping_company,  
  340. 'address_1' => $order->shipping_address_1,  
  341. 'address_2' => $order->shipping_address_2,  
  342. 'city' => $order->shipping_city,  
  343. 'state' => $order->shipping_state,  
  344. 'postcode' => $order->shipping_postcode,  
  345. 'country' => $order->shipping_country,  
  346. ),  
  347. ); 
  348.  
  349. } else { 
  350.  
  351. $order_data['customer'] = current( $this->get_customer( $order->customer_user ) ); 
  352.  
  353. return $order_data; 
  354.  
  355. /** 
  356. * Modify the WP_User_Query to support filtering on the date the customer was created 
  357. * @since 2.1 
  358. * @param WP_User_Query $query 
  359. */ 
  360. public function modify_user_query( $query ) { 
  361.  
  362. if ( $this->created_at_min ) 
  363. $query->query_where .= sprintf( " AND user_registered >= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%h:%%i:%%s' )", esc_sql( $this->created_at_min ) ); 
  364.  
  365. if ( $this->created_at_max ) 
  366. $query->query_where .= sprintf( " AND user_registered <= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%h:%%i:%%s' )", esc_sql( $this->created_at_max ) ); 
  367.  
  368. /** 
  369. * Wrapper for @see get_avatar() which doesn't simply return 
  370. * the URL so we need to pluck it from the HTML img tag 
  371. * @since 2.1 
  372. * @param string $email the customer's email 
  373. * @return string the URL to the customer's avatar 
  374. */ 
  375. private function get_avatar_url( $email ) { 
  376.  
  377. $avatar_html = get_avatar( $email ); 
  378.  
  379. // Get the URL of the avatar from the provided HTML 
  380. preg_match( '/src=["|\'](.+)[\&|"|\']/U', $avatar_html, $matches ); 
  381.  
  382. if ( isset( $matches[1] ) && ! empty( $matches[1] ) ) { 
  383. return esc_url_raw( $matches[1] ); 
  384.  
  385. return null; 
  386.  
  387. /** 
  388. * Validate the request by checking: 
  389. * 1) the ID is a valid integer 
  390. * 2) the ID returns a valid WP_User 
  391. * 3) the current user has the proper permissions 
  392. * @since 2.1 
  393. * @see WC_API_Resource::validate_request() 
  394. * @param string|int $id the customer ID 
  395. * @param string $type the request type, unused because this method overrides the parent class 
  396. * @param string $context the context of the request, either `read`, `edit` or `delete` 
  397. * @return int|WP_Error valid user ID or WP_Error if any of the checks fails 
  398. */ 
  399. protected function validate_request( $id, $type, $context ) { 
  400.  
  401. $id = absint( $id ); 
  402.  
  403. // validate ID 
  404. if ( empty( $id ) ) 
  405. return new WP_Error( 'woocommerce_api_invalid_customer_id', __( 'Invalid customer ID', 'woocommerce' ), array( 'status' => 404 ) ); 
  406.  
  407. // non-existent IDs return a valid WP_User object with the user ID = 0 
  408. $customer = new WP_User( $id ); 
  409.  
  410. if ( 0 === $customer->ID ) 
  411. return new WP_Error( 'woocommerce_api_invalid_customer', __( 'Invalid customer', 'woocommerce' ), array( 'status' => 404 ) ); 
  412.  
  413. // validate permissions 
  414. switch ( $context ) { 
  415.  
  416. case 'read': 
  417. if ( ! current_user_can( 'list_users' ) ) 
  418. return new WP_Error( 'woocommerce_api_user_cannot_read_customer', __( 'You do not have permission to read this customer', 'woocommerce' ), array( 'status' => 401 ) ); 
  419. break; 
  420.  
  421. case 'edit': 
  422. if ( ! current_user_can( 'edit_users' ) ) 
  423. return new WP_Error( 'woocommerce_api_user_cannot_edit_customer', __( 'You do not have permission to edit this customer', 'woocommerce' ), array( 'status' => 401 ) ); 
  424. break; 
  425.  
  426. case 'delete': 
  427. if ( ! current_user_can( 'delete_users' ) ) 
  428. return new WP_Error( 'woocommerce_api_user_cannot_delete_customer', __( 'You do not have permission to delete this customer', 'woocommerce' ), array( 'status' => 401 ) ); 
  429. break; 
  430.  
  431. return $id; 
  432.  
  433. /** 
  434. * Check if the current user can read users 
  435. * @since 2.1 
  436. * @see WC_API_Resource::is_readable() 
  437. * @param int|WP_Post $post unused 
  438. * @return bool true if the current user can read users, false otherwise 
  439. */ 
  440. protected function is_readable( $post ) { 
  441.  
  442. return current_user_can( 'list_users' ); 
  443.  
/includes/api/legacy/v2/class-wc-api-customers.php  
  1. class WC_API_Customers extends WC_API_Resource { 
  2.  
  3. /** @var string $base the route base */ 
  4. protected $base = '/customers'; 
  5.  
  6. /** @var string $created_at_min for date filtering */ 
  7. private $created_at_min = null; 
  8.  
  9. /** @var string $created_at_max for date filtering */ 
  10. private $created_at_max = null; 
  11.  
  12. /** 
  13. * Setup class, overridden to provide customer data to order response 
  14. * @since 2.1 
  15. * @param WC_API_Server $server 
  16. * @return WC_API_Customers 
  17. */ 
  18. public function __construct( WC_API_Server $server ) { 
  19.  
  20. parent::__construct( $server ); 
  21.  
  22. // add customer data to order responses 
  23. add_filter( 'woocommerce_api_order_response', array( $this, 'add_customer_data' ), 10, 2 ); 
  24.  
  25. // modify WP_User_Query to support created_at date filtering 
  26. add_action( 'pre_user_query', array( $this, 'modify_user_query' ) ); 
  27.  
  28. /** 
  29. * Register the routes for this class 
  30. * GET /customers 
  31. * GET /customers/count 
  32. * GET /customers/<id> 
  33. * GET /customers/<id>/orders 
  34. * @since 2.2 
  35. * @param array $routes 
  36. * @return array 
  37. */ 
  38. public function register_routes( $routes ) { 
  39.  
  40. # GET/POST /customers 
  41. $routes[ $this->base ] = array( 
  42. array( array( $this, 'get_customers' ), WC_API_SERVER::READABLE ),  
  43. array( array( $this, 'create_customer' ), WC_API_SERVER::CREATABLE | WC_API_Server::ACCEPT_DATA ),  
  44. ); 
  45.  
  46. # GET /customers/count 
  47. $routes[ $this->base . '/count'] = array( 
  48. array( array( $this, 'get_customers_count' ), WC_API_SERVER::READABLE ),  
  49. ); 
  50.  
  51. # GET/PUT/DELETE /customers/<id> 
  52. $routes[ $this->base . '/(?P<id>\d+)' ] = array( 
  53. array( array( $this, 'get_customer' ), WC_API_SERVER::READABLE ),  
  54. array( array( $this, 'edit_customer' ), WC_API_SERVER::EDITABLE | WC_API_SERVER::ACCEPT_DATA ),  
  55. array( array( $this, 'delete_customer' ), WC_API_SERVER::DELETABLE ),  
  56. ); 
  57.  
  58. # GET /customers/email/<email> 
  59. $routes[ $this->base . '/email/(?P<email>.+)' ] = array( 
  60. array( array( $this, 'get_customer_by_email' ), WC_API_SERVER::READABLE ),  
  61. ); 
  62.  
  63. # GET /customers/<id>/orders 
  64. $routes[ $this->base . '/(?P<id>\d+)/orders' ] = array( 
  65. array( array( $this, 'get_customer_orders' ), WC_API_SERVER::READABLE ),  
  66. ); 
  67.  
  68. # GET /customers/<id>/downloads 
  69. $routes[ $this->base . '/(?P<id>\d+)/downloads' ] = array( 
  70. array( array( $this, 'get_customer_downloads' ), WC_API_SERVER::READABLE ),  
  71. ); 
  72.  
  73. # POST|PUT /customers/bulk 
  74. $routes[ $this->base . '/bulk' ] = array( 
  75. array( array( $this, 'bulk' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),  
  76. ); 
  77.  
  78. return $routes; 
  79.  
  80. /** 
  81. * Get all customers 
  82. * @since 2.1 
  83. * @param array $fields 
  84. * @param array $filter 
  85. * @param int $page 
  86. * @return array 
  87. */ 
  88. public function get_customers( $fields = null, $filter = array(), $page = 1 ) { 
  89.  
  90. $filter['page'] = $page; 
  91.  
  92. $query = $this->query_customers( $filter ); 
  93.  
  94. $customers = array(); 
  95.  
  96. foreach ( $query->get_results() as $user_id ) { 
  97.  
  98. if ( ! $this->is_readable( $user_id ) ) { 
  99. continue; 
  100.  
  101. $customers[] = current( $this->get_customer( $user_id, $fields ) ); 
  102.  
  103. $this->server->add_pagination_headers( $query ); 
  104.  
  105. return array( 'customers' => $customers ); 
  106.  
  107. /** 
  108. * Get the customer for the given ID 
  109. * @since 2.1 
  110. * @param int $id the customer ID 
  111. * @param array $fields 
  112. * @return array 
  113. */ 
  114. public function get_customer( $id, $fields = null ) { 
  115. global $wpdb; 
  116.  
  117. $id = $this->validate_request( $id, 'customer', 'read' ); 
  118.  
  119. if ( is_wp_error( $id ) ) { 
  120. return $id; 
  121.  
  122. $customer = new WP_User( $id ); 
  123.  
  124. // Get info about user's last order 
  125. $last_order = $wpdb->get_row( "SELECT id, post_date_gmt 
  126. FROM $wpdb->posts AS posts 
  127. LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id 
  128. WHERE meta.meta_key = '_customer_user' 
  129. AND meta.meta_value = {$customer->ID} 
  130. AND posts.post_type = 'shop_order' 
  131. AND posts.post_status IN ( '" . implode( "', '", array_keys( wc_get_order_statuses() ) ) . "' ) 
  132. ORDER BY posts.ID DESC 
  133. " ); 
  134.  
  135. $roles = array_values( $customer->roles ); 
  136.  
  137. $customer_data = array( 
  138. 'id' => $customer->ID,  
  139. 'created_at' => $this->server->format_datetime( $customer->user_registered ),  
  140. 'email' => $customer->user_email,  
  141. 'first_name' => $customer->first_name,  
  142. 'last_name' => $customer->last_name,  
  143. 'username' => $customer->user_login,  
  144. 'role' => $roles[0],  
  145. 'last_order_id' => is_object( $last_order ) ? $last_order->id : null,  
  146. 'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->post_date_gmt ) : null,  
  147. 'orders_count' => wc_get_customer_order_count( $customer->ID ),  
  148. 'total_spent' => wc_format_decimal( wc_get_customer_total_spent( $customer->ID ), 2 ),  
  149. 'avatar_url' => $this->get_avatar_url( $customer->customer_email ),  
  150. 'billing_address' => array( 
  151. 'first_name' => $customer->billing_first_name,  
  152. 'last_name' => $customer->billing_last_name,  
  153. 'company' => $customer->billing_company,  
  154. 'address_1' => $customer->billing_address_1,  
  155. 'address_2' => $customer->billing_address_2,  
  156. 'city' => $customer->billing_city,  
  157. 'state' => $customer->billing_state,  
  158. 'postcode' => $customer->billing_postcode,  
  159. 'country' => $customer->billing_country,  
  160. 'email' => $customer->billing_email,  
  161. 'phone' => $customer->billing_phone,  
  162. ),  
  163. 'shipping_address' => array( 
  164. 'first_name' => $customer->shipping_first_name,  
  165. 'last_name' => $customer->shipping_last_name,  
  166. 'company' => $customer->shipping_company,  
  167. 'address_1' => $customer->shipping_address_1,  
  168. 'address_2' => $customer->shipping_address_2,  
  169. 'city' => $customer->shipping_city,  
  170. 'state' => $customer->shipping_state,  
  171. 'postcode' => $customer->shipping_postcode,  
  172. 'country' => $customer->shipping_country,  
  173. ),  
  174. ); 
  175.  
  176. return array( 'customer' => apply_filters( 'woocommerce_api_customer_response', $customer_data, $customer, $fields, $this->server ) ); 
  177.  
  178. /** 
  179. * Get the customer for the given email 
  180. * @since 2.1 
  181. * @param string $email the customer email 
  182. * @param array $fields 
  183. * @return array 
  184. */ 
  185. public function get_customer_by_email( $email, $fields = null ) { 
  186. try { 
  187. if ( is_email( $email ) ) { 
  188. $customer = get_user_by( 'email', $email ); 
  189. if ( ! is_object( $customer ) ) { 
  190. throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer Email', 'woocommerce' ), 404 ); 
  191. } else { 
  192. throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer Email', 'woocommerce' ), 404 ); 
  193.  
  194. return $this->get_customer( $customer->ID, $fields ); 
  195. } catch ( WC_API_Exception $e ) { 
  196. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  197.  
  198. /** 
  199. * Get the total number of customers 
  200. * @since 2.1 
  201. * @param array $filter 
  202. * @return array 
  203. */ 
  204. public function get_customers_count( $filter = array() ) { 
  205. try { 
  206. if ( ! current_user_can( 'list_users' ) ) { 
  207. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_customers_count', __( 'You do not have permission to read the customers count', 'woocommerce' ), 401 ); 
  208.  
  209. $query = $this->query_customers( $filter ); 
  210.  
  211. return array( 'count' => $query->get_total() ); 
  212. } catch ( WC_API_Exception $e ) { 
  213. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  214.  
  215. /** 
  216. * Get customer billing address fields. 
  217. * @since 2.2 
  218. * @return array 
  219. */ 
  220. protected function get_customer_billing_address() { 
  221. $billing_address = apply_filters( 'woocommerce_api_customer_billing_address', array( 
  222. 'first_name',  
  223. 'last_name',  
  224. 'company',  
  225. 'address_1',  
  226. 'address_2',  
  227. 'city',  
  228. 'state',  
  229. 'postcode',  
  230. 'country',  
  231. 'email',  
  232. 'phone',  
  233. ) ); 
  234.  
  235. return $billing_address; 
  236.  
  237. /** 
  238. * Get customer shipping address fields. 
  239. * @since 2.2 
  240. * @return array 
  241. */ 
  242. protected function get_customer_shipping_address() { 
  243. $shipping_address = apply_filters( 'woocommerce_api_customer_shipping_address', array( 
  244. 'first_name',  
  245. 'last_name',  
  246. 'company',  
  247. 'address_1',  
  248. 'address_2',  
  249. 'city',  
  250. 'state',  
  251. 'postcode',  
  252. 'country',  
  253. ) ); 
  254.  
  255. return $shipping_address; 
  256.  
  257. /** 
  258. * Add/Update customer data. 
  259. * @since 2.2 
  260. * @param int $id the customer ID 
  261. * @param array $data 
  262. */ 
  263. protected function update_customer_data( $id, $data ) { 
  264. // Customer first name. 
  265. if ( isset( $data['first_name'] ) ) { 
  266. update_user_meta( $id, 'first_name', wc_clean( $data['first_name'] ) ); 
  267.  
  268. // Customer last name. 
  269. if ( isset( $data['last_name'] ) ) { 
  270. update_user_meta( $id, 'last_name', wc_clean( $data['last_name'] ) ); 
  271.  
  272. // Customer billing address. 
  273. if ( isset( $data['billing_address'] ) ) { 
  274. foreach ( $this->get_customer_billing_address() as $address ) { 
  275. if ( isset( $data['billing_address'][ $address ] ) ) { 
  276. update_user_meta( $id, 'billing_' . $address, wc_clean( $data['billing_address'][ $address ] ) ); 
  277.  
  278. // Customer shipping address. 
  279. if ( isset( $data['shipping_address'] ) ) { 
  280. foreach ( $this->get_customer_shipping_address() as $address ) { 
  281. if ( isset( $data['shipping_address'][ $address ] ) ) { 
  282. update_user_meta( $id, 'shipping_' . $address, wc_clean( $data['shipping_address'][ $address ] ) ); 
  283.  
  284. do_action( 'woocommerce_api_update_customer_data', $id, $data ); 
  285.  
  286. /** 
  287. * Create a customer 
  288. * @since 2.2 
  289. * @param array $data 
  290. * @return array 
  291. */ 
  292. public function create_customer( $data ) { 
  293. try { 
  294. if ( ! isset( $data['customer'] ) ) { 
  295. throw new WC_API_Exception( 'woocommerce_api_missing_customer_data', sprintf( __( 'No %1$s data specified to create %1$s', 'woocommerce' ), 'customer' ), 400 ); 
  296.  
  297. $data = $data['customer']; 
  298.  
  299. // Checks with can create new users. 
  300. if ( ! current_user_can( 'create_users' ) ) { 
  301. throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_customer', __( 'You do not have permission to create this customer', 'woocommerce' ), 401 ); 
  302.  
  303. $data = apply_filters( 'woocommerce_api_create_customer_data', $data, $this ); 
  304.  
  305. // Checks with the email is missing. 
  306. if ( ! isset( $data['email'] ) ) { 
  307. throw new WC_API_Exception( 'woocommerce_api_missing_customer_email', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'email' ), 400 ); 
  308.  
  309. // Sets the username. 
  310. $data['username'] = ! empty( $data['username'] ) ? $data['username'] : ''; 
  311.  
  312. // Sets the password. 
  313. $data['password'] = ! empty( $data['password'] ) ? $data['password'] : ''; 
  314.  
  315. // Attempts to create the new customer 
  316. $id = wc_create_new_customer( $data['email'], $data['username'], $data['password'] ); 
  317.  
  318. // Checks for an error in the customer creation. 
  319. if ( is_wp_error( $id ) ) { 
  320. throw new WC_API_Exception( $id->get_error_code(), $id->get_error_message(), 400 ); 
  321.  
  322. // Added customer data. 
  323. $this->update_customer_data( $id, $data ); 
  324.  
  325. do_action( 'woocommerce_api_create_customer', $id, $data ); 
  326.  
  327. $this->server->send_status( 201 ); 
  328.  
  329. return $this->get_customer( $id ); 
  330. } catch ( WC_API_Exception $e ) { 
  331. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  332.  
  333. /** 
  334. * Edit a customer 
  335. * @since 2.2 
  336. * @param int $id the customer ID 
  337. * @param array $data 
  338. * @return array 
  339. */ 
  340. public function edit_customer( $id, $data ) { 
  341. try { 
  342. if ( ! isset( $data['customer'] ) ) { 
  343. throw new WC_API_Exception( 'woocommerce_api_missing_customer_data', sprintf( __( 'No %1$s data specified to edit %1$s', 'woocommerce' ), 'customer' ), 400 ); 
  344.  
  345. $data = $data['customer']; 
  346.  
  347. // Validate the customer ID. 
  348. $id = $this->validate_request( $id, 'customer', 'edit' ); 
  349.  
  350. // Return the validate error. 
  351. if ( is_wp_error( $id ) ) { 
  352. throw new WC_API_Exception( $id->get_error_code(), $id->get_error_message(), 400 ); 
  353.  
  354. $data = apply_filters( 'woocommerce_api_edit_customer_data', $data, $this ); 
  355.  
  356. // Customer email. 
  357. if ( isset( $data['email'] ) ) { 
  358. wp_update_user( array( 'ID' => $id, 'user_email' => sanitize_email( $data['email'] ) ) ); 
  359.  
  360. // Customer password. 
  361. if ( isset( $data['password'] ) ) { 
  362. wp_update_user( array( 'ID' => $id, 'user_pass' => wc_clean( $data['password'] ) ) ); 
  363.  
  364. // Update customer data. 
  365. $this->update_customer_data( $id, $data ); 
  366.  
  367. do_action( 'woocommerce_api_edit_customer', $id, $data ); 
  368.  
  369. return $this->get_customer( $id ); 
  370. } catch ( WC_API_Exception $e ) { 
  371. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  372.  
  373. /** 
  374. * Delete a customer 
  375. * @since 2.2 
  376. * @param int $id the customer ID 
  377. * @return array 
  378. */ 
  379. public function delete_customer( $id ) { 
  380.  
  381. // Validate the customer ID. 
  382. $id = $this->validate_request( $id, 'customer', 'delete' ); 
  383.  
  384. // Return the validate error. 
  385. if ( is_wp_error( $id ) ) { 
  386. return $id; 
  387.  
  388. do_action( 'woocommerce_api_delete_customer', $id, $this ); 
  389.  
  390. return $this->delete( $id, 'customer' ); 
  391.  
  392. /** 
  393. * Get the orders for a customer 
  394. * @since 2.1 
  395. * @param int $id the customer ID 
  396. * @param string $fields fields to include in response 
  397. * @return array 
  398. */ 
  399. public function get_customer_orders( $id, $fields = null ) { 
  400. global $wpdb; 
  401.  
  402. $id = $this->validate_request( $id, 'customer', 'read' ); 
  403.  
  404. if ( is_wp_error( $id ) ) { 
  405. return $id; 
  406.  
  407. $order_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id 
  408. FROM $wpdb->posts AS posts 
  409. LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id 
  410. WHERE meta.meta_key = '_customer_user' 
  411. AND meta.meta_value = '%s' 
  412. AND posts.post_type = 'shop_order' 
  413. AND posts.post_status IN ( '" . implode( "', '", array_keys( wc_get_order_statuses() ) ) . "' ) 
  414. ", $id ) ); 
  415.  
  416. if ( empty( $order_ids ) ) { 
  417. return array( 'orders' => array() ); 
  418.  
  419. $orders = array(); 
  420.  
  421. foreach ( $order_ids as $order_id ) { 
  422. $orders[] = current( WC()->api->WC_API_Orders->get_order( $order_id, $fields ) ); 
  423.  
  424. return array( 'orders' => apply_filters( 'woocommerce_api_customer_orders_response', $orders, $id, $fields, $order_ids, $this->server ) ); 
  425.  
  426. /** 
  427. * Get the available downloads for a customer 
  428. * @since 2.2 
  429. * @param int $id the customer ID 
  430. * @param string $fields fields to include in response 
  431. * @return array 
  432. */ 
  433. public function get_customer_downloads( $id, $fields = null ) { 
  434. $id = $this->validate_request( $id, 'customer', 'read' ); 
  435.  
  436. if ( is_wp_error( $id ) ) { 
  437. return $id; 
  438.  
  439. $downloads = array(); 
  440. $_downloads = wc_get_customer_available_downloads( $id ); 
  441.  
  442. foreach ( $_downloads as $key => $download ) { 
  443. $downloads[ $key ] = $download; 
  444. $downloads[ $key ]['access_expires'] = $this->server->format_datetime( $downloads[ $key ]['access_expires'] ); 
  445.  
  446. return array( 'downloads' => apply_filters( 'woocommerce_api_customer_downloads_response', $downloads, $id, $fields, $this->server ) ); 
  447.  
  448. /** 
  449. * Helper method to get customer user objects 
  450. * Note that WP_User_Query does not have built-in pagination so limit & offset are used to provide limited 
  451. * pagination support 
  452. * The filter for role can only be a single role in a string. 
  453. * @since 2.3 
  454. * @param array $args request arguments for filtering query 
  455. * @return WP_User_Query 
  456. */ 
  457. private function query_customers( $args = array() ) { 
  458.  
  459. // default users per page 
  460. $users_per_page = get_option( 'posts_per_page' ); 
  461.  
  462. // Set base query arguments 
  463. $query_args = array( 
  464. 'fields' => 'ID',  
  465. 'role' => 'customer',  
  466. 'orderby' => 'registered',  
  467. 'number' => $users_per_page,  
  468. ); 
  469.  
  470. // Custom Role 
  471. if ( ! empty( $args['role'] ) ) { 
  472. $query_args['role'] = $args['role']; 
  473.  
  474. // Search 
  475. if ( ! empty( $args['q'] ) ) { 
  476. $query_args['search'] = $args['q']; 
  477.  
  478. // Limit number of users returned 
  479. if ( ! empty( $args['limit'] ) ) { 
  480. if ( $args['limit'] == -1 ) { 
  481. unset( $query_args['number'] ); 
  482. } else { 
  483. $query_args['number'] = absint( $args['limit'] ); 
  484. $users_per_page = absint( $args['limit'] ); 
  485. } else { 
  486. $args['limit'] = $query_args['number']; 
  487.  
  488. // Page 
  489. $page = ( isset( $args['page'] ) ) ? absint( $args['page'] ) : 1; 
  490.  
  491. // Offset 
  492. if ( ! empty( $args['offset'] ) ) { 
  493. $query_args['offset'] = absint( $args['offset'] ); 
  494. } else { 
  495. $query_args['offset'] = $users_per_page * ( $page - 1 ); 
  496.  
  497. // Created date 
  498. if ( ! empty( $args['created_at_min'] ) ) { 
  499. $this->created_at_min = $this->server->parse_datetime( $args['created_at_min'] ); 
  500.  
  501. if ( ! empty( $args['created_at_max'] ) ) { 
  502. $this->created_at_max = $this->server->parse_datetime( $args['created_at_max'] ); 
  503.  
  504. // Order (ASC or DESC, ASC by default) 
  505. if ( ! empty( $args['order'] ) ) { 
  506. $query_args['order'] = $args['order']; 
  507.  
  508. // Orderby 
  509. if ( ! empty( $args['orderby'] ) ) { 
  510. $query_args['orderby'] = $args['orderby']; 
  511.  
  512. // Allow sorting by meta value 
  513. if ( ! empty( $args['orderby_meta_key'] ) ) { 
  514. $query_args['meta_key'] = $args['orderby_meta_key']; 
  515.  
  516. $query = new WP_User_Query( $query_args ); 
  517.  
  518. // Helper members for pagination headers 
  519. $query->total_pages = ( $args['limit'] == -1 ) ? 1 : ceil( $query->get_total() / $users_per_page ); 
  520. $query->page = $page; 
  521.  
  522. return $query; 
  523.  
  524. /** 
  525. * Add customer data to orders 
  526. * @since 2.1 
  527. * @param $order_data 
  528. * @param $order 
  529. * @return array 
  530. */ 
  531. public function add_customer_data( $order_data, $order ) { 
  532.  
  533. if ( 0 == $order->customer_user ) { 
  534.  
  535. // add customer data from order 
  536. $order_data['customer'] = array( 
  537. 'id' => 0,  
  538. 'email' => $order->billing_email,  
  539. 'first_name' => $order->billing_first_name,  
  540. 'last_name' => $order->billing_last_name,  
  541. 'billing_address' => array( 
  542. 'first_name' => $order->billing_first_name,  
  543. 'last_name' => $order->billing_last_name,  
  544. 'company' => $order->billing_company,  
  545. 'address_1' => $order->billing_address_1,  
  546. 'address_2' => $order->billing_address_2,  
  547. 'city' => $order->billing_city,  
  548. 'state' => $order->billing_state,  
  549. 'postcode' => $order->billing_postcode,  
  550. 'country' => $order->billing_country,  
  551. 'email' => $order->billing_email,  
  552. 'phone' => $order->billing_phone,  
  553. ),  
  554. 'shipping_address' => array( 
  555. 'first_name' => $order->shipping_first_name,  
  556. 'last_name' => $order->shipping_last_name,  
  557. 'company' => $order->shipping_company,  
  558. 'address_1' => $order->shipping_address_1,  
  559. 'address_2' => $order->shipping_address_2,  
  560. 'city' => $order->shipping_city,  
  561. 'state' => $order->shipping_state,  
  562. 'postcode' => $order->shipping_postcode,  
  563. 'country' => $order->shipping_country,  
  564. ),  
  565. ); 
  566.  
  567. } else { 
  568.  
  569. $order_data['customer'] = current( $this->get_customer( $order->customer_user ) ); 
  570.  
  571. return $order_data; 
  572.  
  573. /** 
  574. * Modify the WP_User_Query to support filtering on the date the customer was created 
  575. * @since 2.1 
  576. * @param WP_User_Query $query 
  577. */ 
  578. public function modify_user_query( $query ) { 
  579.  
  580. if ( $this->created_at_min ) { 
  581. $query->query_where .= sprintf( " AND user_registered >= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%H:%%i:%%s' )", esc_sql( $this->created_at_min ) ); 
  582.  
  583. if ( $this->created_at_max ) { 
  584. $query->query_where .= sprintf( " AND user_registered <= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%H:%%i:%%s' )", esc_sql( $this->created_at_max ) ); 
  585.  
  586. /** 
  587. * Wrapper for @see get_avatar() which doesn't simply return 
  588. * the URL so we need to pluck it from the HTML img tag 
  589. * Kudos to https://github.com/WP-API/WP-API for offering a better solution 
  590. * @since 2.1 
  591. * @param string $email the customer's email 
  592. * @return string the URL to the customer's avatar 
  593. */ 
  594. private function get_avatar_url( $email ) { 
  595. $avatar_html = get_avatar( $email ); 
  596.  
  597. // Get the URL of the avatar from the provided HTML 
  598. preg_match( '/src=["|\'](.+)[\&|"|\']/U', $avatar_html, $matches ); 
  599.  
  600. if ( isset( $matches[1] ) && ! empty( $matches[1] ) ) { 
  601. return esc_url_raw( $matches[1] ); 
  602.  
  603. return null; 
  604.  
  605. /** 
  606. * Validate the request by checking: 
  607. * 1) the ID is a valid integer 
  608. * 2) the ID returns a valid WP_User 
  609. * 3) the current user has the proper permissions 
  610. * @since 2.1 
  611. * @see WC_API_Resource::validate_request() 
  612. * @param integer $id the customer ID 
  613. * @param string $type the request type, unused because this method overrides the parent class 
  614. * @param string $context the context of the request, either `read`, `edit` or `delete` 
  615. * @return int|WP_Error valid user ID or WP_Error if any of the checks fails 
  616. */ 
  617. protected function validate_request( $id, $type, $context ) { 
  618.  
  619. try { 
  620. $id = absint( $id ); 
  621.  
  622. // validate ID 
  623. if ( empty( $id ) ) { 
  624. throw new WC_API_Exception( 'woocommerce_api_invalid_customer_id', __( 'Invalid customer ID', 'woocommerce' ), 404 ); 
  625.  
  626. // non-existent IDs return a valid WP_User object with the user ID = 0 
  627. $customer = new WP_User( $id ); 
  628.  
  629. if ( 0 === $customer->ID ) { 
  630. throw new WC_API_Exception( 'woocommerce_api_invalid_customer', __( 'Invalid customer', 'woocommerce' ), 404 ); 
  631.  
  632. // validate permissions 
  633. switch ( $context ) { 
  634.  
  635. case 'read': 
  636. if ( ! current_user_can( 'list_users' ) ) { 
  637. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_customer', __( 'You do not have permission to read this customer', 'woocommerce' ), 401 ); 
  638. break; 
  639.  
  640. case 'edit': 
  641. if ( ! current_user_can( 'edit_users' ) ) { 
  642. throw new WC_API_Exception( 'woocommerce_api_user_cannot_edit_customer', __( 'You do not have permission to edit this customer', 'woocommerce' ), 401 ); 
  643. break; 
  644.  
  645. case 'delete': 
  646. if ( ! current_user_can( 'delete_users' ) ) { 
  647. throw new WC_API_Exception( 'woocommerce_api_user_cannot_delete_customer', __( 'You do not have permission to delete this customer', 'woocommerce' ), 401 ); 
  648. break; 
  649.  
  650. return $id; 
  651. } catch ( WC_API_Exception $e ) { 
  652. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  653.  
  654. /** 
  655. * Check if the current user can read users 
  656. * @since 2.1 
  657. * @see WC_API_Resource::is_readable() 
  658. * @param int|WP_Post $post unused 
  659. * @return bool true if the current user can read users, false otherwise 
  660. */ 
  661. protected function is_readable( $post ) { 
  662. return current_user_can( 'list_users' ); 
  663.  
  664. /** 
  665. * Bulk update or insert customers 
  666. * Accepts an array with customers in the formats supported by 
  667. * WC_API_Customers->create_customer() and WC_API_Customers->edit_customer() 
  668. * @since 2.4.0 
  669. * @param array $data 
  670. * @return array 
  671. */ 
  672. public function bulk( $data ) { 
  673.  
  674. try { 
  675. if ( ! isset( $data['customers'] ) ) { 
  676. throw new WC_API_Exception( 'woocommerce_api_missing_customers_data', sprintf( __( 'No %1$s data specified to create/edit %1$s', 'woocommerce' ), 'customers' ), 400 ); 
  677.  
  678. $data = $data['customers']; 
  679. $limit = apply_filters( 'woocommerce_api_bulk_limit', 100, 'customers' ); 
  680.  
  681. // Limit bulk operation 
  682. if ( count( $data ) > $limit ) { 
  683. throw new WC_API_Exception( 'woocommerce_api_customers_request_entity_too_large', sprintf( __( 'Unable to accept more than %s items for this request', 'woocommerce' ), $limit ), 413 ); 
  684.  
  685. $customers = array(); 
  686.  
  687. foreach ( $data as $_customer ) { 
  688. $customer_id = 0; 
  689.  
  690. // Try to get the customer ID 
  691. if ( isset( $_customer['id'] ) ) { 
  692. $customer_id = intval( $_customer['id'] ); 
  693.  
  694. // Customer exists / edit customer 
  695. if ( $customer_id ) { 
  696. $edit = $this->edit_customer( $customer_id, array( 'customer' => $_customer ) ); 
  697.  
  698. if ( is_wp_error( $edit ) ) { 
  699. $customers[] = array( 
  700. 'id' => $customer_id,  
  701. 'error' => array( 'code' => $edit->get_error_code(), 'message' => $edit->get_error_message() ) 
  702. ); 
  703. } else { 
  704. $customers[] = $edit['customer']; 
  705.  
  706. // Customer don't exists / create customer 
  707. else { 
  708. $new = $this->create_customer( array( 'customer' => $_customer ) ); 
  709.  
  710. if ( is_wp_error( $new ) ) { 
  711. $customers[] = array( 
  712. 'id' => $customer_id,  
  713. 'error' => array( 'code' => $new->get_error_code(), 'message' => $new->get_error_message() ) 
  714. ); 
  715. } else { 
  716. $customers[] = $new['customer']; 
  717.  
  718. return array( 'customers' => apply_filters( 'woocommerce_api_customers_bulk_response', $customers, $this ) ); 
  719. } catch ( WC_API_Exception $e ) { 
  720. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
/includes/api/legacy/v3/class-wc-api-customers.php  
  1. class WC_API_Customers extends WC_API_Resource { 
  2.  
  3. /** @var string $base the route base */ 
  4. protected $base = '/customers'; 
  5.  
  6. /** @var string $created_at_min for date filtering */ 
  7. private $created_at_min = null; 
  8.  
  9. /** @var string $created_at_max for date filtering */ 
  10. private $created_at_max = null; 
  11.  
  12. /** 
  13. * Setup class, overridden to provide customer data to order response 
  14. * @since 2.1 
  15. * @param WC_API_Server $server 
  16. * @return WC_API_Customers 
  17. */ 
  18. public function __construct( WC_API_Server $server ) { 
  19.  
  20. parent::__construct( $server ); 
  21.  
  22. // add customer data to order responses 
  23. add_filter( 'woocommerce_api_order_response', array( $this, 'add_customer_data' ), 10, 2 ); 
  24.  
  25. // modify WP_User_Query to support created_at date filtering 
  26. add_action( 'pre_user_query', array( $this, 'modify_user_query' ) ); 
  27.  
  28. /** 
  29. * Register the routes for this class 
  30. * GET /customers 
  31. * GET /customers/count 
  32. * GET /customers/<id> 
  33. * GET /customers/<id>/orders 
  34. * @since 2.2 
  35. * @param array $routes 
  36. * @return array 
  37. */ 
  38. public function register_routes( $routes ) { 
  39.  
  40. # GET/POST /customers 
  41. $routes[ $this->base ] = array( 
  42. array( array( $this, 'get_customers' ), WC_API_SERVER::READABLE ),  
  43. array( array( $this, 'create_customer' ), WC_API_SERVER::CREATABLE | WC_API_Server::ACCEPT_DATA ),  
  44. ); 
  45.  
  46. # GET /customers/count 
  47. $routes[ $this->base . '/count'] = array( 
  48. array( array( $this, 'get_customers_count' ), WC_API_SERVER::READABLE ),  
  49. ); 
  50.  
  51. # GET/PUT/DELETE /customers/<id> 
  52. $routes[ $this->base . '/(?P<id>\d+)' ] = array( 
  53. array( array( $this, 'get_customer' ), WC_API_SERVER::READABLE ),  
  54. array( array( $this, 'edit_customer' ), WC_API_SERVER::EDITABLE | WC_API_SERVER::ACCEPT_DATA ),  
  55. array( array( $this, 'delete_customer' ), WC_API_SERVER::DELETABLE ),  
  56. ); 
  57.  
  58. # GET /customers/email/<email> 
  59. $routes[ $this->base . '/email/(?P<email>.+)' ] = array( 
  60. array( array( $this, 'get_customer_by_email' ), WC_API_SERVER::READABLE ),  
  61. ); 
  62.  
  63. # GET /customers/<id>/orders 
  64. $routes[ $this->base . '/(?P<id>\d+)/orders' ] = array( 
  65. array( array( $this, 'get_customer_orders' ), WC_API_SERVER::READABLE ),  
  66. ); 
  67.  
  68. # GET /customers/<id>/downloads 
  69. $routes[ $this->base . '/(?P<id>\d+)/downloads' ] = array( 
  70. array( array( $this, 'get_customer_downloads' ), WC_API_SERVER::READABLE ),  
  71. ); 
  72.  
  73. # POST|PUT /customers/bulk 
  74. $routes[ $this->base . '/bulk' ] = array( 
  75. array( array( $this, 'bulk' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),  
  76. ); 
  77.  
  78. return $routes; 
  79.  
  80. /** 
  81. * Get all customers 
  82. * @since 2.1 
  83. * @param array $fields 
  84. * @param array $filter 
  85. * @param int $page 
  86. * @return array 
  87. */ 
  88. public function get_customers( $fields = null, $filter = array(), $page = 1 ) { 
  89.  
  90. $filter['page'] = $page; 
  91.  
  92. $query = $this->query_customers( $filter ); 
  93.  
  94. $customers = array(); 
  95.  
  96. foreach ( $query->get_results() as $user_id ) { 
  97.  
  98. if ( ! $this->is_readable( $user_id ) ) { 
  99. continue; 
  100.  
  101. $customers[] = current( $this->get_customer( $user_id, $fields ) ); 
  102.  
  103. $this->server->add_pagination_headers( $query ); 
  104.  
  105. return array( 'customers' => $customers ); 
  106.  
  107. /** 
  108. * Get the customer for the given ID 
  109. * @since 2.1 
  110. * @param int $id the customer ID 
  111. * @param array $fields 
  112. * @return array 
  113. */ 
  114. public function get_customer( $id, $fields = null ) { 
  115. global $wpdb; 
  116.  
  117. $id = $this->validate_request( $id, 'customer', 'read' ); 
  118.  
  119. if ( is_wp_error( $id ) ) { 
  120. return $id; 
  121.  
  122. $customer = new WP_User( $id ); 
  123.  
  124. // Get info about user's last order 
  125. $last_order = $wpdb->get_row( "SELECT id, post_date_gmt 
  126. FROM $wpdb->posts AS posts 
  127. LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id 
  128. WHERE meta.meta_key = '_customer_user' 
  129. AND meta.meta_value = {$customer->ID} 
  130. AND posts.post_type = 'shop_order' 
  131. AND posts.post_status IN ( '" . implode( "', '", array_keys( wc_get_order_statuses() ) ) . "' ) 
  132. ORDER BY posts.ID DESC 
  133. " ); 
  134.  
  135. $roles = array_values( $customer->roles ); 
  136.  
  137. $customer_data = array( 
  138. 'id' => $customer->ID,  
  139. 'created_at' => $this->server->format_datetime( $customer->user_registered ),  
  140. 'last_update' => $this->server->format_datetime( get_user_meta( $customer->ID, 'last_update', true ) ),  
  141. 'email' => $customer->user_email,  
  142. 'first_name' => $customer->first_name,  
  143. 'last_name' => $customer->last_name,  
  144. 'username' => $customer->user_login,  
  145. 'role' => $roles[0],  
  146. 'last_order_id' => is_object( $last_order ) ? $last_order->id : null,  
  147. 'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->post_date_gmt ) : null,  
  148. 'orders_count' => wc_get_customer_order_count( $customer->ID ),  
  149. 'total_spent' => wc_format_decimal( wc_get_customer_total_spent( $customer->ID ), 2 ),  
  150. 'avatar_url' => $this->get_avatar_url( $customer->customer_email ),  
  151. 'billing_address' => array( 
  152. 'first_name' => $customer->billing_first_name,  
  153. 'last_name' => $customer->billing_last_name,  
  154. 'company' => $customer->billing_company,  
  155. 'address_1' => $customer->billing_address_1,  
  156. 'address_2' => $customer->billing_address_2,  
  157. 'city' => $customer->billing_city,  
  158. 'state' => $customer->billing_state,  
  159. 'postcode' => $customer->billing_postcode,  
  160. 'country' => $customer->billing_country,  
  161. 'email' => $customer->billing_email,  
  162. 'phone' => $customer->billing_phone,  
  163. ),  
  164. 'shipping_address' => array( 
  165. 'first_name' => $customer->shipping_first_name,  
  166. 'last_name' => $customer->shipping_last_name,  
  167. 'company' => $customer->shipping_company,  
  168. 'address_1' => $customer->shipping_address_1,  
  169. 'address_2' => $customer->shipping_address_2,  
  170. 'city' => $customer->shipping_city,  
  171. 'state' => $customer->shipping_state,  
  172. 'postcode' => $customer->shipping_postcode,  
  173. 'country' => $customer->shipping_country,  
  174. ),  
  175. ); 
  176.  
  177. return array( 'customer' => apply_filters( 'woocommerce_api_customer_response', $customer_data, $customer, $fields, $this->server ) ); 
  178.  
  179. /** 
  180. * Get the customer for the given email 
  181. * @since 2.1 
  182. * @param string $email the customer email 
  183. * @param array $fields 
  184. * @return array 
  185. */ 
  186. public function get_customer_by_email( $email, $fields = null ) { 
  187. try { 
  188. if ( is_email( $email ) ) { 
  189. $customer = get_user_by( 'email', $email ); 
  190. if ( ! is_object( $customer ) ) { 
  191. throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer Email', 'woocommerce' ), 404 ); 
  192. } else { 
  193. throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer Email', 'woocommerce' ), 404 ); 
  194.  
  195. return $this->get_customer( $customer->ID, $fields ); 
  196. } catch ( WC_API_Exception $e ) { 
  197. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  198.  
  199. /** 
  200. * Get the total number of customers 
  201. * @since 2.1 
  202. * @param array $filter 
  203. * @return array 
  204. */ 
  205. public function get_customers_count( $filter = array() ) { 
  206. try { 
  207. if ( ! current_user_can( 'list_users' ) ) { 
  208. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_customers_count', __( 'You do not have permission to read the customers count', 'woocommerce' ), 401 ); 
  209.  
  210. $query = $this->query_customers( $filter ); 
  211.  
  212. return array( 'count' => $query->get_total() ); 
  213. } catch ( WC_API_Exception $e ) { 
  214. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  215.  
  216. /** 
  217. * Get customer billing address fields. 
  218. * @since 2.2 
  219. * @return array 
  220. */ 
  221. protected function get_customer_billing_address() { 
  222. $billing_address = apply_filters( 'woocommerce_api_customer_billing_address', array( 
  223. 'first_name',  
  224. 'last_name',  
  225. 'company',  
  226. 'address_1',  
  227. 'address_2',  
  228. 'city',  
  229. 'state',  
  230. 'postcode',  
  231. 'country',  
  232. 'email',  
  233. 'phone',  
  234. ) ); 
  235.  
  236. return $billing_address; 
  237.  
  238. /** 
  239. * Get customer shipping address fields. 
  240. * @since 2.2 
  241. * @return array 
  242. */ 
  243. protected function get_customer_shipping_address() { 
  244. $shipping_address = apply_filters( 'woocommerce_api_customer_shipping_address', array( 
  245. 'first_name',  
  246. 'last_name',  
  247. 'company',  
  248. 'address_1',  
  249. 'address_2',  
  250. 'city',  
  251. 'state',  
  252. 'postcode',  
  253. 'country',  
  254. ) ); 
  255.  
  256. return $shipping_address; 
  257.  
  258. /** 
  259. * Add/Update customer data. 
  260. * @since 2.2 
  261. * @param int $id the customer ID 
  262. * @param array $data 
  263. */ 
  264. protected function update_customer_data( $id, $data ) { 
  265. // Customer first name. 
  266. if ( isset( $data['first_name'] ) ) { 
  267. update_user_meta( $id, 'first_name', wc_clean( $data['first_name'] ) ); 
  268.  
  269. // Customer last name. 
  270. if ( isset( $data['last_name'] ) ) { 
  271. update_user_meta( $id, 'last_name', wc_clean( $data['last_name'] ) ); 
  272.  
  273. // Customer billing address. 
  274. if ( isset( $data['billing_address'] ) ) { 
  275. foreach ( $this->get_customer_billing_address() as $address ) { 
  276. if ( isset( $data['billing_address'][ $address ] ) ) { 
  277. update_user_meta( $id, 'billing_' . $address, wc_clean( $data['billing_address'][ $address ] ) ); 
  278.  
  279. // Customer shipping address. 
  280. if ( isset( $data['shipping_address'] ) ) { 
  281. foreach ( $this->get_customer_shipping_address() as $address ) { 
  282. if ( isset( $data['shipping_address'][ $address ] ) ) { 
  283. update_user_meta( $id, 'shipping_' . $address, wc_clean( $data['shipping_address'][ $address ] ) ); 
  284.  
  285. do_action( 'woocommerce_api_update_customer_data', $id, $data ); 
  286.  
  287. /** 
  288. * Create a customer 
  289. * @since 2.2 
  290. * @param array $data 
  291. * @return array 
  292. */ 
  293. public function create_customer( $data ) { 
  294. try { 
  295. if ( ! isset( $data['customer'] ) ) { 
  296. throw new WC_API_Exception( 'woocommerce_api_missing_customer_data', sprintf( __( 'No %1$s data specified to create %1$s', 'woocommerce' ), 'customer' ), 400 ); 
  297.  
  298. $data = $data['customer']; 
  299.  
  300. // Checks with can create new users. 
  301. if ( ! current_user_can( 'create_users' ) ) { 
  302. throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_customer', __( 'You do not have permission to create this customer', 'woocommerce' ), 401 ); 
  303.  
  304. $data = apply_filters( 'woocommerce_api_create_customer_data', $data, $this ); 
  305.  
  306. // Checks with the email is missing. 
  307. if ( ! isset( $data['email'] ) ) { 
  308. throw new WC_API_Exception( 'woocommerce_api_missing_customer_email', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'email' ), 400 ); 
  309.  
  310. // Sets the username. 
  311. $data['username'] = ! empty( $data['username'] ) ? $data['username'] : ''; 
  312.  
  313. // Sets the password. 
  314. $data['password'] = ! empty( $data['password'] ) ? $data['password'] : ''; 
  315.  
  316. // Attempts to create the new customer 
  317. $id = wc_create_new_customer( $data['email'], $data['username'], $data['password'] ); 
  318.  
  319. // Checks for an error in the customer creation. 
  320. if ( is_wp_error( $id ) ) { 
  321. throw new WC_API_Exception( $id->get_error_code(), $id->get_error_message(), 400 ); 
  322.  
  323. // Added customer data. 
  324. $this->update_customer_data( $id, $data ); 
  325.  
  326. do_action( 'woocommerce_api_create_customer', $id, $data ); 
  327.  
  328. $this->server->send_status( 201 ); 
  329.  
  330. return $this->get_customer( $id ); 
  331. } catch ( WC_API_Exception $e ) { 
  332. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  333.  
  334. /** 
  335. * Edit a customer 
  336. * @since 2.2 
  337. * @param int $id the customer ID 
  338. * @param array $data 
  339. * @return array 
  340. */ 
  341. public function edit_customer( $id, $data ) { 
  342. try { 
  343. if ( ! isset( $data['customer'] ) ) { 
  344. throw new WC_API_Exception( 'woocommerce_api_missing_customer_data', sprintf( __( 'No %1$s data specified to edit %1$s', 'woocommerce' ), 'customer' ), 400 ); 
  345.  
  346. $data = $data['customer']; 
  347.  
  348. // Validate the customer ID. 
  349. $id = $this->validate_request( $id, 'customer', 'edit' ); 
  350.  
  351. // Return the validate error. 
  352. if ( is_wp_error( $id ) ) { 
  353. throw new WC_API_Exception( $id->get_error_code(), $id->get_error_message(), 400 ); 
  354.  
  355. $data = apply_filters( 'woocommerce_api_edit_customer_data', $data, $this ); 
  356.  
  357. // Customer email. 
  358. if ( isset( $data['email'] ) ) { 
  359. wp_update_user( array( 'ID' => $id, 'user_email' => sanitize_email( $data['email'] ) ) ); 
  360.  
  361. // Customer password. 
  362. if ( isset( $data['password'] ) ) { 
  363. wp_update_user( array( 'ID' => $id, 'user_pass' => wc_clean( $data['password'] ) ) ); 
  364.  
  365. // Update customer data. 
  366. $this->update_customer_data( $id, $data ); 
  367.  
  368. do_action( 'woocommerce_api_edit_customer', $id, $data ); 
  369.  
  370. return $this->get_customer( $id ); 
  371. } catch ( WC_API_Exception $e ) { 
  372. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  373.  
  374. /** 
  375. * Delete a customer 
  376. * @since 2.2 
  377. * @param int $id the customer ID 
  378. * @return array 
  379. */ 
  380. public function delete_customer( $id ) { 
  381.  
  382. // Validate the customer ID. 
  383. $id = $this->validate_request( $id, 'customer', 'delete' ); 
  384.  
  385. // Return the validate error. 
  386. if ( is_wp_error( $id ) ) { 
  387. return $id; 
  388.  
  389. do_action( 'woocommerce_api_delete_customer', $id, $this ); 
  390.  
  391. return $this->delete( $id, 'customer' ); 
  392.  
  393. /** 
  394. * Get the orders for a customer 
  395. * @since 2.1 
  396. * @param int $id the customer ID 
  397. * @param string $fields fields to include in response 
  398. * @param array $filter filters 
  399. * @return array 
  400. */ 
  401. public function get_customer_orders( $id, $fields = null, $filter = array() ) { 
  402. $id = $this->validate_request( $id, 'customer', 'read' ); 
  403.  
  404. if ( is_wp_error( $id ) ) { 
  405. return $id; 
  406.  
  407. $filter['customer_id'] = $id; 
  408. $orders = WC()->api->WC_API_Orders->get_orders( $fields, $filter, null, -1 ); 
  409.  
  410. return $orders; 
  411.  
  412. /** 
  413. * Get the available downloads for a customer 
  414. * @since 2.2 
  415. * @param int $id the customer ID 
  416. * @param string $fields fields to include in response 
  417. * @return array 
  418. */ 
  419. public function get_customer_downloads( $id, $fields = null ) { 
  420. $id = $this->validate_request( $id, 'customer', 'read' ); 
  421.  
  422. if ( is_wp_error( $id ) ) { 
  423. return $id; 
  424.  
  425. $downloads = array(); 
  426. $_downloads = wc_get_customer_available_downloads( $id ); 
  427.  
  428. foreach ( $_downloads as $key => $download ) { 
  429. $downloads[ $key ] = $download; 
  430. $downloads[ $key ]['access_expires'] = $this->server->format_datetime( $downloads[ $key ]['access_expires'] ); 
  431.  
  432. return array( 'downloads' => apply_filters( 'woocommerce_api_customer_downloads_response', $downloads, $id, $fields, $this->server ) ); 
  433.  
  434. /** 
  435. * Helper method to get customer user objects 
  436. * Note that WP_User_Query does not have built-in pagination so limit & offset are used to provide limited 
  437. * pagination support 
  438. * The filter for role can only be a single role in a string. 
  439. * @since 2.3 
  440. * @param array $args request arguments for filtering query 
  441. * @return WP_User_Query 
  442. */ 
  443. private function query_customers( $args = array() ) { 
  444.  
  445. // default users per page 
  446. $users_per_page = get_option( 'posts_per_page' ); 
  447.  
  448. // Set base query arguments 
  449. $query_args = array( 
  450. 'fields' => 'ID',  
  451. 'role' => 'customer',  
  452. 'orderby' => 'registered',  
  453. 'number' => $users_per_page,  
  454. ); 
  455.  
  456. // Custom Role 
  457. if ( ! empty( $args['role'] ) ) { 
  458. $query_args['role'] = $args['role']; 
  459.  
  460. // Show users on all roles 
  461. if ( 'all' === $query_args['role'] ) { 
  462. unset( $query_args['role'] ); 
  463.  
  464. // Search 
  465. if ( ! empty( $args['q'] ) ) { 
  466. $query_args['search'] = $args['q']; 
  467.  
  468. // Limit number of users returned 
  469. if ( ! empty( $args['limit'] ) ) { 
  470. if ( $args['limit'] == -1 ) { 
  471. unset( $query_args['number'] ); 
  472. } else { 
  473. $query_args['number'] = absint( $args['limit'] ); 
  474. $users_per_page = absint( $args['limit'] ); 
  475. } else { 
  476. $args['limit'] = $query_args['number']; 
  477.  
  478. // Page 
  479. $page = ( isset( $args['page'] ) ) ? absint( $args['page'] ) : 1; 
  480.  
  481. // Offset 
  482. if ( ! empty( $args['offset'] ) ) { 
  483. $query_args['offset'] = absint( $args['offset'] ); 
  484. } else { 
  485. $query_args['offset'] = $users_per_page * ( $page - 1 ); 
  486.  
  487. // Created date 
  488. if ( ! empty( $args['created_at_min'] ) ) { 
  489. $this->created_at_min = $this->server->parse_datetime( $args['created_at_min'] ); 
  490.  
  491. if ( ! empty( $args['created_at_max'] ) ) { 
  492. $this->created_at_max = $this->server->parse_datetime( $args['created_at_max'] ); 
  493.  
  494. // Order (ASC or DESC, ASC by default) 
  495. if ( ! empty( $args['order'] ) ) { 
  496. $query_args['order'] = $args['order']; 
  497.  
  498. // Orderby 
  499. if ( ! empty( $args['orderby'] ) ) { 
  500. $query_args['orderby'] = $args['orderby']; 
  501.  
  502. // Allow sorting by meta value 
  503. if ( ! empty( $args['orderby_meta_key'] ) ) { 
  504. $query_args['meta_key'] = $args['orderby_meta_key']; 
  505.  
  506. $query = new WP_User_Query( $query_args ); 
  507.  
  508. // Helper members for pagination headers 
  509. $query->total_pages = ( $args['limit'] == -1 ) ? 1 : ceil( $query->get_total() / $users_per_page ); 
  510. $query->page = $page; 
  511.  
  512. return $query; 
  513.  
  514. /** 
  515. * Add customer data to orders 
  516. * @since 2.1 
  517. * @param $order_data 
  518. * @param $order 
  519. * @return array 
  520. */ 
  521. public function add_customer_data( $order_data, $order ) { 
  522.  
  523. if ( 0 == $order->customer_user ) { 
  524.  
  525. // add customer data from order 
  526. $order_data['customer'] = array( 
  527. 'id' => 0,  
  528. 'email' => $order->billing_email,  
  529. 'first_name' => $order->billing_first_name,  
  530. 'last_name' => $order->billing_last_name,  
  531. 'billing_address' => array( 
  532. 'first_name' => $order->billing_first_name,  
  533. 'last_name' => $order->billing_last_name,  
  534. 'company' => $order->billing_company,  
  535. 'address_1' => $order->billing_address_1,  
  536. 'address_2' => $order->billing_address_2,  
  537. 'city' => $order->billing_city,  
  538. 'state' => $order->billing_state,  
  539. 'postcode' => $order->billing_postcode,  
  540. 'country' => $order->billing_country,  
  541. 'email' => $order->billing_email,  
  542. 'phone' => $order->billing_phone,  
  543. ),  
  544. 'shipping_address' => array( 
  545. 'first_name' => $order->shipping_first_name,  
  546. 'last_name' => $order->shipping_last_name,  
  547. 'company' => $order->shipping_company,  
  548. 'address_1' => $order->shipping_address_1,  
  549. 'address_2' => $order->shipping_address_2,  
  550. 'city' => $order->shipping_city,  
  551. 'state' => $order->shipping_state,  
  552. 'postcode' => $order->shipping_postcode,  
  553. 'country' => $order->shipping_country,  
  554. ),  
  555. ); 
  556.  
  557. } else { 
  558.  
  559. $order_data['customer'] = current( $this->get_customer( $order->customer_user ) ); 
  560.  
  561. return $order_data; 
  562.  
  563. /** 
  564. * Modify the WP_User_Query to support filtering on the date the customer was created 
  565. * @since 2.1 
  566. * @param WP_User_Query $query 
  567. */ 
  568. public function modify_user_query( $query ) { 
  569.  
  570. if ( $this->created_at_min ) { 
  571. $query->query_where .= sprintf( " AND user_registered >= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%H:%%i:%%s' )", esc_sql( $this->created_at_min ) ); 
  572.  
  573. if ( $this->created_at_max ) { 
  574. $query->query_where .= sprintf( " AND user_registered <= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%H:%%i:%%s' )", esc_sql( $this->created_at_max ) ); 
  575.  
  576. /** 
  577. * Wrapper for @see get_avatar() which doesn't simply return 
  578. * the URL so we need to pluck it from the HTML img tag 
  579. * Kudos to https://github.com/WP-API/WP-API for offering a better solution 
  580. * @since 2.1 
  581. * @param string $email the customer's email 
  582. * @return string the URL to the customer's avatar 
  583. */ 
  584. private function get_avatar_url( $email ) { 
  585. $avatar_html = get_avatar( $email ); 
  586.  
  587. // Get the URL of the avatar from the provided HTML 
  588. preg_match( '/src=["|\'](.+)[\&|"|\']/U', $avatar_html, $matches ); 
  589.  
  590. if ( isset( $matches[1] ) && ! empty( $matches[1] ) ) { 
  591. return esc_url_raw( $matches[1] ); 
  592.  
  593. return null; 
  594.  
  595. /** 
  596. * Validate the request by checking: 
  597. * 1) the ID is a valid integer 
  598. * 2) the ID returns a valid WP_User 
  599. * 3) the current user has the proper permissions 
  600. * @since 2.1 
  601. * @see WC_API_Resource::validate_request() 
  602. * @param integer $id the customer ID 
  603. * @param string $type the request type, unused because this method overrides the parent class 
  604. * @param string $context the context of the request, either `read`, `edit` or `delete` 
  605. * @return int|WP_Error valid user ID or WP_Error if any of the checks fails 
  606. */ 
  607. protected function validate_request( $id, $type, $context ) { 
  608.  
  609. try { 
  610. $id = absint( $id ); 
  611.  
  612. // validate ID 
  613. if ( empty( $id ) ) { 
  614. throw new WC_API_Exception( 'woocommerce_api_invalid_customer_id', __( 'Invalid customer ID', 'woocommerce' ), 404 ); 
  615.  
  616. // non-existent IDs return a valid WP_User object with the user ID = 0 
  617. $customer = new WP_User( $id ); 
  618.  
  619. if ( 0 === $customer->ID ) { 
  620. throw new WC_API_Exception( 'woocommerce_api_invalid_customer', __( 'Invalid customer', 'woocommerce' ), 404 ); 
  621.  
  622. // validate permissions 
  623. switch ( $context ) { 
  624.  
  625. case 'read': 
  626. if ( ! current_user_can( 'list_users' ) ) { 
  627. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_customer', __( 'You do not have permission to read this customer', 'woocommerce' ), 401 ); 
  628. break; 
  629.  
  630. case 'edit': 
  631. if ( ! current_user_can( 'edit_users' ) ) { 
  632. throw new WC_API_Exception( 'woocommerce_api_user_cannot_edit_customer', __( 'You do not have permission to edit this customer', 'woocommerce' ), 401 ); 
  633. break; 
  634.  
  635. case 'delete': 
  636. if ( ! current_user_can( 'delete_users' ) ) { 
  637. throw new WC_API_Exception( 'woocommerce_api_user_cannot_delete_customer', __( 'You do not have permission to delete this customer', 'woocommerce' ), 401 ); 
  638. break; 
  639.  
  640. return $id; 
  641. } catch ( WC_API_Exception $e ) { 
  642. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  643.  
  644. /** 
  645. * Check if the current user can read users 
  646. * @since 2.1 
  647. * @see WC_API_Resource::is_readable() 
  648. * @param int|WP_Post $post unused 
  649. * @return bool true if the current user can read users, false otherwise 
  650. */ 
  651. protected function is_readable( $post ) { 
  652. return current_user_can( 'list_users' ); 
  653.  
  654. /** 
  655. * Bulk update or insert customers 
  656. * Accepts an array with customers in the formats supported by 
  657. * WC_API_Customers->create_customer() and WC_API_Customers->edit_customer() 
  658. * @since 2.4.0 
  659. * @param array $data 
  660. * @return array 
  661. */ 
  662. public function bulk( $data ) { 
  663.  
  664. try { 
  665. if ( ! isset( $data['customers'] ) ) { 
  666. throw new WC_API_Exception( 'woocommerce_api_missing_customers_data', sprintf( __( 'No %1$s data specified to create/edit %1$s', 'woocommerce' ), 'customers' ), 400 ); 
  667.  
  668. $data = $data['customers']; 
  669. $limit = apply_filters( 'woocommerce_api_bulk_limit', 100, 'customers' ); 
  670.  
  671. // Limit bulk operation 
  672. if ( count( $data ) > $limit ) { 
  673. throw new WC_API_Exception( 'woocommerce_api_customers_request_entity_too_large', sprintf( __( 'Unable to accept more than %s items for this request', 'woocommerce' ), $limit ), 413 ); 
  674.  
  675. $customers = array(); 
  676.  
  677. foreach ( $data as $_customer ) { 
  678. $customer_id = 0; 
  679.  
  680. // Try to get the customer ID 
  681. if ( isset( $_customer['id'] ) ) { 
  682. $customer_id = intval( $_customer['id'] ); 
  683.  
  684. // Customer exists / edit customer 
  685. if ( $customer_id ) { 
  686. $edit = $this->edit_customer( $customer_id, array( 'customer' => $_customer ) ); 
  687.  
  688. if ( is_wp_error( $edit ) ) { 
  689. $customers[] = array( 
  690. 'id' => $customer_id,  
  691. 'error' => array( 'code' => $edit->get_error_code(), 'message' => $edit->get_error_message() ) 
  692. ); 
  693. } else { 
  694. $customers[] = $edit['customer']; 
  695.  
  696. // Customer don't exists / create customer 
  697. else { 
  698. $new = $this->create_customer( array( 'customer' => $_customer ) ); 
  699.  
  700. if ( is_wp_error( $new ) ) { 
  701. $customers[] = array( 
  702. 'id' => $customer_id,  
  703. 'error' => array( 'code' => $new->get_error_code(), 'message' => $new->get_error_message() ) 
  704. ); 
  705. } else { 
  706. $customers[] = $new['customer']; 
  707.  
  708. return array( 'customers' => apply_filters( 'woocommerce_api_customers_bulk_response', $customers, $this ) ); 
  709. } catch ( WC_API_Exception $e ) { 
  710. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );