Completed
Pull Request — master (#11797)
by Aristeides
08:16
created

WC_REST_Coupons_Controller   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 637
Duplicated Lines 16.64 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 4
Bugs 1 Features 0
Metric Value
c 4
b 1
f 0
dl 106
loc 637
rs 8.076
wmc 51
lcom 1
cbo 2

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A query_args() 0 11 2
A register_routes() 60 60 1
C prepare_item_for_database() 0 59 11
B create_item() 31 31 3
B update_item() 3 29 4
A save_coupon() 0 5 1
A get_coupon_expiry_date() 0 7 2
A add_post_meta_fields() 0 51 2
F update_post_meta_fields() 0 72 17
B get_item_schema() 0 137 1
A get_collection_params() 12 12 1
B prepare_item_for_response() 0 53 5

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like WC_REST_Coupons_Controller often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WC_REST_Coupons_Controller, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * REST API Coupons controller
4
 *
5
 * Handles requests to the /coupons endpoint.
6
 *
7
 * @author   WooThemes
8
 * @category API
9
 * @package  WooCommerce/API
10
 * @since    2.6.0
11
 */
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * REST API Coupons controller class.
19
 *
20
 * @package WooCommerce/API
21
 * @extends WC_REST_Posts_Controller
22
 */
23
class WC_REST_Coupons_Controller extends WC_REST_Posts_Controller {
24
25
	/**
26
	 * Endpoint namespace.
27
	 *
28
	 * @var string
29
	 */
30
	protected $namespace = 'wc/v1';
31
32
	/**
33
	 * Route base.
34
	 *
35
	 * @var string
36
	 */
37
	protected $rest_base = 'coupons';
38
39
	/**
40
	 * Post type.
41
	 *
42
	 * @var string
43
	 */
44
	protected $post_type = 'shop_coupon';
45
46
	/**
47
	 * Order refunds actions.
48
	 */
49
	public function __construct() {
50
		add_filter( "woocommerce_rest_{$this->post_type}_query", array( $this, 'query_args' ), 10, 2 );
51
	}
52
53
	/**
54
	 * Register the routes for coupons.
55
	 */
56 View Code Duplication
	public function register_routes() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
57
		register_rest_route( $this->namespace, '/' . $this->rest_base, array(
58
			array(
59
				'methods'             => WP_REST_Server::READABLE,
60
				'callback'            => array( $this, 'get_items' ),
61
				'permission_callback' => array( $this, 'get_items_permissions_check' ),
62
				'args'                => $this->get_collection_params(),
63
			),
64
			array(
65
				'methods'             => WP_REST_Server::CREATABLE,
66
				'callback'            => array( $this, 'create_item' ),
67
				'permission_callback' => array( $this, 'create_item_permissions_check' ),
68
				'args'                => array_merge( $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), array(
69
					'code' => array(
70
						'required' => true,
71
					),
72
				) ),
73
			),
74
			'schema' => array( $this, 'get_public_item_schema' ),
75
		) );
76
77
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
78
			array(
79
				'methods'             => WP_REST_Server::READABLE,
80
				'callback'            => array( $this, 'get_item' ),
81
				'permission_callback' => array( $this, 'get_item_permissions_check' ),
82
				'args'                => array(
83
					'context'         => $this->get_context_param( array( 'default' => 'view' ) ),
84
				),
85
			),
86
			array(
87
				'methods'         => WP_REST_Server::EDITABLE,
88
				'callback'        => array( $this, 'update_item' ),
89
				'permission_callback' => array( $this, 'update_item_permissions_check' ),
90
				'args'            => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
91
			),
92
			array(
93
				'methods'             => WP_REST_Server::DELETABLE,
94
				'callback'            => array( $this, 'delete_item' ),
95
				'permission_callback' => array( $this, 'delete_item_permissions_check' ),
96
				'args'                => array(
97
					'force' => array(
98
						'default'     => false,
99
						'description' => __( 'Whether to bypass trash and force deletion.', 'woocommerce' ),
100
					),
101
				),
102
			),
103
			'schema' => array( $this, 'get_public_item_schema' ),
104
		) );
