Passed
Push — master ( 6176aa...f7c939 )
by Mike
03:08
created

Customers   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 735
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 435
dl 0
loc 735
rs 9.36
c 0
b 0
f 0
wmc 38

11 Methods

Rating   Name   Duplication   Size   Complexity  
B get_item_schema() 0 234 1
A update_item() 0 27 4
B register_routes() 0 88 1
A prepare_item_for_response() 0 18 2
A get_item() 0 12 3
D get_items() 0 93 10
A get_collection_params() 0 64 1
B delete_item() 0 48 10
A create_item() 0 34 4
A get_role_names() 0 4 1
A prepare_links() 0 11 1
1
<?php
2
/**
3
 * REST API Customers controller
4
 *
5
 * Handles requests to the /customers endpoint.
6
 *
7
 * @package WooCommerce/RestApi
8
 */
9
10
namespace WooCommerce\RestApi\Controllers\Version4;
11
12
defined( 'ABSPATH' ) || exit;
13
14
use \WP_REST_Server;
15
use WooCommerce\RestApi\Controllers\Version4\Requests\CustomerRequest;
16
use WooCommerce\RestApi\Controllers\Version4\Responses\CustomerResponse;
17
18
/**
19
 * REST API Customers controller class.
20
 */
21
class Customers extends AbstractController {
22
23
	/**
24
	 * Route base.
25
	 *
26
	 * @var string
27
	 */
28
	protected $rest_base = 'customers';
29
30
	/**
31
	 * Permission to check.
32
	 *
33
	 * @var string
34
	 */
35
	protected $resource_type = 'customers';
36
37
	/**
38
	 * Register the routes for customers.
39
	 */
40
	public function register_routes() {
41
		register_rest_route(
42
			$this->namespace,
43
			'/' . $this->rest_base,
44
			array(
45
				array(
46
					'methods'             => \WP_REST_Server::READABLE,
47
					'callback'            => array( $this, 'get_items' ),
48
					'permission_callback' => array( $this, 'get_items_permissions_check' ),
49
					'args'                => $this->get_collection_params(),
50
				),
51
				array(
52
					'methods'             => \WP_REST_Server::CREATABLE,
53
					'callback'            => array( $this, 'create_item' ),
54
					'permission_callback' => array( $this, 'create_item_permissions_check' ),
55
					'args'                => array_merge(
56
						$this->get_endpoint_args_for_item_schema( \WP_REST_Server::CREATABLE ),
57
						array(
58
							'email' => array(
59
								'required'    => true,
60
								'type'        => 'string',
61
								'description' => __( 'New user email address.', 'woocommerce' ),
62
							),
63
							'username' => array(
64
								'required'    => 'no' === get_option( 'woocommerce_registration_generate_username', 'yes' ),
65
								'description' => __( 'New user username.', 'woocommerce' ),
66
								'type'        => 'string',
67
							),
68
							'password' => array(
69
								'required'    => 'no' === get_option( 'woocommerce_registration_generate_password', 'no' ),
70
								'description' => __( 'New user password.', 'woocommerce' ),
71
								'type'        => 'string',
72
							),
73
						)
74
					),
75
				),
76
				'schema' => array( $this, 'get_public_item_schema' ),
77
			),
78
			true
79
		);
80
81
		register_rest_route(
82
			$this->namespace,
83
			'/' . $this->rest_base . '/(?P<id>[\d]+)',
84
			array(
85
				'args' => array(
86
					'id' => array(
87
						'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
88
						'type'        => 'integer',
89
					),
90
				),
91
				array(
92
					'methods'             => \WP_REST_Server::READABLE,
93
					'callback'            => array( $this, 'get_item' ),
94
					'permission_callback' => array( $this, 'get_item_permissions_check' ),
95
					'args'                => array(
96
						'context' => $this->get_context_param( array( 'default' => 'view' ) ),
97
					),
98
				),
99
				array(
100
					'methods'             => \WP_REST_Server::EDITABLE,
101
					'callback'            => array( $this, 'update_item' ),
102
					'permission_callback' => array( $this, 'update_item_permissions_check' ),
103
					'args'                => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::EDITABLE ),
104
				),
105
				array(
106
					'methods'             => \WP_REST_Server::DELETABLE,
107
					'callback'            => array( $this, 'delete_item' ),
108
					'permission_callback' => array( $this, 'delete_item_permissions_check' ),
109
					'args'                => array(
110
						'force' => array(
111
							'default'     => false,
112
							'type'        => 'boolean',
113
							'description' => __( 'Required to be true, as resource does not support trashing.', 'woocommerce' ),
114
						),
115
						'reassign' => array(
116
							'default'     => 0,
117
							'type'        => 'integer',
118
							'description' => __( 'ID to reassign posts to.', 'woocommerce' ),
119
						),
120
					),
121
				),
122
				'schema' => array( $this, 'get_public_item_schema' ),
123
			),
124
			true
125
		);
126
127
		$this->register_batch_route();
128
	}
