Completed
Pull Request — master (#11785)
by Mike
13:06
created

WC_REST_Coupons_Controller::create_item()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 31
Code Lines 16

Duplication

Lines 31
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 16
nc 3
nop 1
dl 31
loc 31
rs 8.8571
c 1
b 0
f 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
149
		// Format decimal values.
150
		foreach ( $format_decimal as $key ) {
151
			$data[ $key ] = wc_format_decimal( $data[ $key ], 2 );
152
		}
153
154
		// Format date values.
155 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...
156
			$data[ $key ] = $data[ $key ] ? wc_rest_prepare_date_response( get_gmt_from_date( date( 'Y-m-d H:i:s', $data[ $key ] ) ) ) : false;
157
		}
158
159
		$context  = ! empty( $request['context'] ) ? $request['context'] : 'view';
160
		$data     = $this->add_additional_fields_to_object( $data, $request );
161
		$data     = $this->filter_response_by_context( $data, $context );
162
		$response = rest_ensure_response( $data );
163
		$response->add_links( $this->prepare_links( $post ) );
164
165
		/**
166
		 * Filter the data for a response.
167
		 *
168
		 * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being
169
		 * prepared for the response.
170
		 *
171
		 * @param WP_REST_Response   $response   The response object.
172
		 * @param WP_Post            $post       Post object.
173
		 * @param WP_REST_Request    $request    Request object.
174
		 */
175
		return apply_filters( "woocommerce_rest_prepare_{$this->post_type}", $response, $post, $request );
176
	}
177
178
	/**
179
	 * Only reutrn writeable props from schema.
180
	 * @param  array $schema
181
	 * @return bool
182
	 */
183
	protected function filter_writable_props( $schema ) {
184
		return empty( $schema['readonly'] );
185
	}
186
187
	/**
188
	 * Prepare a single coupon for create or update.
189
	 *
190
	 * @param WP_REST_Request $request Request object.
191
	 * @return WP_Error|stdClass $data Post object.
192
	 */
193
	protected function prepare_item_for_database( $request ) {
194
		global $wpdb;
195
		
196
		$id        = isset( $request['id'] ) ? absint( $request['id'] ) : 0;
197
		$coupon    = new WC_Coupon( $id );
198
		$schema    = $this->get_item_schema();
199
		$data_keys = array_keys( array_filter( $schema['properties'], array( $this, 'filter_writable_props' ) ) );
200
201
		// Validate required POST fields.
202
		if ( 'POST' === $request->get_method() && 0 === $coupon->get_id() ) {
203
			if ( empty( $request['code'] ) ) {
204
				return new WP_Error( 'woocommerce_rest_empty_coupon_code', sprintf( __( 'The coupon code cannot be empty.', 'woocommerce' ), 'code' ), array( 'status' => 400 ) );
205
			}
206
		}
207
208
		// Handle all writable props
209
		foreach ( $data_keys as $key ) {
210
			$value = $request[ $key ];
211
212
			if ( ! is_null( $value ) ) {
213
				switch ( $key ) {
214
					case 'code' :
215
						$coupon_code = apply_filters( 'woocommerce_coupon_code', $value );
216
						$id          = $coupon->get_id() ? $coupon->get_id() : 0;
217
218
						// Check for duplicate coupon codes.
219
						$coupon_found = $wpdb->get_var( $wpdb->prepare( "
220
							SELECT $wpdb->posts.ID
221
							FROM $wpdb->posts
222
							WHERE $wpdb->posts.post_type = 'shop_coupon'
223
							AND $wpdb->posts.post_status = 'publish'
224
							AND $wpdb->posts.post_title = %s
225
							AND $wpdb->posts.ID != %s
226
						 ", $coupon_code, $id ) );
227
228
						if ( $coupon_found ) {
229
							return new WP_Error( 'woocommerce_rest_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ), array( 'status' => 400 ) );
230
						}
231
232
						$coupon->set_code( $coupon_code );
233
						break;
234 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...
235
						if ( is_array( $value ) ) {
236
							foreach ( $value as $meta ) {
237
								$coupon->update_meta_data( $meta['key'], $meta['value'], $meta['id'] );
238
							}
239
						}
240
						break;
241
					case 'description' :
242
						$coupon->set_description( wp_filter_post_kses( $value ) );
243
						break;
244
					default :
245
						if ( is_callable( array( $coupon, "set_{$key}" ) ) ) {
246
							$coupon->{"set_{$key}"}( $value );
247
						}
248
						break;
249
				}
250
			}
251
		}
252
253
		/**
254
		 * Filter the query_vars used in `get_items` for the constructed query.
255
		 *
256
		 * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being
257
		 * prepared for insertion.
258
		 *
259
		 * @param WC_Coupon       $coupon        The coupon object.
260
		 * @param WP_REST_Request $request       Request object.
261
		 */
262
		return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}", $coupon, $request );
263
	}
264
265
	/**
266
	 * Create a single item.
267
	 *
268
	 * @param WP_REST_Request $request Full details about the request.
269
	 * @return WP_Error|WP_REST_Response
270
	 */
271 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...
272
		if ( ! empty( $request['id'] ) ) {
273
			return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) );
274
		}