105
106
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/batch', array(
107
			array(
108
				'methods'             => WP_REST_Server::EDITABLE,
109
				'callback'            => array( $this, 'batch_items' ),
110
				'permission_callback' => array( $this, 'batch_items_permissions_check' ),
111
				'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
112
			),
113
			'schema' => array( $this, 'get_public_batch_schema' ),
114
		) );
115
	}
116
117
	/**
118
	 * Query args.
119
	 *
120
	 * @param array $args
121
	 * @param WP_REST_Request $request
122
	 * @return array
123
	 */
124
	public function query_args( $args, $request ) {
125
		global $wpdb;
126
127
		if ( ! empty( $request['code'] ) ) {
128
			$id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish'", $request['code'] ) );
129
130
			$args['post__in'] = array( $id );
131
		}
132
133
		return $args;
134
	}
135
136
	/**
137
	 * Prepare a single coupon output for response.
138
	 *
139
	 * @param WP_Post $post Post object.
140
	 * @param WP_REST_Request $request Request object.
141
	 * @return WP_REST_Response $data
142
	 */
143
	public function prepare_item_for_response( $post, $request ) {
144
		// Get the coupon code.
145
		$code = wc_get_coupon_code_by_id( $post->ID );
146
147
		$coupon = new WC_Coupon( $code );
148
149
		$data = array(
150
			'id'                           => $coupon->get_id(),
151
			'code'                         => $coupon->get_code(),
152
			'date_created'                 => wc_rest_prepare_date_response( $post->post_date_gmt ),
153
			'date_modified'                => wc_rest_prepare_date_response( $post->post_modified_gmt ),
154
			'discount_type'                => $coupon->get_discount_type(),
155
			'description'                  => $coupon->get_description(),
156
			'amount'                       => wc_format_decimal( $coupon->get_amount(), 2 ),
0 ignored issues
show
Bug introduced by
It seems like $coupon->get_amount() targeting WC_Coupon::get_amount() can also be of type array; however, wc_format_decimal() does only seem to accept double|string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
157
			'expiry_date'                  => $coupon->get_expiry_date() ? wc_rest_prepare_date_response( $coupon->get_expiry_date() ) : null,
158
			'usage_count'                  => (int) $coupon->get_usage_count(),
159
			'individual_use'               => $coupon->get_individual_use(),
160
			'product_ids'                  => array_map( 'absint', (array) $coupon->get_product_ids() ),
161
			'exclude_product_ids'          => array_map( 'absint', (array) $coupon->get_excluded_product_ids() ),
162
			'usage_limit'                  => $coupon->get_usage_limit() ? $coupon->get_usage_limit() : null,
163
			'usage_limit_per_user'         => $coupon->get_usage_limit_per_user() ? $coupon->get_usage_limit_per_user() : null,
164
			'limit_usage_to_x_items'       => (int) $coupon->get_limit_usage_to_x_items(),
165
			'free_shipping'                => $coupon->get_free_shipping(),
166
			'product_categories'           => array_map( 'absint', (array) $coupon->get_product_categories() ),
167
			'excluded_product_categories'  => array_map( 'absint', (array) $coupon->get_excluded_product_categories() ),
168
			'exclude_sale_items'           => $coupon->get_exclude_sale_items(),
169
			'minimum_amount'               => wc_format_decimal( $coupon->get_minimum_amount(), 2 ),
0 ignored issues
show
Bug introduced by
It seems like $coupon->get_minimum_amount() targeting WC_Coupon::get_minimum_amount() can also be of type array; however, wc_format_decimal() does only seem to accept double|string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
170
			'maximum_amount'               => wc_format_decimal( $coupon->get_maximum_amount(), 2 ),
0 ignored issues
show
Bug introduced by
It seems like $coupon->get_maximum_amount() targeting WC_Coupon::get_maximum_amount() can also be of type array; however, wc_format_decimal() does only seem to accept double|string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
171
			'email_restrictions'           => $coupon->get_email_restrictions(),
172
			'used_by'                      => $coupon->get_used_by(),
173
		);
174
175
		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
176
		$data    = $this->add_additional_fields_to_object( $data, $request );
177
		$data    = $this->filter_response_by_context( $data, $context );
178
179
		// Wrap the data in a response object.
180
		$response = rest_ensure_response( $data );
181
182
		$response->add_links( $this->prepare_links( $post ) );
183
184
		/**
185
		 * Filter the data for a response.
186
		 *
187
		 * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being
188
		 * prepared for the response.
189
		 *
190
		 * @param WP_REST_Response   $response   The response object.
191
		 * @param WP_Post            $post       Post object.
192
		 * @param WP_REST_Request    $request    Request object.
193
		 */
194
		return apply_filters( "woocommerce_rest_prepare_{$this->post_type}", $response, $post, $request );
195
	}