129
130
	/**
131
	 * Get all customers.
132
	 *
133
	 * @param \WP_REST_Request $request Full details about the request.
134
	 * @return \WP_Error|\WP_REST_Response
135
	 */
136
	public function get_items( $request ) {
137
		$prepared_args = array(
138
			'exclude' => $request['exclude'],
139
			'include' => $request['include'],
140
			'order'   => $request['order'],
141
			'number'  => $request['per_page'],
142
		);
143
144
		if ( ! empty( $request['offset'] ) ) {
145
			$prepared_args['offset'] = $request['offset'];
146
		} else {
147
			$prepared_args['offset'] = ( $request['page'] - 1 ) * $prepared_args['number'];
148
		}
149
150
		$orderby_possibles = array(
151
			'id'              => 'ID',
152
			'include'         => 'include',
153
			'name'            => 'display_name',
154
			'registered_date' => 'registered',
155
		);
156
		$prepared_args['orderby'] = $orderby_possibles[ $request['orderby'] ];
157
		$prepared_args['search']  = $request['search'];
158
159
		if ( '' !== $prepared_args['search'] ) {
160
			$prepared_args['search'] = '*' . $prepared_args['search'] . '*';
161
		}
162
163
		// Filter by email.
164
		if ( ! empty( $request['email'] ) ) {
165
			$prepared_args['search']         = $request['email'];
166
			$prepared_args['search_columns'] = array( 'user_email' );
167
		}
168
169
		// Filter by role.
170
		if ( 'all' !== $request['role'] ) {
171
			$prepared_args['role'] = $request['role'];
172
		}
173
174
		/**
175
		 * Filter arguments, before passing to \ WP_User_Query, when querying users via the REST API.
176
		 *
177
		 * @see https://developer.wordpress.org/reference/classes/\ WP_User_Query/
178
		 *
179
		 * @param array           $prepared_args Array of arguments for \ WP_User_Query.
180
		 * @param \WP_REST_Request $request       The current request.
181
		 */
182
		$prepared_args = apply_filters( 'woocommerce_rest_customer_query', $prepared_args, $request );
183
184
		$query = new \WP_User_Query( $prepared_args );
185
186
		$users = array();
187
		foreach ( $query->results as $user ) {
188
			$customer = new \WC_Customer( $user->ID );
189
			$data     = $this->prepare_item_for_response( $customer, $request );
190
			$users[]  = $this->prepare_response_for_collection( $data );
191
		}
192
193
		$response = rest_ensure_response( $users );
194
195
		// Store pagination values for headers then unset for count query.
196
		$per_page = (int) $prepared_args['number'];
197
		$page     = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
198
199
		$prepared_args['fields'] = 'ID';
200
201
		$total_users = $query->get_total();
202
		if ( $total_users < 1 ) {
203
			// Out-of-bounds, run the query again without LIMIT for total count.
204
			unset( $prepared_args['number'] );
205
			unset( $prepared_args['offset'] );
206
			$count_query = new \ WP_User_Query( $prepared_args );
207
			$total_users = $count_query->get_total();
208
		}
209
		$response->header( 'X-WP-Total', (int) $total_users );
210
		$max_pages = ceil( $total_users / $per_page );
211
		$response->header( 'X-WP-TotalPages', (int) $max_pages );
212
213
		$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
214
		if ( $page > 1 ) {
215
			$prev_page = $page - 1;
216
			if ( $prev_page > $max_pages ) {
217
				$prev_page = $max_pages;
218
			}
219
			$prev_link = add_query_arg( 'page', $prev_page, $base );
220
			$response->link_header( 'prev', $prev_link );
221
		}
222
		if ( $max_pages > $page ) {
223
			$next_page = $page + 1;
224
			$next_link = add_query_arg( 'page', $next_page, $base );
225
			$response->link_header( 'next', $next_link );
226
		}
227
228
		return $response;
229
	}
