Completed
Push — master ( f54ada...499e19 )
by Mike
22:45
created

WC_REST_Coupons_Controller::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
eloc 2
nc 1
nop 0
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
			$args['post__in'] = array( $id );
130
		}
131
132
		return $args;
133
	}
134
135
	/**
136
	 * Prepare a single coupon output for response.
137
	 *
138
	 * @param WP_Post $post Post object.
139
	 * @param WP_REST_Request $request Request object.
140
	 * @return WP_REST_Response $data
141
	 */
142
	public function prepare_item_for_response( $post, $request ) {
143
		$code           = wc_get_coupon_code_by_id( $post->ID );
144
		$coupon         = new WC_Coupon( $code );
145
		$data           = $coupon->get_data();
146
		$format_decimal = array( 'amount', 'minimum_amount', 'maximum_amount' );
147
		$format_date    = array( 'date_created', 'date_modified', 'date_expires' );
148
		$format_null    = array( 'usage_limit', 'usage_limit_per_user', 'limit_usage_to_x_items' );
149
150
		// Format decimal values.
151
		foreach ( $format_decimal as $key ) {
152
			$data[ $key ] = wc_format_decimal( $data[ $key ], 2 );
153
		}
154
155
		// Format date values.
156 View Code Duplication
		foreach ( $format_date as $key ) {
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...
157
			$data[ $key ] = $data[ $key ] ? wc_rest_prepare_date_response( get_gmt_from_date( date( 'Y-m-d H:i:s', $data[ $key ] ) ) ) : null;
158
		}
159
160
		// Format null values.
161
		foreach ( $format_null as $key ) {
162
			$data[ $key ] = $data[ $key ] ? $data[ $key ] : null;
163
		}
164
165
		$context  = ! empty( $request['context'] ) ? $request['context'] : 'view';
166
		$data     = $this->add_additional_fields_to_object( $data, $request );
167
		$data     = $this->filter_response_by_context( $data, $context );
168
		$response = rest_ensure_response( $data );
169
		$response->add_links( $this->prepare_links( $post ) );
170
171
		/**
172
		 * Filter the data for a response.
173
		 *
174
		 * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being
175
		 * prepared for the response.
176
		 *
177
		 * @param WP_REST_Response   $response   The response object.
178
		 * @param WP_Post            $post       Post object.
179
		 * @param WP_REST_Request    $request    Request object.
180
		 */
181
		return apply_filters( "woocommerce_rest_prepare_{$this->post_type}", $response, $post, $request );
182
	}
183
184
	/**
185
	 * Only reutrn writeable props from schema.
186
	 * @param  array $schema
187
	 * @return bool
188
	 */
189
	protected function filter_writable_props( $schema ) {
190
		return empty( $schema['readonly'] );
191
	}
192
193
	/**
194
	 * Prepare a single coupon for create or update.
195
	 *
196
	 * @param WP_REST_Request $request Request object.
197
	 * @return WP_Error|stdClass $data Post object.
198
	 */