196
197
	/**
198
	 * Prepare a single coupon for create or update.
199
	 *
200
	 * @param WP_REST_Request $request Request object.
201
	 * @return WP_Error|stdClass $data Post object.
202
	 */
203
	protected function prepare_item_for_database( $request ) {
204
		global $wpdb;
205
206
		// ID.
207
		if ( isset( $request['id'] ) ) {
208
			$code   = wc_get_coupon_code_by_id( $request['id'] );
209
			$coupon = new WC_Coupon( $code );
210
		} else {
211
			$coupon = new WC_Coupon();
212
		}
213
214
		$schema = $this->get_item_schema();
215
216
		// Validate required POST fields.
217
		if ( 'POST' === $request->get_method() && 0 === $coupon->get_id() ) {
218
			if ( empty( $request['code'] ) ) {
219
				return new WP_Error( 'woocommerce_rest_empty_coupon_code', sprintf( __( 'The coupon code cannot be empty.', 'woocommerce' ), 'code' ), array( 'status' => 400 ) );
220
			}
221
		}
222
223
		// Code.
224
		if ( ! empty( $schema['properties']['code'] ) && ! empty( $request['code'] ) ) {
225
			$coupon_code = apply_filters( 'woocommerce_coupon_code', $request['code'] );
226
			$id = $coupon->get_id() ? $coupon->get_id() : 0;
227
228
			// Check for duplicate coupon codes.
229
			$coupon_found = $wpdb->get_var( $wpdb->prepare( "
230
				SELECT $wpdb->posts.ID
231
				FROM $wpdb->posts
232
				WHERE $wpdb->posts.post_type = 'shop_coupon'
233
				AND $wpdb->posts.post_status = 'publish'
234
				AND $wpdb->posts.post_title = '%s'
235
				AND $wpdb->posts.ID != %s
236
			 ", $coupon_code, $id ) );
237
238
			if ( $coupon_found ) {
239
				return new WP_Error( 'woocommerce_rest_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ), array( 'status' => 400 ) );
240
			}
241
242
			$coupon->set_code( $coupon_code );
243
		}
244
245
		// Coupon description (excerpt).
246
		if ( ! empty( $schema['properties']['description'] ) && isset( $request['description'] ) ) {
247
			$coupon->set_description( wp_filter_post_kses( $request['description'] ) );
248
		}
249
250
		/**
251
		 * Filter the query_vars used in `get_items` for the constructed query.
252
		 *
253
		 * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being
254
		 * prepared for insertion.
255
		 *
256
		 * @param stdClass        $data An object representing a single item prepared
257
		 *                                       for inserting or updating the database.
258
		 * @param WP_REST_Request $request       Request object.
259
		 */
260
		return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}", $coupon, $request );
261
	}
262
263
	/**
264
	 * Create a single item.
265
	 *
266
	 * @param WP_REST_Request $request Full details about the request.
267
	 * @return WP_Error|WP_REST_Response
268
	 */
269 View Code Duplication
	public function create_item( $request ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
270
		if ( ! empty( $request['id'] ) ) {
271
			return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) );
272
		}
273
274
		$coupon_id = $this->save_coupon( $request );
275
		if ( is_wp_error( $coupon_id ) ) {
276
			return $coupon_id;
277
		}
278
279
		$post = get_post( $coupon_id );
280
		$this->update_additional_fields_for_object( $post, $request );
281
282
		$this->add_post_meta_fields( $post, $request );
283
284
		/**
285
		 * Fires after a single item is created or updated via the REST API.
286
		 *
287
		 * @param object          $post      Inserted object (not a WP_Post object).
288
		 * @param WP_REST_Request $request   Request object.
289
		 * @param boolean         $creating  True when creating item, false when updating.
290
		 */
291
		do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, true );