230
231
	/**
232
	 * Create a single customer.
233
	 *
234
	 * @throws \WC_REST_Exception On invalid params.
235
	 * @param \WP_REST_Request $request Full details about the request.
236
	 * @return \WP_Error|\WP_REST_Response
237
	 */
238
	public function create_item( $request ) {
239
		try {
240
			if ( ! empty( $request['id'] ) ) {
241
				throw new \WC_REST_Exception( 'woocommerce_rest_customer_exists', __( 'Cannot create existing resource.', 'woocommerce' ), 400 );
242
			}
243
244
			$customer_request = new CustomerRequest( $request );
245
			$customer         = $customer_request->prepare_object();
246
			$customer->save();
247
248
			if ( ! $customer->get_id() ) {
249
				throw new \WC_REST_Exception( 'woocommerce_rest_cannot_create', __( 'This resource cannot be created.', 'woocommerce' ), 400 );
250
			}
251
252
			$this->update_additional_fields_for_object( $customer, $request );
0 ignored issues
show
Bug introduced by
$customer of type WC_Customer is incompatible with the type array expected by parameter $object of WP_REST_Controller::upda...nal_fields_for_object(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

252
			$this->update_additional_fields_for_object( /** @scrutinizer ignore-type */ $customer, $request );
Loading history...
253
254
			/**
255
			 * Fires after a customer is created or updated via the REST API.
256
			 *
257
			 * @param \WC_Customer     $customer Customer object.
258
			 * @param \WP_REST_Request $request   Request object.
259
			 * @param boolean          $creating  True when creating customer, false when updating customer.
260
			 */
261
			do_action( 'woocommerce_rest_insert_customer_object', $customer, $request, true );
262
263
			$request->set_param( 'context', 'edit' );
264
			$response = $this->prepare_item_for_response( $customer, $request );
265
			$response = rest_ensure_response( $response );
266
			$response->set_status( 201 );
267
			$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $customer->get_id() ) ) );
268
269
			return $response;
270
		} catch ( \Exception $e ) {
271
			return new \WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
0 ignored issues
show
Bug introduced by
The method getErrorCode() does not exist on Exception. It seems like you code against a sub-type of Exception such as WC_API_Exception or WC_Data_Exception. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

271
			return new \WP_Error( $e->/** @scrutinizer ignore-call */ getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
Loading history...
272
		}
273
	}
274
275
	/**
276
	 * Get a single customer.
277
	 *
278
	 * @param \WP_REST_Request $request Full details about the request.
279
	 * @return \WP_Error|\WP_REST_Response
280
	 */
281
	public function get_item( $request ) {
282
		$id       = (int) $request['id'];
283
		$customer = new \WC_Customer( $id );
284
285
		if ( empty( $id ) || ! $customer->get_id() ) {
286
			return new \WP_Error( 'woocommerce_rest_invalid_id', __( 'Invalid resource ID.', 'woocommerce' ), array( 'status' => 404 ) );
287
		}
288
289
		$response = $this->prepare_item_for_response( $customer, $request );
290
		$response = rest_ensure_response( $response );
291
292
		return $response;
293
	}
294
295
	/**
296
	 * Update a single user.
297
	 *
298
	 * @throws \WC_REST_Exception On invalid params.
299
	 *
300
	 * @param \WP_REST_Request $request Full details about the request.
301
	 * @return \WP_Error|\WP_REST_Response
302
	 */