199
	protected function prepare_item_for_database( $request ) {
200
		global $wpdb;
201
202
		$id        = isset( $request['id'] ) ? absint( $request['id'] ) : 0;
203
		$coupon    = new WC_Coupon( $id );
204
		$schema    = $this->get_item_schema();
205
		$data_keys = array_keys( array_filter( $schema['properties'], array( $this, 'filter_writable_props' ) ) );
206
207
		// BW compat
208
		if ( $request['exclude_product_ids'] ) {
209
			$request['excluded_product_ids'] = $request['exclude_product_ids'];
210
		}
211
		if ( $request['expiry_date'] ) {
212
			$request['date_expires'] = $request['expiry_date'];
213
		}
214
215
		// Validate required POST fields.
216
		if ( 'POST' === $request->get_method() && 0 === $coupon->get_id() ) {
217
			if ( empty( $request['code'] ) ) {
218
				return new WP_Error( 'woocommerce_rest_empty_coupon_code', sprintf( __( 'The coupon code cannot be empty.', 'woocommerce' ), 'code' ), array( 'status' => 400 ) );
219
			}
220
		}
221
222
		// Handle all writable props
223
		foreach ( $data_keys as $key ) {
224
			$value = $request[ $key ];
225
226
			if ( ! is_null( $value ) ) {
227
				switch ( $key ) {
228
					case 'code' :
229
						$coupon_code = apply_filters( 'woocommerce_coupon_code', $value );
230
						$id          = $coupon->get_id() ? $coupon->get_id() : 0;
231
						$id_from_code = wc_get_coupon_id_by_code( $coupon_code, $id );
232
233
						if ( $id_from_code ) {
234
							return new WP_Error( 'woocommerce_rest_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ), array( 'status' => 400 ) );
235
						}
236
237
						$coupon->set_code( $coupon_code );
238
						break;
239 View Code Duplication
					case 'meta_data' :
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...
240
						if ( is_array( $value ) ) {
241
							foreach ( $value as $meta ) {
242
								$coupon->update_meta_data( $meta['key'], $meta['value'], $meta['id'] );
243
							}
244
						}
245
						break;
246
					case 'description' :
247
						$coupon->set_description( wp_filter_post_kses( $value ) );
248
						break;
249
					default :
250
						if ( is_callable( array( $coupon, "set_{$key}" ) ) ) {
251
							$coupon->{"set_{$key}"}( $value );
252
						}
253
						break;
254
				}
255
			}
256
		}
257
258
		/**
259
		 * Filter the query_vars used in `get_items` for the constructed query.
260
		 *
261
		 * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being
262
		 * prepared for insertion.
263
		 *
264
		 * @param WC_Coupon       $coupon        The coupon object.
265
		 * @param WP_REST_Request $request       Request object.
266
		 */
267
		return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}", $coupon, $request );
268
	}
269
270
	/**
271
	 * Create a single item.
272
	 *
273
	 * @param WP_REST_Request $request Full details about the request.
274
	 * @return WP_Error|WP_REST_Response
275
	 */
276 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...
277
		if ( ! empty( $request['id'] ) ) {
278
			return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) );
279
		}
280
281
		$coupon_id = $this->save_coupon( $request );
282
		if ( is_wp_error( $coupon_id ) ) {
283
			return $coupon_id;
284
		}
285
286
		$post = get_post( $coupon_id );
287
		$this->update_additional_fields_for_object( $post, $request );
288
289
		$this->add_post_meta_fields( $post, $request );
0 ignored issues
show
Unused Code introduced by
The call to the method WC_REST_Coupons_Controller::add_post_meta_fields() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
290
291
		/**
292
		 * Fires after a single item is created or updated via the REST API.
293
		 *
294
		 * @param object          $post      Inserted object (not a WP_Post object).
295
		 * @param WP_REST_Request $request   Request object.
296
		 * @param boolean         $creating  True when creating item, false when updating.
297
		 */
298
		do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, true );
299
		$request->set_param( 'context', 'edit' );
300
		$response = $this->prepare_item_for_response( $post, $request );
301
		$response = rest_ensure_response( $response );
302
		$response->set_status( 201 );
303
		$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post->ID ) ) );
304
305
		return $response;
306
	}
307
308
	/**
309
	 * Update a single coupon.
310
	 *
311
	 * @param WP_REST_Request $request Full details about the request.
312
	 * @return WP_Error|WP_REST_Response
313
	 */
314 View Code Duplication
	public function update_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...
315
		try {
316
			$post_id = (int) $request['id'];
317
318
			if ( empty( $post_id ) || $this->post_type !== get_post_type( $post_id ) ) {
319
				return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) );
320
			}
321
322
			$coupon_id = $this->save_coupon( $request );
323
			if ( is_wp_error( $coupon_id ) ) {
324
				return $coupon_id;
325
			}