292
		$request->set_param( 'context', 'edit' );
293
		$response = $this->prepare_item_for_response( $post, $request );
294
		$response = rest_ensure_response( $response );
295
		$response->set_status( 201 );
296
		$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post->ID ) ) );
297
298
		return $response;
299
	}
300
301
	/**
302
	 * Update a single coupon.
303
	 *
304
	 * @param WP_REST_Request $request Full details about the request.
305
	 * @return WP_Error|WP_REST_Response
306
	 */
307
	public function update_item( $request ) {
308
		$post_id = (int) $request['id'];
309
310 View Code Duplication
		if ( empty( $post_id ) || $this->post_type !== get_post_type( $post_id ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
311
			return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) );
312
		}
313
314
		$coupon_id = $this->save_coupon( $request );
315
		if ( is_wp_error( $coupon_id ) ) {
316
			return $coupon_id;
317
		}
318
319
		$post = get_post( $coupon_id );
320
		$this->update_additional_fields_for_object( $post, $request );
321
322
		$this->update_post_meta_fields( $post, $request );
323
324
		/**
325
		 * Fires after a single item is created or updated via the REST API.
326
		 *
327
		 * @param object          $post      Inserted object (not a WP_Post object).
328
		 * @param WP_REST_Request $request   Request object.
329
		 * @param boolean         $creating  True when creating item, false when updating.
330
		 */
331
		do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, false );
332
		$request->set_param( 'context', 'edit' );
333
		$response = $this->prepare_item_for_response( $post, $request );
334
		return rest_ensure_response( $response );
335
	}
336
337
	/**
338
	 * Saves a coupon to the database.
339
	 */
340
	public function save_coupon( $request ) {
341
		$coupon = $this->prepare_item_for_database( $request );
342
		$coupon->save();
343
		return $coupon->get_id();
344
	}
345
346
	/**
347
	 * Expiry date format.
348
	 *
349
	 * @param string $expiry_date
350
	 * @return string
351
	 */
352
	protected function get_coupon_expiry_date( $expiry_date ) {
353
		if ( '' != $expiry_date ) {
354
			return date( 'Y-m-d', strtotime( $expiry_date ) );
355
		}
356
357
		return '';
358
	}
359
360
	/**
361
	 * Add post meta fields.
362
	 *
363
	 * @param WP_Post $post
364
	 * @param WP_REST_Request $request
365
	 * @return bool|WP_Error
366
	 */