303
	public function update_item( $request ) {
304
		try {
305
			$customer_request = new CustomerRequest( $request );
306
			$customer         = $customer_request->prepare_object();
307
			$customer->save();
308
309
			$this->update_additional_fields_for_object( $customer, $request );
0 ignored issues
show
Bug introduced by
$customer of type WC_Customer is incompatible with the type array expected by parameter $object of WP_REST_Controller::upda...nal_fields_for_object(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

309
			$this->update_additional_fields_for_object( /** @scrutinizer ignore-type */ $customer, $request );
Loading history...
310
311
			if ( is_multisite() && ! is_user_member_of_blog( $customer->get_id() ) ) {
312
				add_user_to_blog( get_current_blog_id(), $customer->get_id(), 'customer' );
313
			}
314
315
			/**
316
			 * Fires after a customer is created or updated via the REST API.
317
			 *
318
			 * @param \WC_Customer     $customer  Data used to create the customer.
319
			 * @param \WP_REST_Request $request   Request object.
320
			 * @param boolean         $creating  True when creating customer, false when updating customer.
321
			 */
322
			do_action( 'woocommerce_rest_insert_customer_object', $customer, $request, false );
323
324
			$request->set_param( 'context', 'edit' );
325
			$response = $this->prepare_item_for_response( $customer, $request );
326
			$response = rest_ensure_response( $response );
327
			return $response;
328
		} catch ( Exception $e ) {
0 ignored issues
show
Bug introduced by
The type WooCommerce\RestApi\Controllers\Version4\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
329
			return new \WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
330
		}
331
	}
332
333
	/**
334
	 * Delete a single customer.
335
	 *
336
	 * @param \WP_REST_Request $request Full details about the request.
337
	 * @return \WP_Error|\WP_REST_Response
338
	 */
339
	public function delete_item( $request ) {
340
		$id       = (int) $request['id'];
341
		$reassign = isset( $request['reassign'] ) ? absint( $request['reassign'] ) : null;
342
		$force    = isset( $request['force'] ) ? (bool) $request['force'] : false;
343
344
		// We don't support trashing for this type, error out.
345
		if ( ! $force ) {
346
			return new \WP_Error( 'woocommerce_rest_trash_not_supported', __( 'Customers do not support trashing.', 'woocommerce' ), array( 'status' => 501 ) );
347
		}
348
349
		if ( ! get_userdata( $id ) ) {
350
			return new \WP_Error( 'woocommerce_rest_invalid_id', __( 'Invalid resource id.', 'woocommerce' ), array( 'status' => 400 ) );
351
		}
352
353
		if ( ! empty( $reassign ) ) {
354
			if ( $reassign === $id || ! get_userdata( $reassign ) ) {
355
				return new \WP_Error( 'woocommerce_rest_customer_invalid_reassign', __( 'Invalid resource id for reassignment.', 'woocommerce' ), array( 'status' => 400 ) );
356
			}
357
		}
358
359
		/** Include admin customer functions to get access to wp_delete_user() */
360
		require_once ABSPATH . 'wp-admin/includes/user.php';
361
362
		$customer = new \WC_Customer( $id );
363
364
		$request->set_param( 'context', 'edit' );
365
		$response = $this->prepare_item_for_response( $customer, $request );
366
367
		if ( ! is_null( $reassign ) ) {
368
			$result = $customer->delete_and_reassign( $reassign );
369
		} else {
370
			$result = $customer->delete();
371
		}
372
373
		if ( ! $result ) {
374
			return new \WP_Error( 'woocommerce_rest_cannot_delete', __( 'The resource cannot be deleted.', 'woocommerce' ), array( 'status' => 500 ) );
375
		}
376
377
		/**
378
		 * Fires after a customer is deleted via the REST API.
379
		 *
380
		 * @param \WC_Customer      $customer User data.
381
		 * @param \WP_REST_Response $response  The response returned from the API.
382
		 * @param \WP_REST_Request  $request   The request sent to the API.
383
		 */
384
		do_action( 'woocommerce_rest_delete_customer_object', $customer, $response, $request );
385
386
		return $response;
387
	}
388
389
	/**
390
	 * Prepare a single customer output for response.
391
	 *
392
	 * @param  \WC_Customer     $customer User object.
393
	 * @param  \WP_REST_Request $request   Request object.
394
	 * @return \WP_REST_Response $response  Response data.
395
	 */
396
	public function prepare_item_for_response( $customer, $request ) {
397
		$context           = ! empty( $request['context'] ) ? $request['context'] : 'view';
398
		$customer_response = new CustomerResponse();
399
400
		$data     = $customer_response->prepare_response( $customer, $context );
401
		$data     = $this->add_additional_fields_to_object( $data, $request );
402
		$data     = $this->filter_response_by_context( $data, $context );
403
		$response = rest_ensure_response( $data );
404
		$response->add_links( $this->prepare_links( $customer ) );
405
406
		/**
407
		 * Filter customer data returned from the REST API.
408
		 *
409
		 * @param \WP_REST_Response $response   The response object.
410
		 * @param \WC_Customer      $customer  User object used to create response.
411
		 * @param \WP_REST_Request  $request    Request object.
412
		 */
413
		return apply_filters( 'woocommerce_rest_prepare_customer_object', $response, $customer, $request );
414
	}
415
416
	/**
417
	 * Prepare links for the request.
418
	 *
419
	 * @param \WC_Customer $customer Customer object.
420
	 * @return array Links for the given customer.
421
	 */
422
	protected function prepare_links( $customer ) {
423
		$links = array(
424
			'self' => array(
425
				'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $customer->get_id() ) ),
426
			),
427
			'collection' => array(
428
				'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
429
			),
430
		);
431
432
		return $links;
433
	}
434
435
	/**
436
	 * Get the Customer's schema, conforming to JSON Schema.
437
	 *
438
	 * @return array
439
	 */
440
	public function get_item_schema() {
441
		$schema = array(
442
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
443
			'title'      => 'customer',
444
			'type'       => 'object',
445
			'properties' => array(
446
				'id'                 => array(
447
					'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
448
					'type'        => 'integer',
449
					'context'     => array( 'view', 'edit' ),
450
					'readonly'    => true,
451
				),
452
				'date_created'       => array(
453
					'description' => __( "The date the customer was created, in the site's timezone.", 'woocommerce' ),
454
					'type'        => 'date-time',
455
					'context'     => array( 'view', 'edit' ),
456
					'readonly'    => true,
457
				),
458
				'date_created_gmt'   => array(
459
					'description' => __( 'The date the customer was created, as GMT.', 'woocommerce' ),
460
					'type'        => 'date-time',
461
					'context'     => array( 'view', 'edit' ),
462
					'readonly'    => true,
463
				),
464
				'date_modified'      => array(
465
					'description' => __( "The date the customer was last modified, in the site's timezone.", 'woocommerce' ),
466
					'type'        => 'date-time',
467
					'context'     => array( 'view', 'edit' ),
468
					'readonly'    => true,
469
				),
470
				'date_modified_gmt'  => array(
471
					'description' => __( 'The date the customer was last modified, as GMT.', 'woocommerce' ),
472
					'type'        => 'date-time',
473
					'context'     => array( 'view', 'edit' ),
474
					'readonly'    => true,
475
				),
476
				'email'              => array(
477
					'description' => __( 'The email address for the customer.', 'woocommerce' ),
478
					'type'        => 'string',
479
					'format'      => 'email',
480
					'context'     => array( 'view', 'edit' ),
481
				),
482
				'first_name'         => array(
483
					'description' => __( 'Customer first name.', 'woocommerce' ),
484
					'type'        => 'string',
485
					'context'     => array( 'view', 'edit' ),
486
					'arg_options' => array(
487
						'sanitize_callback' => 'sanitize_text_field',
488
					),
489
				),
490
				'last_name'          => array(
491
					'description' => __( 'Customer last name.', 'woocommerce' ),
492
					'type'        => 'string',
493
					'context'     => array( 'view', 'edit' ),
494
					'arg_options' => array(
495
						'sanitize_callback' => 'sanitize_text_field',
496
					),
497
				),
498
				'role'               => array(
499
					'description' => __( 'Customer role.', 'woocommerce' ),
500
					'type'        => 'string',
501
					'context'     => array( 'view', 'edit' ),
502
					'readonly'    => true,
503
				),
504
				'username'           => array(
505
					'description' => __( 'Customer login name.', 'woocommerce' ),
506
					'type'        => 'string',
507
					'context'     => array( 'view', 'edit' ),
508
					'arg_options' => array(
509
						'sanitize_callback' => 'sanitize_user',
510
					),
511
				),
512
				'password'           => array(
513
					'description' => __( 'Customer password.', 'woocommerce' ),
514
					'type'        => 'string',
515
					'context'     => array( 'edit' ),
516
				),
517
				'billing'            => array(
518
					'description' => __( 'List of billing address data.', 'woocommerce' ),
519
					'type'        => 'object',
520
					'context'     => array( 'view', 'edit' ),
521
					'properties'  => array(
522
						'first_name' => array(
523
							'description' => __( 'First name.', 'woocommerce' ),
524
							'type'        => 'string',
525
							'context'     => array( 'view', 'edit' ),
526
						),
527
						'last_name'  => array(
528
							'description' => __( 'Last name.', 'woocommerce' ),
529
							'type'        => 'string',
530
							'context'     => array( 'view', 'edit' ),
531
						),
532
						'company'    => array(
533
							'description' => __( 'Company name.', 'woocommerce' ),
534
							'type'        => 'string',
535
							'context'     => array( 'view', 'edit' ),
536
						),
537
						'address_1'  => array(
538
							'description' => __( 'Address line 1', 'woocommerce' ),
539
							'type'        => 'string',
540
							'context'     => array( 'view', 'edit' ),
541
						),
542
						'address_2'  => array(
543
							'description' => __( 'Address line 2', 'woocommerce' ),
544
							'type'        => 'string',
545
							'context'     => array( 'view', 'edit' ),
546
						),
547
						'city'       => array(
548
							'description' => __( 'City name.', 'woocommerce' ),
549
							'type'        => 'string',
550
							'context'     => array( 'view', 'edit' ),
551
						),
552
						'state'      => array(
553
							'description' => __( 'ISO code or name of the state, province or district.', 'woocommerce' ),
554
							'type'        => 'string',
555
							'context'     => array( 'view', 'edit' ),
556
						),
557
						'postcode'   => array(
558
							'description' => __( 'Postal code.', 'woocommerce' ),
559
							'type'        => 'string',
560
							'context'     => array( 'view', 'edit' ),
561
						),
562
						'country'    => array(
563
							'description' => __( 'ISO code of the country.', 'woocommerce' ),
564
							'type'        => 'string',
565
							'context'     => array( 'view', 'edit' ),
566
						),
567
						'email'      => array(
568
							'description' => __( 'Email address.', 'woocommerce' ),
569
							'type'        => 'string',
570
							'format'      => 'email',
571
							'context'     => array( 'view', 'edit' ),
572
						),
573
						'phone'      => array(
574
							'description' => __( 'Phone number.', 'woocommerce' ),
575
							'type'        => 'string',
576
							'context'     => array( 'view', 'edit' ),
577
						),
578
					),
579
				),
580
				'shipping'           => array(
581
					'description' => __( 'List of shipping address data.', 'woocommerce' ),
582
					'type'        => 'object',
583
					'context'     => array( 'view', 'edit' ),
584
					'properties'  => array(
585
						'first_name' => array(
586
							'description' => __( 'First name.', 'woocommerce' ),
587
							'type'        => 'string',
588
							'context'     => array( 'view', 'edit' ),
589
						),
590
						'last_name'  => array(
591
							'description' => __( 'Last name.', 'woocommerce' ),
592
							'type'        => 'string',
593
							'context'     => array( 'view', 'edit' ),
594
						),
595
						'company'    => array(
596
							'description' => __( 'Company name.', 'woocommerce' ),
597
							'type'        => 'string',
598
							'context'     => array( 'view', 'edit' ),
599
						),
600
						'address_1'  => array(
601
							'description' => __( 'Address line 1', 'woocommerce' ),
602
							'type'        => 'string',
603
							'context'     => array( 'view', 'edit' ),
604
						),
605
						'address_2'  => array(
606
							'description' => __( 'Address line 2', 'woocommerce' ),
607
							'type'        => 'string',
608
							'context'     => array( 'view', 'edit' ),
609
						),
610
						'city'       => array(
611
							'description' => __( 'City name.', 'woocommerce' ),
612
							'type'        => 'string',
613
							'context'     => array( 'view', 'edit' ),
614
						),
615
						'state'      => array(
616
							'description' => __( 'ISO code or name of the state, province or district.', 'woocommerce' ),
617
							'type'        => 'string',
618
							'context'     => array( 'view', 'edit' ),
619
						),
620
						'postcode'   => array(
621
							'description' => __( 'Postal code.', 'woocommerce' ),
622
							'type'        => 'string',
623
							'context'     => array( 'view', 'edit' ),
624
						),
625
						'country'    => array(
626
							'description' => __( 'ISO code of the country.', 'woocommerce' ),
627
							'type'        => 'string',
628
							'context'     => array( 'view', 'edit' ),
629
						),
630
					),
631
				),
632
				'is_paying_customer' => array(
633
					'description' => __( 'Is the customer a paying customer?', 'woocommerce' ),
634
					'type'        => 'bool',
635
					'context'     => array( 'view', 'edit' ),
636
					'readonly'    => true,
637
				),
638
				'avatar_url'         => array(
639
					'description' => __( 'Avatar URL.', 'woocommerce' ),
640
					'type'        => 'string',
641
					'context'     => array( 'view', 'edit' ),
642
					'readonly'    => true,
643
				),
644
				'meta_data'          => array(
645
					'description' => __( 'Meta data.', 'woocommerce' ),
646
					'type'        => 'array',
647
					'context'     => array( 'view', 'edit' ),
648
					'items'       => array(
649
						'type'       => 'object',
650
						'properties' => array(
651
							'id'    => array(
652
								'description' => __( 'Meta ID.', 'woocommerce' ),
653
								'type'        => 'integer',
654
								'context'     => array( 'view', 'edit' ),
655
								'readonly'    => true,
656
							),
657
							'key'   => array(
658
								'description' => __( 'Meta key.', 'woocommerce' ),
659
								'type'        => 'string',
660
								'context'     => array( 'view', 'edit' ),
661
							),
662
							'value' => array(
663
								'description' => __( 'Meta value.', 'woocommerce' ),
664
								'type'        => 'mixed',
665
								'context'     => array( 'view', 'edit' ),
666
							),
667
						),
668
					),
669
				),
670
			),
671
		);
672
673
		return $this->add_additional_fields_schema( $schema );
674
	}
675
676
	/**
677
	 * Get role names.
678
	 *
679
	 * @return array
680
	 */
681
	protected function get_role_names() {
682
		global $wp_roles;
683
684
		return array_keys( $wp_roles->role_names );
685
	}
686
687
	/**
688
	 * Get the query params for collections.
689
	 *
690
	 * @return array
691
	 */
692
	public function get_collection_params() {
693
		$params = parent::get_collection_params();
694
695
		$params['context']['default'] = 'view';
696
697
		$params['exclude'] = array(
698
			'description'       => __( 'Ensure result set excludes specific IDs.', 'woocommerce' ),
699
			'type'              => 'array',
700
			'items'             => array(
701
				'type'          => 'integer',
702
			),
703
			'default'           => array(),
704
			'sanitize_callback' => 'wp_parse_id_list',
705
		);
706
		$params['include'] = array(
707
			'description'       => __( 'Limit result set to specific IDs.', 'woocommerce' ),
708
			'type'              => 'array',
709
			'items'             => array(
710
				'type'          => 'integer',
711
			),
712
			'default'           => array(),
713
			'sanitize_callback' => 'wp_parse_id_list',
714
		);
715
		$params['offset'] = array(
716
			'description'        => __( 'Offset the result set by a specific number of items.', 'woocommerce' ),
717
			'type'               => 'integer',
718
			'sanitize_callback'  => 'absint',
719
			'validate_callback'  => 'rest_validate_request_arg',
720
		);
721
		$params['order'] = array(
722
			'default'            => 'asc',
723
			'description'        => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
724
			'enum'               => array( 'asc', 'desc' ),
725
			'sanitize_callback'  => 'sanitize_key',
726
			'type'               => 'string',
727
			'validate_callback'  => 'rest_validate_request_arg',
728
		);
729
		$params['orderby'] = array(
730
			'default'            => 'name',
731
			'description'        => __( 'Sort collection by object attribute.', 'woocommerce' ),
732
			'enum'               => array(
733
				'id',
734
				'include',
735
				'name',
736
				'registered_date',
737
			),
738
			'sanitize_callback'  => 'sanitize_key',
739
			'type'               => 'string',
740
			'validate_callback'  => 'rest_validate_request_arg',
741
		);
742
		$params['email'] = array(
743
			'description'        => __( 'Limit result set to resources with a specific email.', 'woocommerce' ),
744
			'type'               => 'string',
745
			'format'             => 'email',
746
			'validate_callback'  => 'rest_validate_request_arg',
747
		);
748
		$params['role'] = array(
749
			'description'        => __( 'Limit result set to resources with a specific role.', 'woocommerce' ),
750
			'type'               => 'string',
751
			'default'            => 'customer',
752
			'enum'               => array_merge( array( 'all' ), $this->get_role_names() ),
753
			'validate_callback'  => 'rest_validate_request_arg',
754
		);
755
		return $params;
756
	}
757
}
758