326
327
			$post = get_post( $coupon_id );
328
			$this->update_additional_fields_for_object( $post, $request );
329
330
			/**
331
			 * Fires after a single item is created or updated via the REST API.
332
			 *
333
			 * @param object          $post      Inserted object (not a WP_Post object).
334
			 * @param WP_REST_Request $request   Request object.
335
			 * @param boolean         $creating  True when creating item, false when updating.
336
			 */
337
			do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, false );
338
			$request->set_param( 'context', 'edit' );
339
			$response = $this->prepare_item_for_response( $post, $request );
340
			return rest_ensure_response( $response );
341
342
		} catch ( Exception $e ) {
343
			return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Exception as the method getErrorCode() does only exist in the following sub-classes of Exception: WC_CLI_Exception, WC_Data_Exception, WC_REST_Exception. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
344
		}
345
	}
346
347
	/**
348
	 * Saves a coupon to the database.
349
	 */
350
	public function save_coupon( $request ) {
351
		try {
352
			$coupon = $this->prepare_item_for_database( $request );
353
			$coupon->save();
354
			return $coupon->get_id();
355
		} catch ( WC_Data_Exception $e ) {
356
			return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
357
		} catch ( WC_REST_Exception $e ) {
358
			return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
359
		}
360
	}
361
362
	/**
363
	 * Get the Coupon's schema, conforming to JSON Schema.
364
	 *
365
	 * @return array
366
	 */