275
276
		$coupon_id = $this->save_coupon( $request );
277
		if ( is_wp_error( $coupon_id ) ) {
278
			return $coupon_id;
279
		}
280
281
		$post = get_post( $coupon_id );
282
		$this->update_additional_fields_for_object( $post, $request );
283
284
		$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...
285
286
		/**
287
		 * Fires after a single item is created or updated via the REST API.
288
		 *
289
		 * @param object          $post      Inserted object (not a WP_Post object).
290
		 * @param WP_REST_Request $request   Request object.
291
		 * @param boolean         $creating  True when creating item, false when updating.
292
		 */
293
		do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, true );
294
		$request->set_param( 'context', 'edit' );
295
		$response = $this->prepare_item_for_response( $post, $request );
296
		$response = rest_ensure_response( $response );
297
		$response->set_status( 201 );
298
		$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post->ID ) ) );
299
300
		return $response;
301
	}
302
303
	/**
304
	 * Update a single coupon.
305
	 *
306
	 * @param WP_REST_Request $request Full details about the request.
307
	 * @return WP_Error|WP_REST_Response
308
	 */
309 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...
310
		try {
311
			$post_id = (int) $request['id'];
312
313
			if ( empty( $post_id ) || $this->post_type !== get_post_type( $post_id ) ) {
314
				return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) );
315
			}
316
317
			$coupon_id = $this->save_coupon( $request );
318
			if ( is_wp_error( $coupon_id ) ) {
319
				return $coupon_id;
320
			}
321
322
			$post = get_post( $coupon_id );
323
			$this->update_additional_fields_for_object( $post, $request );
324
325
			/**
326
			 * Fires after a single item is created or updated via the REST API.
327
			 *
328
			 * @param object          $post      Inserted object (not a WP_Post object).
329
			 * @param WP_REST_Request $request   Request object.
330
			 * @param boolean         $creating  True when creating item, false when updating.
331
			 */
332
			do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, false );
333
			$request->set_param( 'context', 'edit' );
334
			$response = $this->prepare_item_for_response( $post, $request );
335
			return rest_ensure_response( $response );
336
337
		} catch ( Exception $e ) {
338
			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...
339
		}
340
	}
341
342
	/**
343
	 * Saves a coupon to the database.
344
	 */
345
	public function save_coupon( $request ) {
346
		try {
347
			$coupon = $this->prepare_item_for_database( $request );
348
			$coupon->save();
349
			return $coupon->get_id();
350
		} catch ( WC_Data_Exception $e ) {
351
			return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
352
		} catch ( WC_REST_Exception $e ) {
353
			return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
354
		}
355
	}
356
357
	/**
358
	 * Get the Coupon's schema, conforming to JSON Schema.
359
	 *
360
	 * @return array
361
	 */
