Completed
Pull Request — master (#10013)
by Fredrik
48:07
created

WC_CLI_Coupon::update()   F

Complexity

Conditions 28
Paths > 20000

Size

Total Lines 114
Code Lines 64

Duplication

Lines 37
Ratio 32.46 %
Metric Value
dl 37
loc 114
rs 2
cc 28
eloc 64
nc 1048588
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 15 and the first side effect is on line 4.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	exit; // Exit if accessed directly
5
}
6
7
/**
8
 * Manage Coupons.
9
 *
10
 * @since    2.5.0
11
 * @package  WooCommerce/CLI
12
 * @category CLI
13
 * @author   WooThemes
14
 */
15
class WC_CLI_Coupon extends WC_CLI_Command {
16
17
	/**
18
	 * Create a coupon.
19
	 *
20
	 * ## OPTIONS
21
	 *
22
	 * [--<field>=<value>]
23
	 * : Associative args for the new coupon.
24
	 *
25
	 * [--porcelain]
26
	 * : Outputs just the new coupon id.
27
	 *
28
	 * ## AVAILABLE FIELDS
29
	 *
30
	 * These fields are available for create command:
31
	 *
32
	 * * code
33
	 * * type
34
	 * * amount
35
	 * * description
36
	 * * expiry_date
37
	 * * individual_use
38
	 * * product_ids
39
	 * * exclude_product_ids
40
	 * * usage_limit
41
	 * * usage_limit_per_user
42
	 * * limit_usage_to_x_items
43
	 * * usage_count
44
	 * * enable_free_shipping
45
	 * * product_category_ids
46
	 * * exclude_product_category_ids
47
	 * * minimum_amount
48
	 * * maximum_amount
49
	 * * customer_emails
50
	 *
51
	 * ## EXAMPLES
52
	 *
53
	 *     wp wc coupon create --code=new-coupon --type=percent
54
	 *
55
	 */
56
	public function create( $__, $assoc_args ) {
57
		global $wpdb;
58
59
		try {
60
			$porcelain = isset( $assoc_args['porcelain'] );
61
			unset( $assoc_args['porcelain'] );
62
63
			$assoc_args = apply_filters( 'woocommerce_cli_create_coupon_data', $assoc_args );
64
65
			// Check if coupon code is specified.
66 View Code Duplication
			if ( ! isset( $assoc_args['code'] ) ) {
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...
67
				throw new WC_CLI_Exception( 'woocommerce_cli_missing_coupon_code', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'code' ) );
68
			}
69
70
			$coupon_code = apply_filters( 'woocommerce_coupon_code', $assoc_args['code'] );
71
72
			// Check for duplicate coupon codes.
73
			$coupon_found = $wpdb->get_var( $wpdb->prepare( "
74
				SELECT $wpdb->posts.ID
75
				FROM $wpdb->posts
76
				WHERE $wpdb->posts.post_type = 'shop_coupon'
77
				AND $wpdb->posts.post_status = 'publish'
78
				AND $wpdb->posts.post_title = '%s'
79
			 ", $coupon_code ) );
80
81
			if ( $coupon_found ) {
82
				throw new WC_CLI_Exception( 'woocommerce_cli_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ) );
83
			}
84
85
			$defaults = array(
86
				'type'                         => 'fixed_cart',
87
				'amount'                       => 0,
88
				'individual_use'               => false,
89
				'product_ids'                  => array(),
90
				'exclude_product_ids'          => array(),
91
				'usage_limit'                  => '',
92
				'usage_limit_per_user'         => '',
93
				'limit_usage_to_x_items'       => '',
94
				'usage_count'                  => '',
95
				'expiry_date'                  => '',
96
				'enable_free_shipping'         => false,
97
				'product_category_ids'         => array(),
98
				'exclude_product_category_ids' => array(),
99
				'exclude_sale_items'           => false,
100
				'minimum_amount'               => '',
101
				'maximum_amount'               => '',
102
				'customer_emails'              => array(),
103
				'description'                  => ''
104
			);
105
106
			$coupon_data = wp_parse_args( $assoc_args, $defaults );
107
108
			// Validate coupon types
109
			if ( ! in_array( wc_clean( $coupon_data['type'] ), array_keys( wc_get_coupon_types() ) ) ) {
110
				throw new WC_CLI_Exception( 'woocommerce_cli_invalid_coupon_type', sprintf( __( 'Invalid coupon type - the coupon type must be any of these: %s', 'woocommerce' ), implode( ', ', array_keys( wc_get_coupon_types() ) ) ) );
111
			}
112
113
			$new_coupon = array(
114
				'post_title'   => $coupon_code,
115
				'post_content' => '',
116
				'post_status'  => 'publish',
117
				'post_author'  => get_current_user_id(),
118
				'post_type'    => 'shop_coupon',
119
				'post_excerpt' => $coupon_data['description']
120
	 		);
121
122
			$id = wp_insert_post( $new_coupon, $wp_error = false );
123
124
			if ( is_wp_error( $id ) ) {
125
				throw new WC_CLI_Exception( 'woocommerce_cli_cannot_create_coupon', $id->get_error_message() );
126
			}
127
128
			// Set coupon meta
129
			update_post_meta( $id, 'discount_type', $coupon_data['type'] );
130
			update_post_meta( $id, 'coupon_amount', wc_format_decimal( $coupon_data['amount'] ) );
131
			update_post_meta( $id, 'individual_use', ( true === $coupon_data['individual_use'] ) ? 'yes' : 'no' );
132
			update_post_meta( $id, 'product_ids', implode( ',', array_filter( array_map( 'intval', $coupon_data['product_ids'] ) ) ) );
133
			update_post_meta( $id, 'exclude_product_ids', implode( ',', array_filter( array_map( 'intval', $coupon_data['exclude_product_ids'] ) ) ) );
134
			update_post_meta( $id, 'usage_limit', absint( $coupon_data['usage_limit'] ) );
135
			update_post_meta( $id, 'usage_limit_per_user', absint( $coupon_data['usage_limit_per_user'] ) );
136
			update_post_meta( $id, 'limit_usage_to_x_items', absint( $coupon_data['limit_usage_to_x_items'] ) );
137
			update_post_meta( $id, 'usage_count', absint( $coupon_data['usage_count'] ) );
138
			update_post_meta( $id, 'expiry_date', $this->get_coupon_expiry_date( wc_clean( $coupon_data['expiry_date'] ) ) );
139
			update_post_meta( $id, 'free_shipping', ( true === $coupon_data['enable_free_shipping'] ) ? 'yes' : 'no' );
140
			update_post_meta( $id, 'product_categories', array_filter( array_map( 'intval', $coupon_data['product_category_ids'] ) ) );
141
			update_post_meta( $id, 'exclude_product_categories', array_filter( array_map( 'intval', $coupon_data['exclude_product_category_ids'] ) ) );
142
			update_post_meta( $id, 'exclude_sale_items', ( true === $coupon_data['exclude_sale_items'] ) ? 'yes' : 'no' );
143
			update_post_meta( $id, 'minimum_amount', wc_format_decimal( $coupon_data['minimum_amount'] ) );
144
			update_post_meta( $id, 'maximum_amount', wc_format_decimal( $coupon_data['maximum_amount'] ) );
145
			update_post_meta( $id, 'customer_email', array_filter( array_map( 'sanitize_email', $coupon_data['customer_emails'] ) ) );
146
147
			do_action( 'woocommerce_cli_create_coupon', $id, $coupon_data );
148
149
			if ( $porcelain ) {
150
				WP_CLI::line( $id );
151
			} else {
152
				WP_CLI::success( "Created coupon $id." );
153
			}
154
		} catch ( WC_CLI_Exception $e ) {
155
			WP_CLI::error( $e->getMessage() );
156
		}
157
	}
158
159
	/**
160
	 * Delete one or more coupons.
161
	 *
162
	 * ## OPTIONS
163
	 *
164
	 * <id>...
165
	 * : The coupon ID to delete.
166
	 *
167
	 * ## EXAMPLES
168
	 *
169
	 *     wp wc coupon delete 123
170
	 *
171
	 *     wp wc coupon delete $(wp wc coupon list --format=ids)
172
	 *
173
	 */
174
	public function delete( $args, $assoc_args ) {
175
		$exit_code = 0;
176
		foreach ( $this->get_many_coupons_from_ids_or_codes( $args, true ) as $coupon ) {
177
			do_action( 'woocommerce_cli_delete_coupon', $coupon->id );
178
			$r = wp_delete_post( $coupon->id, true );
179
180
			if ( $r ) {
181
				WP_CLI::success( "Deleted coupon {$coupon->id}." );
182
			} else {
183
				$exit_code += 1;
184
				WP_CLI::warning( "Failed deleting coupon {$coupon->id}." );
185
			}
186
		}
187
		exit( $exit_code ? 1 : 0 );
188
	}
189
190
	/**
191
	 * Get a coupon.
192
	 *
193
	 * ## OPTIONS
194
	 *
195
	 * <coupon>
196
	 * : Coupon ID or code
197
	 *
198
	 * [--field=<field>]
199
	 * : Instead of returning the whole coupon fields, returns the value of a single fields.
200
	 *
201
	 * [--fields=<fields>]
202
	 * : Get a specific subset of the coupon's fields.
203
	 *
204
	 * [--format=<format>]
205
	 * : Accepted values: table, json, csv. Default: table.
206
	 *
207
	 * ## AVAILABLE FIELDS
208
	 *
209
	 * These fields are available for get command:
210
	 *
211
	 * * id
212
	 * * code
213
	 * * type
214
	 * * amount
215
	 * * description
216
	 * * expiry_date
217
	 * * individual_use
218
	 * * product_ids
219
	 * * exclude_product_ids
220
	 * * usage_limit
221
	 * * usage_limit_per_user
222
	 * * limit_usage_to_x_items
223
	 * * usage_count
224
	 * * enable_free_shipping
225
	 * * product_category_ids
226
	 * * exclude_product_category_ids
227
	 * * minimum_amount
228
	 * * maximum_amount
229
	 * * customer_emails
230
	 *
231
	 * ## EXAMPLES
232
	 *
233
	 *     wp wc coupon get 123 --field=discount_type
234
	 *
235
	 *     wp wc coupon get disc50 --format=json > disc50.json
236
	 *
237
	 * @since 2.5.0
238
	 */
239
	public function get( $args, $assoc_args ) {
240
		global $wpdb;
241
242
		try {
243
			$coupon = $this->get_coupon_from_id_or_code( $args[0] );
244 View Code Duplication
			if ( ! $coupon ) {
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...
245
				throw new WC_CLI_Exception( 'woocommerce_cli_invalid_coupon', sprintf( __( 'Invalid coupon ID or code: %s', 'woocommerce' ), $args[0] ) );
246
			}
247
248
			$coupon_post = get_post( $coupon->id );
249
			$coupon_data = array(
250
				'id'                           => $coupon->id,
251
				'code'                         => $coupon->code,
252
				'type'                         => $coupon->type,
253
				'created_at'                   => $this->format_datetime( $coupon_post->post_date_gmt ),
254
				'updated_at'                   => $this->format_datetime( $coupon_post->post_modified_gmt ),
255
				'amount'                       => wc_format_decimal( $coupon->coupon_amount, 2 ),
256
				'individual_use'               => $coupon->individual_use,
257
				'product_ids'                  => $coupon_post->product_ids,
258
				'exclude_product_ids'          => $coupon_post->exclude_product_ids,
259
				'usage_limit'                  => ( ! empty( $coupon->usage_limit ) ) ? $coupon->usage_limit : null,
260
				'usage_limit_per_user'         => ( ! empty( $coupon->usage_limit_per_user ) ) ? $coupon->usage_limit_per_user : null,
261
				'limit_usage_to_x_items'       => (int) $coupon->limit_usage_to_x_items,
262
				'usage_count'                  => (int) $coupon->usage_count,
263
				'expiry_date'                  => ( ! empty( $coupon->expiry_date ) ) ? $this->format_datetime( $coupon->expiry_date ) : null,
264
				'enable_free_shipping'         => $coupon->free_shipping,
265
				'product_category_ids'         => implode( ', ', $coupon->product_categories ),
266
				'exclude_product_category_ids' => implode( ', ', $coupon->exclude_product_categories ),
267
				'exclude_sale_items'           => $coupon->exclude_sale_items,
268
				'minimum_amount'               => wc_format_decimal( $coupon->minimum_amount, 2 ),
269
				'maximum_amount'               => wc_format_decimal( $coupon->maximum_amount, 2 ),
270
				'customer_emails'              => implode( ', ', $coupon->customer_email ),
271
				'description'                  => $coupon_post->post_excerpt,
272
			);
273
274
			$coupon_data = apply_filters( 'woocommerce_cli_get_coupon', $coupon_data );
275
276
			if ( empty( $assoc_args['fields'] ) ) {
277
				$assoc_args['fields'] = array_keys( $coupon_data );
278
			}
279
280
			$formatter = $this->get_formatter( $assoc_args );
281
			$formatter->display_item( $coupon_data );
282
		} catch ( WC_CLI_Exception $e ) {
283
			WP_CLI::error( $e->getMessage() );
284
		}
285
	}
286
287
	/**
288
	 * List coupons.
289
	 *
290
	 * ## OPTIONS
291
	 *
292
	 * [--<field>=<value>]
293
	 * : Filter coupon based on coupon property.
294
	 *
295
	 * [--field=<field>]
296
	 * : Prints the value of a single field for each coupon.
297
	 *
298
	 * [--fields=<fields>]
299
	 * : Limit the output to specific coupon fields.
300
	 *
301
	 * [--format=<format>]
302
	 * : Acceptec values: table, csv, json, count, ids. Default: table.
303
	 *
304
	 * ## AVAILABLE FIELDS
305
	 *
306
	 * These fields will be displayed by default for each coupon:
307
	 *
308
	 * * id
309
	 * * code
310
	 * * type
311
	 * * amount
312
	 * * description
313
	 * * expiry_date
314
	 *
315
	 * These fields are optionally available:
316
	 *
317
	 * * individual_use
318
	 * * product_ids
319
	 * * exclude_product_ids
320
	 * * usage_limit
321
	 * * usage_limit_per_user
322
	 * * limit_usage_to_x_items
323
	 * * usage_count
324
	 * * free_shipping
325
	 * * product_category_ids
326
	 * * exclude_product_category_ids
327
	 * * exclude_sale_items
328
	 * * minimum_amount
329
	 * * maximum_amount
330
	 * * customer_emails
331
	 *
332
	 * Fields for filtering query result also available:
333
	 *
334
	 * * q              Filter coupons with search query.
335
	 * * in             Specify coupon IDs to retrieve.
336
	 * * not_in         Specify coupon IDs NOT to retrieve.
337
	 * * created_at_min Filter coupons created after this date.
338
	 * * created_at_max Filter coupons created before this date.
339
	 * * updated_at_min Filter coupons updated after this date.
340
	 * * updated_at_max Filter coupons updated before this date.
341
	 * * page           Page number.
342
	 * * offset         Number of coupon to displace or pass over.
343
	 * * order          Accepted values: ASC and DESC. Default: DESC.
344
	 * * orderby        Sort retrieved coupons by parameter. One or more options can be passed.
345
	 *
346
	 * ## EXAMPLES
347
	 *
348
	 *     wp wc coupon list
349
	 *
350
	 *     wp wc coupon list --field=id
351
	 *
352
	 *     wp wc coupon list --fields=id,code,type --format=json
353
	 *
354
	 * @since      2.5.0
355
	 * @subcommand list
356
	 */
357 View Code Duplication
	public function list_( $__, $assoc_args ) {
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...
358
		$query_args = $this->merge_wp_query_args( $this->get_list_query_args(), $assoc_args );
359
		$formatter  = $this->get_formatter( $assoc_args );
360
361
		if ( 'ids' === $formatter->format ) {
362
			$query_args['fields'] = 'ids';
363
			$query = new WP_Query( $query_args );
364
			echo implode( ' ', $query->posts );
365
		} else {
366
			$query = new WP_Query( $query_args );
367
			$items = $this->format_posts_to_items( $query->posts );
368
			$formatter->display_items( $items );
369
		}
370
	}
371
372
	/**
373
	 * Get coupon types.
374
	 *
375
	 * ## EXAMPLES
376
	 *
377
	 *     wp wc coupon types
378
	 *
379
	 * @since 2.5.0
380
	 */
381
	public function types( $__, $___ ) {
382
		$coupon_types = wc_get_coupon_types();
383
		foreach ( $coupon_types as $type => $label ) {
384
			WP_CLI::line( sprintf( '%s: %s', $label, $type ) );
385
		}
386
	}
387
388
	/**
389
	 * Update one or more coupons.
390
	 *
391
	 * ## OPTIONS
392
	 *
393
	 * <coupon>
394
	 * : The ID or code of the coupon to update.
395
	 *
396
	 * [--<field>=<value>]
397
	 * : One or more fields to update.
398
	 *
399
	 * ## AVAILABLE FIELDS
400
	 *
401
	 * These fields are available for update command:
402
	 *
403
	 * * code
404
	 * * type
405
	 * * amount
406
	 * * description
407
	 * * expiry_date
408
	 * * individual_use
409
	 * * product_ids
410
	 * * exclude_product_ids
411
	 * * usage_limit
412
	 * * usage_limit_per_user
413
	 * * limit_usage_to_x_items
414
	 * * usage_count
415
	 * * enable_free_shipping
416
	 * * product_category_ids
417
	 * * exclude_product_categories
418
	 * * exclude_product_category_ids
419
	 * * minimum_amount
420
	 * * maximum_amount
421
	 * * customer_emails
422
	 *
423
	 * ## EXAMPLES
424
	 *
425
	 *     wp wc coupon update 123 --amount=5
426
	 *
427
	 *     wp wc coupon update coupon-code --code=new-coupon-code
428
	 *
429
	 * @since 2.5.0
430
	 */
431
	public function update( $args, $assoc_args ) {
432
		try {
433
			$coupon = $this->get_coupon_from_id_or_code( $args[0] );
434 View Code Duplication
			if ( ! $coupon ) {
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...
435
				throw new WC_CLI_Exception( 'woocommerce_cli_invalid_coupon', sprintf( __( 'Invalid coupon ID or code: %s', 'woocommerce' ), $args[0] ) );
436
			}
437
438
			$id          = $coupon->id;
439
			$coupon_code = $coupon->code;
440
			$data        = apply_filters( 'woocommerce_cli_update_coupon_data', $assoc_args, $id );
441
			if ( isset( $data['code'] ) ) {
442
				global $wpdb;
443
444
				$coupon_code = apply_filters( 'woocommerce_coupon_code', $data['code'] );
445
446
				// Check for duplicate coupon codes
447
				$coupon_found = $wpdb->get_var( $wpdb->prepare( "
448
					SELECT $wpdb->posts.ID
449
					FROM $wpdb->posts
450
					WHERE $wpdb->posts.post_type = 'shop_coupon'
451
					AND $wpdb->posts.post_status = 'publish'
452
					AND $wpdb->posts.post_title = '%s'
453
					AND $wpdb->posts.ID != %s
454
				 ", $coupon_code, $id ) );
455
456
				if ( $coupon_found ) {
457
					throw new WC_CLI_Exception( 'woocommerce_cli_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ) );
458
				}
459
			}
460
461
			$id = wp_update_post( array( 'ID' => intval( $id ), 'post_title' => $coupon_code, 'post_excerpt' => isset( $data['description'] ) ? $data['description'] : '' ) );
462
			if ( 0 === $id ) {
463
				throw new WC_CLI_Exception( 'woocommerce_cli_cannot_update_coupon', __( 'Failed to update coupon', 'woocommerce' ) );
464
			}
465
466 View Code Duplication
			if ( isset( $data['type'] ) ) {
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...
467
				// Validate coupon types.
468
				if ( ! in_array( wc_clean( $data['type'] ), array_keys( wc_get_coupon_types() ) ) ) {
469
					throw new WC_CLI_Exception( 'woocommerce_cli_invalid_coupon_type', sprintf( __( 'Invalid coupon type - the coupon type must be any of these: %s', 'woocommerce' ), implode( ', ', array_keys( wc_get_coupon_types() ) ) ) );
470
				}
471
				update_post_meta( $id, 'discount_type', $data['type'] );
472
			}
473
474
			if ( isset( $data['amount'] ) ) {
475
				update_post_meta( $id, 'coupon_amount', wc_format_decimal( $data['amount'] ) );
476
			}
477
478 View Code Duplication
			if ( isset( $data['individual_use'] ) ) {
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...
479
				update_post_meta( $id, 'individual_use', ( true === $data['individual_use'] ) ? 'yes' : 'no' );
480
			}
481
482 View Code Duplication
			if ( isset( $data['product_ids'] ) ) {
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...
483
				update_post_meta( $id, 'product_ids', implode( ',', array_filter( array_map( 'intval', $data['product_ids'] ) ) ) );
484
			}
485
486 View Code Duplication
			if ( isset( $data['exclude_product_ids'] ) ) {
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...
487
				update_post_meta( $id, 'exclude_product_ids', implode( ',', array_filter( array_map( 'intval', $data['exclude_product_ids'] ) ) ) );
488
			}
489
490
			if ( isset( $data['usage_limit'] ) ) {
491
				update_post_meta( $id, 'usage_limit', absint( $data['usage_limit'] ) );
492
			}
493
494
			if ( isset( $data['usage_limit_per_user'] ) ) {
495
				update_post_meta( $id, 'usage_limit_per_user', absint( $data['usage_limit_per_user'] ) );
496
			}
497
498
			if ( isset( $data['limit_usage_to_x_items'] ) ) {
499
				update_post_meta( $id, 'limit_usage_to_x_items', absint( $data['limit_usage_to_x_items'] ) );
500
			}
501
502
			if ( isset( $data['usage_count'] ) ) {
503
				update_post_meta( $id, 'usage_count', absint( $data['usage_count'] ) );
504
			}
505
506 View Code Duplication
			if ( isset( $data['expiry_date'] ) ) {
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...
507
				update_post_meta( $id, 'expiry_date', $this->get_coupon_expiry_date( wc_clean( $data['expiry_date'] ) ) );
508
			}
509
510 View Code Duplication
			if ( isset( $data['enable_free_shipping'] ) ) {
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...
511
				update_post_meta( $id, 'free_shipping', ( true === $data['enable_free_shipping'] ) ? 'yes' : 'no' );
512
			}
513
514 View Code Duplication
			if ( isset( $data['product_category_ids'] ) ) {
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...
515
				update_post_meta( $id, 'product_categories', array_filter( array_map( 'intval', $data['product_category_ids'] ) ) );
516
			}
517
518 View Code Duplication
			if ( isset( $data['exclude_product_category_ids'] ) ) {
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...
519
				update_post_meta( $id, 'exclude_product_categories', array_filter( array_map( 'intval', $data['exclude_product_category_ids'] ) ) );
520
			}
521
522 View Code Duplication
			if ( isset( $data['exclude_sale_items'] ) ) {
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...
523
				update_post_meta( $id, 'exclude_sale_items', ( true === $data['exclude_sale_items'] ) ? 'yes' : 'no' );
524
			}
525
526
			if ( isset( $data['minimum_amount'] ) ) {
527
				update_post_meta( $id, 'minimum_amount', wc_format_decimal( $data['minimum_amount'] ) );
528
			}
529
530
			if ( isset( $data['maximum_amount'] ) ) {
531
				update_post_meta( $id, 'maximum_amount', wc_format_decimal( $data['maximum_amount'] ) );
532
			}
533
534 View Code Duplication
			if ( isset( $data['customer_emails'] ) ) {
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...
535
				update_post_meta( $id, 'customer_email', array_filter( array_map( 'sanitize_email', $data['customer_emails'] ) ) );
536
			}
537
538
			do_action( 'woocommerce_cli_update_coupon', $id, $data );
539
540
			WP_CLI::success( "Updated coupon $id." );
541
		} catch ( WC_CLI_Exception $e ) {
542
			WP_CLI::error( $e->getMessage() );
543
		}
544
	}
545
546
	/**
547
	 * Get query args for list subcommand.
548
	 *
549
	 * @since  2.5.0
550
	 * @return array
551
	 */
552
	protected function get_list_query_args() {
553
		return array(
554
			'post_type'      => 'shop_coupon',
555
			'post_status'    => 'publish',
556
			'posts_per_page' => -1,
557
			'order'          => 'DESC',
558
		);
559
	}
560
561
	/**
562
	 * Get default format fields that will be used in `list` and `get` subcommands.
563
	 *
564
	 * @since  2.5.0
565
	 * @return string
566
	 */
567
	protected function get_default_format_fields() {
568
		return 'id,code,type,amount,description,expiry_date';
569
	}
570
571
	/**
572
	 * Format posts from WP_Query result to items in which each item contain
573
	 * common properties of item, for instance `post_title` will be `code`.
574
	 *
575
	 * @since  2.5.0
576
	 * @param  array $posts Array of post
577
	 * @return array Items
578
	 */
579
	protected function format_posts_to_items( $posts ) {
580
		$items = array();
581
		foreach ( $posts as $post ) {
582
			$items[] = array(
583
				'id'                           => $post->ID,
584
				'code'                         => $post->post_title,
585
				'type'                         => $post->discount_type,
586
				'created_at'                   => $this->format_datetime( $post->post_date_gmt ),
587
				'updated_at'                   => $this->format_datetime( $post->post_modified_gmt ),
588
				'amount'                       => wc_format_decimal( $post->coupon_amount, 2 ),
589
				'individual_use'               => $post->individual_use,
590
				'product_ids'                  => $post->product_ids,
591
				'exclude_product_ids'          => $post->exclude_product_ids,
592
				'usage_limit'                  => ( ! empty( $post->usage_limit ) ) ? $post->usage_limit : null,
593
				'usage_limit_per_user'         => ( ! empty( $post->usage_limit_per_user ) ) ? $post->usage_limit_per_user : null,
594
				'limit_usage_to_x_items'       => (int) $post->limit_usage_to_x_items,
595
				'usage_count'                  => (int) $post->usage_count,
596
				'expiry_date'                  => ( ! empty( $post->expiry_date ) ) ? $this->format_datetime( $post->expiry_date ) : null,
597
				'free_shipping'                => $post->free_shipping,
598
				'product_category_ids'         => implode( ', ', is_array( $post->product_categories ) ? $post->product_categories : array() ),
599
				'exclude_product_category_ids' => implode( ', ', is_array( $post->exclude_product_categories ) ? $post->exclude_product_categories : array() ),
600
				'exclude_sale_items'           => $post->exclude_sale_items,
601
				'minimum_amount'               => wc_format_decimal( $post->minimum_amount, 2 ),
602
				'maximum_amount'               => wc_format_decimal( $post->maximum_amount, 2 ),
603
				'customer_emails'              => implode( ', ', is_array( $post->customer_email ) ? $post->customer_email : array() ),
604
				'description'                  => $post->post_excerpt,
605
			);
606
		}
607
608
		return $items;
609
	}
610
611
	/**
612
	 * Get expiry_date format before saved into DB.
613
	 *
614
	 * @since  2.5.0
615
	 * @param  string $expiry_date
616
	 * @return string
617
	 */
618
	protected function get_coupon_expiry_date( $expiry_date ) {
619
		if ( '' !== $expiry_date ) {
620
			return date( 'Y-m-d', strtotime( $expiry_date ) );
621
		}
622
623
		return '';
624
	}
625
626
	/**
627
	 * Get coupon from coupon's ID or code.
628
	 *
629
	 * @since  2.5.0
630
	 * @param  int|string $coupon_id_or_code Coupon's ID or code
631
	 * @param  bool       $display_warning   Display warning if ID or code is invalid. Default false.
632
	 * @return WC_Coupon
633
	 */
634
	protected function get_coupon_from_id_or_code( $coupon_id_or_code, $display_warning = false ) {
635
		global $wpdb;
636
637
		$code = $wpdb->get_var( $wpdb->prepare( "SELECT post_title FROM $wpdb->posts WHERE (id = %s OR post_title = %s) AND post_type = 'shop_coupon' AND post_status = 'publish' LIMIT 1", $coupon_id_or_code, $coupon_id_or_code ) );
638
		if ( ! $code ) {
639
			if ( $display_warning ) {
640
				WP_CLI::warning( "Invalid coupon ID or code $coupon_id_or_code" );
641
			}
642
			return null;
643
		}
644
645
		return new WC_Coupon( $code );
646
	}
647
648
	/**
649
	 * Get coupon from coupon's ID or code.
650
	 *
651
	 * @since  2.5.0
652
	 * @param  array     $args            Coupon's IDs or codes
653
	 * @param  bool      $display_warning Display warning if ID or code is invalid. Default false.
654
	 * @return WC_Coupon
655
	 */
656
	protected function get_many_coupons_from_ids_or_codes( $args, $display_warning = false ) {
657
		$coupons = array();
658
659
		foreach ( $args as $arg ) {
660
			$code = $this->get_coupon_from_id_or_code( $arg, $display_warning );
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $code is correct as $this->get_coupon_from_i...$arg, $display_warning) (which targets WC_CLI_Coupon::get_coupon_from_id_or_code()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
661
			if ( $code ) {
662
				$coupons[] = $code;
663
			}
664
		}
665
666
		return $coupons;
667
	}
668
}
669