367
	protected function add_post_meta_fields( $post, $request ) {
368
		$data = array_filter( $request->get_params() );
369
370
		$defaults = array(
371
			'discount_type'                => 'fixed_cart',
372
			'amount'                       => 0,
373
			'individual_use'               => false,
374
			'product_ids'                  => array(),
375
			'exclude_product_ids'          => array(),
376
			'usage_limit'                  => '',
377
			'usage_limit_per_user'         => '',
378
			'limit_usage_to_x_items'       => '',
379
			'usage_count'                  => '',
380
			'expiry_date'                  => '',
381
			'free_shipping'                => false,
382
			'product_categories'           => array(),
383
			'excluded_product_categories'  => array(),
384
			'exclude_sale_items'           => false,
385
			'minimum_amount'               => '',
386
			'maximum_amount'               => '',
387
			'email_restrictions'           => array(),
388
			'description'                  => '',
389
		);
390
391
		$data = wp_parse_args( $data, $defaults );
392
393
		if ( ! empty( $post->post_title ) ) {
394
			$coupon = new WC_Coupon( $post->post_title );
395
			// Set coupon meta.
396
			$coupon->set_discount_type( $data['discount_type'] );
397
			$coupon->set_amount( $data['amount'] );
398
			$coupon->set_individual_use( $data['individual_use'] );
399
			$coupon->set_product_ids( $data['product_ids'] );
400
			$coupon->set_excluded_product_ids( $data['exclude_product_ids'] );
401
			$coupon->set_usage_limit( $data['usage_limit'] );
402
			$coupon->set_usage_limit_per_user( $data['usage_limit_per_user'] );
403
			$coupon->set_limit_usage_to_x_items( $data['limit_usage_to_x_items'] );
404
			$coupon->set_usage_count( $data['usage_count'] );
405
			$coupon->set_expiry_date( $data['expiry_date'] );
406
			$coupon->set_free_shipping( $data['free_shipping'] );
407
			$coupon->set_product_categories( $data['product_categories'] );
408
			$coupon->set_excluded_product_categories( $data['excluded_product_categories'] );
409
			$coupon->set_exclude_sale_items( $data['exclude_sale_items'] );
410
			$coupon->set_minimum_amount( $data['minimum_amount'] );
411
			$coupon->set_maximum_amount( $data['maximum_amount'] );
412
			$coupon->set_email_restrictions( $data['email_restrictions'] );
413
			$coupon->save();
414
		}
415
416
		return true;
417
	}
418
419
	/**
420
	 * Update post meta fields.
421
	 *
422
	 * @param WP_Post $post
423
	 * @param WP_REST_Request $request
424
	 * @return bool|WP_Error
425
	 */
426
	protected function update_post_meta_fields( $post, $request ) {
427
428
		$coupon = new WC_Coupon( $post->post_title );
429
430
		if ( isset( $request['amount'] ) ) {
431
			$coupon->set_amount( $request['amount'] );
432
		}
433
434
		if ( isset( $request['individual_use'] ) ) {
435
			$coupon->set_individual_use( $request['individual_use'] );
436
		}
437
438
		if ( isset( $request['product_ids'] ) ) {
439
			$coupon->set_product_ids( $request['product_ids'] );
440
		}
441
442
		if ( isset( $request['exclude_product_ids'] ) ) {
443
			$coupon->set_excluded_product_ids( $request['exclude_product_ids'] );
444
		}
445
446
		if ( isset( $request['usage_limit'] ) ) {
447
			$coupon->set_usage_limit( $request['usage_limit'] );
448
		}
449
450
		if ( isset( $request['usage_limit_per_user'] ) ) {
451
			$coupon->set_usage_limit_per_user( $request['usage_limit_per_user'] );
452
		}
453
454
		if ( isset( $request['limit_usage_to_x_items'] ) ) {
455
			$coupon->set_limit_usage_to_x_items( $request['limit_usage_to_x_items'] );
456
		}
457
458
		if ( isset( $request['usage_count'] ) ) {
459
			$coupon->set_usage_count( $request['usage_count'] );
460
		}
461
462
		if ( isset( $request['expiry_date'] ) ) {
463
			$coupon->set_expiry_date( $request['expiry_date'] );
464
		}
465
466
		if ( isset( $request['free_shipping'] ) ) {
467
			$coupon->set_free_shipping( $request['free_shipping'] );
468
		}
469
470
		if ( isset( $request['product_categories'] ) ) {
471
			$coupon->set_product_categories( $request['product_categories'] );
472
		}
473
474
		if ( isset( $request['excluded_product_categories'] ) ) {
475
			$coupon->set_excluded_product_categories( $request['excluded_product_categories'] );
476
		}
477
478
		if ( isset( $request['exclude_sale_items'] ) ) {
479
			$coupon->set_exclude_sale_items( $request['exclude_sale_items'] );
480
		}
481
482
		if ( isset( $request['minimum_amount'] ) ) {
483
			$coupon->set_minimum_amount( $request['minimum_amount'] );
484
		}
485
486
		if ( isset( $request['maximum_amount'] ) ) {
487
			$coupon->set_maximum_amount( $request['maximum_amount'] );
488
		}
489
490
		if ( isset( $request['email_restrictions'] ) ) {
491
			$coupon->set_email_restrictions( $request['email_restrictions'] );
492
		}
493
494
		$coupon->save();
495
496
		return true;
497
	}