362
	public function get_item_schema() {
363
		$schema = array(
364
			'$schema'    => 'http://json-schema.org/draft-04/schema#',
365
			'title'      => $this->post_type,
366
			'type'       => 'object',
367
			'properties' => array(
368
				'id' => array(
369
					'description' => __( 'Unique identifier for the object.', 'woocommerce' ),
370
					'type'        => 'integer',
371
					'context'     => array( 'view', 'edit' ),
372
					'readonly'    => true,
373
				),
374
				'code' => array(
375
					'description' => __( 'Coupon code.', 'woocommerce' ),
376
					'type'        => 'string',
377
					'context'     => array( 'view', 'edit' ),
378
				),
379
				'date_created' => array(
380
					'description' => __( "The date the coupon was created, in the site's timezone.", 'woocommerce' ),
381
					'type'        => 'date-time',
382
					'context'     => array( 'view', 'edit' ),
383
					'readonly'    => true,
384
				),
385
				'date_modified' => array(
386
					'description' => __( "The date the coupon was last modified, in the site's timezone.", 'woocommerce' ),
387
					'type'        => 'date-time',
388
					'context'     => array( 'view', 'edit' ),
389
					'readonly'    => true,
390
				),
391
				'description' => array(
392
					'description' => __( 'Coupon description.', 'woocommerce' ),
393
					'type'        => 'string',
394
					'context'     => array( 'view', 'edit' ),
395
				),
396
				'discount_type' => array(
397
					'description' => __( 'Determines the type of discount that will be applied.', 'woocommerce' ),
398
					'type'        => 'string',
399
					'default'     => 'fixed_cart',
400
					'enum'        => array_keys( wc_get_coupon_types() ),
401
					'context'     => array( 'view', 'edit' ),
402
				),
403
				'amount' => array(
404
					'description' => __( 'The amount of discount.', 'woocommerce' ),
405
					'type'        => 'string',
406
					'context'     => array( 'view', 'edit' ),
407
				),
408
				'date_expires' => array(
409
					'description' => __( 'UTC DateTime when the coupon expires.', 'woocommerce' ),
410
					'type'        => 'string',
411
					'context'     => array( 'view', 'edit' ),
412
				),
413
				'usage_count' => array(
414
					'description' => __( 'Number of times the coupon has been used already.', 'woocommerce' ),
415
					'type'        => 'integer',
416
					'context'     => array( 'view', 'edit' ),
417
					'readonly'    => true,
418
				),
419
				'individual_use' => array(
420
					'description' => __( 'Whether coupon can only be used individually.', 'woocommerce' ),
421
					'type'        => 'boolean',
422
					'default'     => false,
423
					'context'     => array( 'view', 'edit' ),
424
				),
425
				'product_ids' => array(
426
					'description' => __( "List of product ID's the coupon can be used on.", 'woocommerce' ),
427
					'type'        => 'array',
428
					'context'     => array( 'view', 'edit' ),
429
				),
430
				'exclude_product_ids' => array(
431
					'description' => __( "List of product ID's the coupon cannot be used on.", 'woocommerce' ),
432
					'type'        => 'array',
433
					'context'     => array( 'view', 'edit' ),
434
				),
435
				'usage_limit' => array(
436
					'description' => __( 'How many times the coupon can be used.', 'woocommerce' ),
437
					'type'        => 'integer',
438
					'context'     => array( 'view', 'edit' ),
439
				),
440
				'usage_limit_per_user' => array(
441
					'description' => __( 'How many times the coupon can be used per customer.', 'woocommerce' ),
442
					'type'        => 'integer',
443
					'context'     => array( 'view', 'edit' ),
444
				),
445
				'limit_usage_to_x_items' => array(
446
					'description' => __( 'Max number of items in the cart the coupon can be applied to.', 'woocommerce' ),
447
					'type'        => 'integer',
448
					'context'     => array( 'view', 'edit' ),
449
				),
450
				'free_shipping' => array(
451
					'description' => __( 'Define if can be applied for free shipping.', 'woocommerce' ),
452
					'type'        => 'boolean',
453
					'default'     => false,
454
					'context'     => array( 'view', 'edit' ),
455
				),
456
				'product_categories' => array(
457
					'description' => __( "List of category ID's the coupon applies to.", 'woocommerce' ),
458
					'type'        => 'array',
459
					'context'     => array( 'view', 'edit' ),
460
				),
461
				'excluded_product_categories' => array(
462
					'description' => __( "List of category ID's the coupon does not apply to.", 'woocommerce' ),
463
					'type'        => 'array',
464
					'context'     => array( 'view', 'edit' ),
465
				),
466
				'exclude_sale_items' => array(
467
					'description' => __( 'Define if should not apply when have sale items.', 'woocommerce' ),
468
					'type'        => 'boolean',
469
					'default'     => false,
470
					'context'     => array( 'view', 'edit' ),
471
				),
472
				'minimum_amount' => array(
473
					'description' => __( 'Minimum order amount that needs to be in the cart before coupon applies.', 'woocommerce' ),
474
					'type'        => 'string',
475
					'context'     => array( 'view', 'edit' ),
476
				),
477
				'maximum_amount' => array(
478
					'description' => __( 'Maximum order amount allowed when using the coupon.', 'woocommerce' ),
479
					'type'        => 'string',
480
					'context'     => array( 'view', 'edit' ),
481
				),
482
				'email_restrictions' => array(
483
					'description' => __( 'List of email addresses that can use this coupon.', 'woocommerce' ),
484
					'type'        => 'array',
485
					'context'     => array( 'view', 'edit' ),
486
				),
487
				'used_by' => array(
488
					'description' => __( 'List of user IDs who have used the coupon.', 'woocommerce' ),
489
					'type'        => 'array',
490
					'context'     => array( 'view', 'edit' ),
491
					'readonly'    => true,
492
				),
493
			),
494
		);
495
		return $this->add_additional_fields_schema( $schema );
496
	}
497
498
	/**
499
	 * Get the query params for collections of attachments.
500
	 *
501
	 * @return array
502
	 */
503 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...
504
		$params = parent::get_collection_params();
505
		$params['code'] = array(
506
			'description'       => __( 'Limit result set to resources with a specific code.', 'woocommerce' ),
507
			'type'              => 'string',
508
			'sanitize_callback' => 'sanitize_text_field',
509
			'validate_callback' => 'rest_validate_request_arg',
510
		);
511
		return $params;
512
	}
513
}
514