1 <?php
2 3 4 5 6 7 8 9 10 11
12
13 if ( ! defined( 'ABSPATH' ) ) exit;
14
15 class WC_API_Customers extends WC_API_Resource {
16
17
18 protected $base = '/customers';
19
20
21 private $created_at_min = null;
22
23
24 private $created_at_max = null;
25
26 27 28 29 30 31 32
33 public function __construct( WC_API_Server $server ) {
34
35 parent::__construct( $server );
36
37
38 add_filter( 'woocommerce_api_order_response', array( $this, 'add_customer_data' ), 10, 2 );
39
40
41 add_action( 'pre_user_query', array( $this, 'modify_user_query' ) );
42 }
43
44 45 46 47 48 49 50 51 52 53 54 55
56 public function register_routes( $routes ) {
57
58
59 $routes[ $this->base ] = array(
60 array( array( $this, 'get_customers' ), WC_API_SERVER::READABLE ),
61 );
62
63
64 $routes[ $this->base . '/count'] = array(
65 array( array( $this, 'get_customers_count' ), WC_API_SERVER::READABLE ),
66 );
67
68
69 $routes[ $this->base . '/(?P<id>\d+)' ] = array(
70 array( array( $this, 'get_customer' ), WC_API_SERVER::READABLE ),
71 );
72
73
74 $routes[ $this->base . '/(?P<id>\d+)/orders' ] = array(
75 array( array( $this, 'get_customer_orders' ), WC_API_SERVER::READABLE ),
76 );
77
78 return $routes;
79 }
80
81 82 83 84 85 86 87 88 89
90 public function get_customers( $fields = null, $filter = array(), $page = 1 ) {
91
92 $filter['page'] = $page;
93
94 $query = $this->query_customers( $filter );
95
96 $customers = array();
97
98 foreach( $query->get_results() as $user_id ) {
99
100 if ( ! $this->is_readable( $user_id ) )
101 continue;
102
103 $customers[] = current( $this->get_customer( $user_id, $fields ) );
104 }
105
106 $this->server->add_pagination_headers( $query );
107
108 return array( 'customers' => $customers );
109 }
110
111 112 113 114 115 116 117 118
119 public function get_customer( $id, $fields = null ) {
120 global $wpdb;
121
122 $id = $this->validate_request( $id, 'customer', 'read' );
123
124 if ( is_wp_error( $id ) )
125 return $id;
126
127 $customer = new WP_User( $id );
128
129
130 $last_order = $wpdb->get_row( "SELECT id, post_date_gmt
131 FROM $wpdb->posts AS posts
132 LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
133 WHERE meta.meta_key = '_customer_user'
134 AND meta.meta_value = {$customer->ID}
135 AND posts.post_type = 'shop_order'
136 AND posts.post_status = 'publish'
137 " );
138
139 $customer_data = array(
140 'id' => $customer->ID,
141 'created_at' => $this->server->format_datetime( $customer->user_registered ),
142 'email' => $customer->user_email,
143 'first_name' => $customer->first_name,
144 'last_name' => $customer->last_name,
145 'username' => $customer->user_login,
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' => (int) $customer->_order_count,
149 'total_spent' => wc_format_decimal( $customer->_money_spent, 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 181 182 183 184 185 186
187 public function get_customers_count( $filter = array() ) {
188
189 $query = $this->query_customers( $filter );
190
191 if ( ! current_user_can( 'list_users' ) )
192 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 ) );
193
194 return array( 'count' => count( $query->get_results() ) );
195 }
196
197
198 199 200 201 202 203 204
205 public function create_customer( $data ) {
206
207 if ( ! current_user_can( 'create_users' ) )
208 return new WP_Error( 'woocommerce_api_user_cannot_create_customer', __( 'You do not have permission to create this customer', 'woocommerce' ), array( 'status' => 401 ) );
209
210 return array();
211 }
212
213 214 215 216 217 218 219 220
221 public function edit_customer( $id, $data ) {
222
223 $id = $this->validate_request( $id, 'customer', 'edit' );
224
225 if ( ! is_wp_error( $id ) )
226 return $id;
227
228 return $this->get_customer( $id );
229 }
230
231 232 233 234 235 236 237
238 public function delete_customer( $id ) {
239
240 $id = $this->validate_request( $id, 'customer', 'delete' );
241
242 if ( ! is_wp_error( $id ) )
243 return $id;
244
245 return $this->delete( $id, 'customer' );
246 }
247
248 249 250 251 252 253 254 255
256 public function get_customer_orders( $id, $fields = null ) {
257 global $wpdb;
258
259 $id = $this->validate_request( $id, 'customer', 'read' );
260
261 if ( is_wp_error( $id ) )
262 return $id;
263
264 $order_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id
265 FROM $wpdb->posts AS posts
266 LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
267 WHERE meta.meta_key = '_customer_user'
268 AND meta.meta_value = '%s'
269 AND posts.post_type = 'shop_order'
270 AND posts.post_status = 'publish'
271 ", $id ) );
272
273 if ( empty( $order_ids ) )
274 return array( 'orders' => array() );
275
276 $orders = array();
277
278 foreach ( $order_ids as $order_id ) {
279 $orders[] = current( WC()->api->WC_API_Orders->get_order( $order_id, $fields ) );
280 }
281
282 return array( 'orders' => apply_filters( 'woocommerce_api_customer_orders_response', $orders, $id, $fields, $order_ids, $this->server ) );
283 }
284
285 286 287 288 289 290 291 292 293 294
295 private function query_customers( $args = array() ) {
296
297
298 $users_per_page = get_option( 'posts_per_page' );
299
300
301 $query_args = array(
302 'fields' => 'ID',
303 'role' => 'customer',
304 'orderby' => 'registered',
305 'number' => $users_per_page,
306 );
307
308
309 if ( ! empty( $args['q'] ) ) {
310 $query_args['search'] = $args['q'];
311 }
312
313
314 if ( ! empty( $args['limit'] ) ) {
315
316 $query_args['number'] = absint( $args['limit'] );
317
318 $users_per_page = absint( $args['limit'] );
319 }
320
321
322 $page = ( isset( $args['page'] ) ) ? absint( $args['page'] ) : 1;
323
324
325 if ( ! empty( $args['offset'] ) ) {
326 $query_args['offset'] = absint( $args['offset'] );
327 } else {
328 $query_args['offset'] = $users_per_page * ( $page - 1 );
329 }
330
331
332 if ( ! empty( $args['created_at_min'] ) ) {
333 $this->created_at_min = $this->server->parse_datetime( $args['created_at_min'] );
334 }
335
336 if ( ! empty( $args['created_at_max'] ) ) {
337 $this->created_at_max = $this->server->parse_datetime( $args['created_at_max'] );
338 }
339
340 $query = new WP_User_Query( $query_args );
341
342
343 $query->total_pages = ceil( $query->get_total() / $users_per_page );
344 $query->page = $page;
345
346 return $query;
347 }
348
349 350 351 352 353 354 355 356
357 public function add_customer_data( $order_data, $order ) {
358
359 if ( 0 == $order->customer_user ) {
360
361
362 $order_data['customer'] = array(
363 'id' => 0,
364 'email' => $order->billing_email,
365 'first_name' => $order->billing_first_name,
366 'last_name' => $order->billing_last_name,
367 'billing_address' => array(
368 'first_name' => $order->billing_first_name,
369 'last_name' => $order->billing_last_name,
370 'company' => $order->billing_company,
371 'address_1' => $order->billing_address_1,
372 'address_2' => $order->billing_address_2,
373 'city' => $order->billing_city,
374 'state' => $order->billing_state,
375 'postcode' => $order->billing_postcode,
376 'country' => $order->billing_country,
377 'email' => $order->billing_email,
378 'phone' => $order->billing_phone,
379 ),
380 'shipping_address' => array(
381 'first_name' => $order->shipping_first_name,
382 'last_name' => $order->shipping_last_name,
383 'company' => $order->shipping_company,
384 'address_1' => $order->shipping_address_1,
385 'address_2' => $order->shipping_address_2,
386 'city' => $order->shipping_city,
387 'state' => $order->shipping_state,
388 'postcode' => $order->shipping_postcode,
389 'country' => $order->shipping_country,
390 ),
391 );
392
393 } else {
394
395 $order_data['customer'] = current( $this->get_customer( $order->customer_user ) );
396 }
397
398 return $order_data;
399 }
400
401 402 403 404 405 406
407 public function modify_user_query( $query ) {
408
409 if ( $this->created_at_min )
410 $query->query_where .= sprintf( " AND user_registered >= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%h:%%i:%%s' )", esc_sql( $this->created_at_min ) );
411
412 if ( $this->created_at_max )
413 $query->query_where .= sprintf( " AND user_registered <= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%h:%%i:%%s' )", esc_sql( $this->created_at_max ) );
414 }
415
416 417 418 419 420 421 422 423
424 private function get_avatar_url( $email ) {
425
426 $dom = new DOMDocument();
427
428 $dom->loadHTML( get_avatar( $email ) );
429
430 $url = $dom->getElementsByTagName( 'img' )->item( 0 )->getAttribute( 'src' );
431
432 return ( ! empty( $url ) ) ? $url : null;
433 }
434
435 436 437 438 439 440 441 442 443 444 445 446 447 448
449 protected function validate_request( $id, $type, $context ) {
450
451 $id = absint( $id );
452
453
454 if ( empty( $id ) )
455 return new WP_Error( 'woocommerce_api_invalid_customer_id', __( 'Invalid customer ID', 'woocommerce' ), array( 'status' => 404 ) );
456
457
458 $customer = new WP_User( $id );
459
460 if ( 0 === $customer->ID )
461 return new WP_Error( 'woocommerce_api_invalid_customer', __( 'Invalid customer', 'woocommerce' ), array( 'status' => 404 ) );
462
463
464 switch ( $context ) {
465
466 case 'read':
467 if ( ! current_user_can( 'list_users' ) )
468 return new WP_Error( 'woocommerce_api_user_cannot_read_customer', __( 'You do not have permission to read this customer', 'woocommerce' ), array( 'status' => 401 ) );
469 break;
470
471 case 'edit':
472 if ( ! current_user_can( 'edit_users' ) )
473 return new WP_Error( 'woocommerce_api_user_cannot_edit_customer', __( 'You do not have permission to edit this customer', 'woocommerce' ), array( 'status' => 401 ) );
474 break;
475
476 case 'delete':
477 if ( ! current_user_can( 'delete_users' ) )
478 return new WP_Error( 'woocommerce_api_user_cannot_delete_customer', __( 'You do not have permission to delete this customer', 'woocommerce' ), array( 'status' => 401 ) );
479 break;
480 }
481
482 return $id;
483 }
484
485 486 487 488 489 490 491 492
493 protected function is_readable( $post ) {
494
495 return current_user_can( 'list_users' );
496 }
497
498 }
499