498
499
	/**
500
	 * Get the Coupon's schema, conforming to JSON Schema.
501
	 *
502
	 * @return array
503
	 */
504
	public function get_item_schema() {
505
506
		$schema = array(
507
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
508
			'title'      => $this->post_type,
509
			'type'       => 'object',
510
			'properties' => array(
511
				'id' => array(
512
					'description' => __( 'Unique identifier for the object.', 'woocommerce' ),
513
					'type'        => 'integer',
514
					'context'     => array( 'view', 'edit' ),
515
					'readonly'    => true,
516
				),
517
				'code' => array(
518
					'description' => __( 'Coupon code.', 'woocommerce' ),
519
					'type'        => 'string',
520
					'context'     => array( 'view', 'edit' ),
521
				),
522
				'date_created' => array(
523
					'description' => __( "The date the coupon was created, in the site's timezone.", 'woocommerce' ),
524
					'type'        => 'date-time',
525
					'context'     => array( 'view', 'edit' ),
526
					'readonly'    => true,
527
				),
528
				'date_modified' => array(
529
					'description' => __( "The date the coupon was last modified, in the site's timezone.", 'woocommerce' ),
530
					'type'        => 'date-time',
531
					'context'     => array( 'view', 'edit' ),
532
					'readonly'    => true,
533
				),
534
				'description' => array(
535
					'description' => __( 'Coupon description.', 'woocommerce' ),
536
					'type'        => 'string',
537
					'context'     => array( 'view', 'edit' ),
538
				),
539
				'discount_type' => array(
540
					'description' => __( 'Determines the type of discount that will be applied.', 'woocommerce' ),
541
					'type'        => 'string',
542
					'default'     => 'fixed_cart',
543
					'enum'        => array_keys( wc_get_coupon_types() ),
544
					'context'     => array( 'view', 'edit' ),
545
				),
546
				'amount' => array(
547
					'description' => __( 'The amount of discount.', 'woocommerce' ),
548
					'type'        => 'string',
549
					'context'     => array( 'view', 'edit' ),
550
				),
551
				'expiry_date' => array(
552
					'description' => __( 'UTC DateTime when the coupon expires.', 'woocommerce' ),
553
					'type'        => 'string',
554
					'context'     => array( 'view', 'edit' ),
555
				),
556
				'usage_count' => array(
557
					'description' => __( 'Number of times the coupon has been used already.', 'woocommerce' ),
558
					'type'        => 'integer',
559
					'context'     => array( 'view', 'edit' ),
560
					'readonly'    => true,
561
				),
562
				'individual_use' => array(
563
					'description' => __( 'Whether coupon can only be used individually.', 'woocommerce' ),
564
					'type'        => 'boolean',
565
					'default'     => false,
566
					'context'     => array( 'view', 'edit' ),
567
				),
568
				'product_ids' => array(
569
					'description' => __( "List of product ID's the coupon can be used on.", 'woocommerce' ),
570
					'type'        => 'array',
571
					'context'     => array( 'view', 'edit' ),
572
				),
573
				'exclude_product_ids' => array(
574
					'description' => __( "List of product ID's the coupon cannot be used on.", 'woocommerce' ),
575
					'type'        => 'array',
576
					'context'     => array( 'view', 'edit' ),
577
				),
578
				'usage_limit' => array(
579
					'description' => __( 'How many times the coupon can be used.', 'woocommerce' ),
580
					'type'        => 'integer',
581
					'context'     => array( 'view', 'edit' ),
582
				),
583
				'usage_limit_per_user' => array(
584
					'description' => __( 'How many times the coupon can be used per customer.', 'woocommerce' ),
585
					'type'        => 'integer',
586
					'context'     => array( 'view', 'edit' ),
587
				),
588
				'limit_usage_to_x_items' => array(
589
					'description' => __( 'Max number of items in the cart the coupon can be applied to.', 'woocommerce' ),
590
					'type'        => 'integer',
591
					'context'     => array( 'view', 'edit' ),
592
				),
593
				'free_shipping' => array(
594
					'description' => __( 'Define if can be applied for free shipping.', 'woocommerce' ),
595
					'type'        => 'boolean',
596
					'default'     => false,
597
					'context'     => array( 'view', 'edit' ),
598
				),
599
				'product_categories' => array(
600
					'description' => __( "List of category ID's the coupon applies to.", 'woocommerce' ),
601
					'type'        => 'array',
602
					'context'     => array( 'view', 'edit' ),
603
				),
604
				'excluded_product_categories' => array(
605
					'description' => __( "List of category ID's the coupon does not apply to.", 'woocommerce' ),
606
					'type'        => 'array',
607
					'context'     => array( 'view', 'edit' ),
608
				),
609
				'exclude_sale_items' => array(
610
					'description' => __( 'Define if should not apply when have sale items.', 'woocommerce' ),
611
					'type'        => 'boolean',
612
					'default'     => false,
613
					'context'     => array( 'view', 'edit' ),
614
				),
615
				'minimum_amount' => array(
616
					'description' => __( 'Minimum order amount that needs to be in the cart before coupon applies.', 'woocommerce' ),
617
					'type'        => 'string',
618
					'context'     => array( 'view', 'edit' ),
619
				),
620
				'maximum_amount' => array(
621
					'description' => __( 'Maximum order amount allowed when using the coupon.', 'woocommerce' ),
622
					'type'        => 'string',
623
					'context'     => array( 'view', 'edit' ),
624
				),
625
				'email_restrictions' => array(
626
					'description' => __( 'List of email addresses that can use this coupon.', 'woocommerce' ),
627
					'type'        => 'array',
628
					'context'     => array( 'view', 'edit' ),
629
				),
630
				'used_by' => array(
631
					'description' => __( 'List of user IDs who have used the coupon.', 'woocommerce' ),
632
					'type'        => 'array',
633
					'context'     => array( 'view', 'edit' ),
634
					'readonly'    => true,
635
				),
636
			),
637
		);
638
639
		return $this->add_additional_fields_schema( $schema );
640
	}
641
642
	/**
643
	 * Get the query params for collections of attachments.
644
	 *
645
	 * @return array
646
	 */
647 View Code Duplication
	public function get_collection_params() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
648
		$params = parent::get_collection_params();
649
650
		$params['code'] = array(
651
			'description'       => __( 'Limit result set to resources with a specific code.', 'woocommerce' ),
652
			'type'              => 'string',
653
			'sanitize_callback' => 'sanitize_text_field',
654
			'validate_callback' => 'rest_validate_request_arg',
655
		);
656
657
		return $params;
658
	}
659
}
660