367
	public function get_item_schema() {
368
		$schema = array(
369
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
370
			'title'      => $this->post_type,
371
			'type'       => 'object',
372
			'properties' => array(
373
				'id' => array(
374
					'description' => __( 'Unique identifier for the object.', 'woocommerce' ),
375
					'type'        => 'integer',
376
					'context'     => array( 'view', 'edit' ),
377
					'readonly'    => true,
378
				),
379
				'code' => array(
380
					'description' => __( 'Coupon code.', 'woocommerce' ),
381
					'type'        => 'string',
382
					'context'     => array( 'view', 'edit' ),
383
				),
384
				'date_created' => array(
385
					'description' => __( "The date the coupon was created, in the site's timezone.", 'woocommerce' ),
386
					'type'        => 'date-time',
387
					'context'     => array( 'view', 'edit' ),
388
					'readonly'    => true,
389
				),
390
				'date_modified' => array(
391
					'description' => __( "The date the coupon was last modified, in the site's timezone.", 'woocommerce' ),
392
					'type'        => 'date-time',
393
					'context'     => array( 'view', 'edit' ),
394
					'readonly'    => true,
395
				),
396
				'description' => array(
397
					'description' => __( 'Coupon description.', 'woocommerce' ),
398
					'type'        => 'string',
399
					'context'     => array( 'view', 'edit' ),
400
				),
401
				'discount_type' => array(
402
					'description' => __( 'Determines the type of discount that will be applied.', 'woocommerce' ),
403
					'type'        => 'string',
404
					'default'     => 'fixed_cart',
405
					'enum'        => array_keys( wc_get_coupon_types() ),
406
					'context'     => array( 'view', 'edit' ),
407
				),
408
				'amount' => array(
409
					'description' => __( 'The amount of discount.', 'woocommerce' ),
410
					'type'        => 'string',
411
					'context'     => array( 'view', 'edit' ),
412
				),
413
				'date_expires' => array(
414
					'description' => __( 'UTC DateTime when the coupon expires.', 'woocommerce' ),
415
					'type'        => 'string',
416
					'context'     => array( 'view', 'edit' ),
417
				),
418
				'usage_count' => array(
419
					'description' => __( 'Number of times the coupon has been used already.', 'woocommerce' ),
420
					'type'        => 'integer',
421
					'context'     => array( 'view', 'edit' ),
422
					'readonly'    => true,
423
				),
424
				'individual_use' => array(
425
					'description' => __( 'Whether coupon can only be used individually.', 'woocommerce' ),
426
					'type'        => 'boolean',
427
					'default'     => false,
428
					'context'     => array( 'view', 'edit' ),
429
				),
430
				'product_ids' => array(
431
					'description' => __( "List of product ID's the coupon can be used on.", 'woocommerce' ),
432
					'type'        => 'array',
433
					'context'     => array( 'view', 'edit' ),
434
				),
435
				'excluded_product_ids' => array(
436
					'description' => __( "List of product ID's the coupon cannot be used on.", 'woocommerce' ),
437
					'type'        => 'array',
438
					'context'     => array( 'view', 'edit' ),
439
				),
440
				'usage_limit' => array(
441
					'description' => __( 'How many times the coupon can be used.', 'woocommerce' ),
442
					'type'        => 'integer',
443
					'context'     => array( 'view', 'edit' ),
444
				),
445
				'usage_limit_per_user' => array(
446
					'description' => __( 'How many times the coupon can be used per customer.', 'woocommerce' ),
447
					'type'        => 'integer',
448
					'context'     => array( 'view', 'edit' ),
449
				),
450
				'limit_usage_to_x_items' => array(
451
					'description' => __( 'Max number of items in the cart the coupon can be applied to.', 'woocommerce' ),
452
					'type'        => 'integer',
453
					'context'     => array( 'view', 'edit' ),
454
				),
455
				'free_shipping' => array(
456
					'description' => __( 'Define if can be applied for free shipping.', 'woocommerce' ),
457
					'type'        => 'boolean',
458
					'default'     => false,
459
					'context'     => array( 'view', 'edit' ),
460
				),
461
				'product_categories' => array(
462
					'description' => __( "List of category ID's the coupon applies to.", 'woocommerce' ),
463
					'type'        => 'array',
464
					'context'     => array( 'view', 'edit' ),
465
				),
466
				'excluded_product_categories' => array(
467
					'description' => __( "List of category ID's the coupon does not apply to.", 'woocommerce' ),
468
					'type'        => 'array',
469
					'context'     => array( 'view', 'edit' ),
470
				),
471
				'exclude_sale_items' => array(
472
					'description' => __( 'Define if should not apply when have sale items.', 'woocommerce' ),
473
					'type'        => 'boolean',
474
					'default'     => false,
475
					'context'     => array( 'view', 'edit' ),
476
				),
477
				'minimum_amount' => array(
478
					'description' => __( 'Minimum order amount that needs to be in the cart before coupon applies.', 'woocommerce' ),
479
					'type'        => 'string',
480
					'context'     => array( 'view', 'edit' ),
481
				),
482
				'maximum_amount' => array(
483
					'description' => __( 'Maximum order amount allowed when using the coupon.', 'woocommerce' ),
484
					'type'        => 'string',
485
					'context'     => array( 'view', 'edit' ),
486
				),
487
				'email_restrictions' => array(
488
					'description' => __( 'List of email addresses that can use this coupon.', 'woocommerce' ),
489
					'type'        => 'array',
490
					'context'     => array( 'view', 'edit' ),
491
				),
492
				'used_by' => array(
493
					'description' => __( 'List of user IDs who have used the coupon.', 'woocommerce' ),
494
					'type'        => 'array',
495
					'context'     => array( 'view', 'edit' ),
496
					'readonly'    => true,
497
				),
498
			),
499
		);
500
		return $this->add_additional_fields_schema( $schema );
501
	}
502
503
	/**
504
	 * Get the query params for collections of attachments.
505
	 *
506
	 * @return array
507
	 */
508 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...
509
		$params = parent::get_collection_params();
510
		$params['code'] = array(
511
			'description'       => __( 'Limit result set to resources with a specific code.', 'woocommerce' ),
512
			'type'              => 'string',
513
			'sanitize_callback' => 'sanitize_text_field',
514
			'validate_callback' => 'rest_validate_request_arg',
515
		);
516
		return $params;
517
	}
518
}
519