Completed
Push — master ( 15aa29...17da96 )
by Claudio
18:39 queued 11s
created

admin/meta-boxes/class-wc-meta-box-coupon-data.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Coupon Data
4
 *
5
 * Display the coupon data meta box.
6
 *
7
 * @author      WooThemes
8
 * @category    Admin
9
 * @package     WooCommerce/Admin/Meta Boxes
10
 * @version     2.1.0
11
 */
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit; // Exit if accessed directly
15
}
16
17
/**
18
 * WC_Meta_Box_Coupon_Data Class.
19
 */
20
class WC_Meta_Box_Coupon_Data {
21
22
	/**
23
	 * Output the metabox.
24
	 *
25
	 * @param WP_Post $post
26
	 */
27
	public static function output( $post ) {
28
		wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );
29
30
		$coupon_id = absint( $post->ID );
31
		$coupon    = new WC_Coupon( $coupon_id );
32
33
		?>
34
35
		<style type="text/css">
36
			#edit-slug-box, #minor-publishing-actions { display:none }
37
		</style>
38
		<div id="coupon_options" class="panel-wrap coupon_data">
39
40
			<div class="wc-tabs-back"></div>
41
42
			<ul class="coupon_data_tabs wc-tabs" style="display:none;">
43
				<?php
44
				$coupon_data_tabs = apply_filters(
45
					'woocommerce_coupon_data_tabs', array(
46
						'general'           => array(
47
							'label'  => __( 'General', 'woocommerce' ),
48
							'target' => 'general_coupon_data',
49
							'class'  => 'general_coupon_data',
50
						),
51
						'usage_restriction' => array(
52
							'label'  => __( 'Usage restriction', 'woocommerce' ),
53
							'target' => 'usage_restriction_coupon_data',
54
							'class'  => '',
55
						),
56
						'usage_limit'       => array(
57
							'label'  => __( 'Usage limits', 'woocommerce' ),
58
							'target' => 'usage_limit_coupon_data',
59
							'class'  => '',
60
						),
61
					)
62
				);
63
64
				foreach ( $coupon_data_tabs as $key => $tab ) :
65
					?>
66
					<li class="<?php echo $key; ?>_options <?php echo $key; ?>_tab <?php echo implode( ' ', (array) $tab['class'] ); ?>">
67
						<a href="#<?php echo $tab['target']; ?>">
68
							<span><?php echo esc_html( $tab['label'] ); ?></span>
69
						</a>
70
					</li>
71
				<?php endforeach; ?>
72
			</ul>
73
			<div id="general_coupon_data" class="panel woocommerce_options_panel">
74
				<?php
75
76
				// Type.
77
				woocommerce_wp_select(
78
					array(
79
						'id'      => 'discount_type',
80
						'label'   => __( 'Discount type', 'woocommerce' ),
81
						'options' => wc_get_coupon_types(),
82
						'value'   => $coupon->get_discount_type( 'edit' ),
83
					)
84
				);
85
86
				// Amount.
87
				woocommerce_wp_text_input(
88
					array(
89
						'id'          => 'coupon_amount',
90
						'label'       => __( 'Coupon amount', 'woocommerce' ),
91
						'placeholder' => wc_format_localized_price( 0 ),
92
						'description' => __( 'Value of the coupon.', 'woocommerce' ),
93
						'data_type'   => 'percent' === $coupon->get_discount_type( 'edit' ) ? 'decimal' : 'price',
94
						'desc_tip'    => true,
95
						'value'       => $coupon->get_amount( 'edit' ),
96
					)
97
				);
98
99
				// Free Shipping.
100
				if ( wc_shipping_enabled() ) {
101
					woocommerce_wp_checkbox(
102
						array(
103
							'id'          => 'free_shipping',
104
							'label'       => __( 'Allow free shipping', 'woocommerce' ),
105
							'description' => sprintf( __( 'Check this box if the coupon grants free shipping. A <a href="%s" target="_blank">free shipping method</a> must be enabled in your shipping zone and be set to require "a valid free shipping coupon" (see the "Free Shipping Requires" setting).', 'woocommerce' ), 'https://docs.woocommerce.com/document/free-shipping/' ),
106
							'value'       => wc_bool_to_string( $coupon->get_free_shipping( 'edit' ) ),
107
						)
108
					);
109
				}
110
111
				// Expiry date.
112
				$expiry_date = $coupon->get_date_expires( 'edit' ) ? $coupon->get_date_expires( 'edit' )->date( 'Y-m-d' ) : '';
113
				woocommerce_wp_text_input(
114
					array(
115
						'id'                => 'expiry_date',
116
						'value'             => esc_attr( $expiry_date ),
117
						'label'             => __( 'Coupon expiry date', 'woocommerce' ),
118
						'placeholder'       => 'YYYY-MM-DD',
119
						'description'       => '',
120
						'class'             => 'date-picker',
121
						'custom_attributes' => array(
122
							'pattern' => apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ),
123
						),
124
					)
125
				);
126
127
				do_action( 'woocommerce_coupon_options', $coupon->get_id(), $coupon );
128
129
				?>
130
			</div>
131
			<div id="usage_restriction_coupon_data" class="panel woocommerce_options_panel">
132
				<?php
133
134
				echo '<div class="options_group">';
135
136
				// minimum spend.
137
				woocommerce_wp_text_input(
138
					array(
139
						'id'          => 'minimum_amount',
140
						'label'       => __( 'Minimum spend', 'woocommerce' ),
141
						'placeholder' => __( 'No minimum', 'woocommerce' ),
142
						'description' => __( 'This field allows you to set the minimum spend (subtotal) allowed to use the coupon.', 'woocommerce' ),
143
						'data_type'   => 'price',
144
						'desc_tip'    => true,
145
						'value'       => $coupon->get_minimum_amount( 'edit' ),
146
					)
147
				);
148
149
				// maximum spend.
150
				woocommerce_wp_text_input(
151
					array(
152
						'id'          => 'maximum_amount',
153
						'label'       => __( 'Maximum spend', 'woocommerce' ),
154
						'placeholder' => __( 'No maximum', 'woocommerce' ),
155
						'description' => __( 'This field allows you to set the maximum spend (subtotal) allowed when using the coupon.', 'woocommerce' ),
156
						'data_type'   => 'price',
157
						'desc_tip'    => true,
158
						'value'       => $coupon->get_maximum_amount( 'edit' ),
159
					)
160
				);
161
162
				// Individual use.
163
				woocommerce_wp_checkbox(
164
					array(
165
						'id'          => 'individual_use',
166
						'label'       => __( 'Individual use only', 'woocommerce' ),
167
						'description' => __( 'Check this box if the coupon cannot be used in conjunction with other coupons.', 'woocommerce' ),
168
						'value'       => wc_bool_to_string( $coupon->get_individual_use( 'edit' ) ),
169
					)
170
				);
171
172
				// Exclude Sale Products.
173
				woocommerce_wp_checkbox(
174
					array(
175
						'id'          => 'exclude_sale_items',
176
						'label'       => __( 'Exclude sale items', 'woocommerce' ),
177
						'description' => __( 'Check this box if the coupon should not apply to items on sale. Per-item coupons will only work if the item is not on sale. Per-cart coupons will only work if there are items in the cart that are not on sale.', 'woocommerce' ),
178
						'value'       => wc_bool_to_string( $coupon->get_exclude_sale_items( 'edit' ) ),
179
					)
180
				);
181
182
				echo '</div><div class="options_group">';
183
184
				// Product ids.
185
				?>
186
				<p class="form-field">
187
					<label><?php _e( 'Products', 'woocommerce' ); ?></label>
188
					<select class="wc-product-search" multiple="multiple" style="width: 50%;" name="product_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations">
189
						<?php
190
						$product_ids = $coupon->get_product_ids( 'edit' );
191
192 View Code Duplication
						foreach ( $product_ids as $product_id ) {
193
							$product = wc_get_product( $product_id );
194
							if ( is_object( $product ) ) {
195
								echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
196
							}
197
						}
198
						?>
199
					</select>
200
					<?php echo wc_help_tip( __( 'Products that the coupon will be applied to, or that need to be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
201
				</p>
202
203
				<?php // Exclude Product ids. ?>
204
				<p class="form-field">
205
					<label><?php _e( 'Exclude products', 'woocommerce' ); ?></label>
206
					<select class="wc-product-search" multiple="multiple" style="width: 50%;" name="exclude_product_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations">
207
						<?php
208
						$product_ids = $coupon->get_excluded_product_ids( 'edit' );
209
210 View Code Duplication
						foreach ( $product_ids as $product_id ) {
211
							$product = wc_get_product( $product_id );
212
							if ( is_object( $product ) ) {
213
								echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . wp_kses_post( $product->get_formatted_name() ) . '</option>';
214
							}
215
						}
216
						?>
217
					</select>
218
					<?php echo wc_help_tip( __( 'Products that the coupon will not be applied to, or that cannot be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
219
				</p>
220
				<?php
221
222
				echo '</div><div class="options_group">';
223
224
				// Categories.
225
				?>
226
				<p class="form-field">
227
					<label for="product_categories"><?php _e( 'Product categories', 'woocommerce' ); ?></label>
228
					<select id="product_categories" name="product_categories[]" style="width: 50%;"  class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'Any category', 'woocommerce' ); ?>">
229
						<?php
230
						$category_ids = $coupon->get_product_categories( 'edit' );
231
						$categories   = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
232
233 View Code Duplication
						if ( $categories ) {
234
							foreach ( $categories as $cat ) {
235
								echo '<option value="' . esc_attr( $cat->term_id ) . '"' . wc_selected( $cat->term_id, $category_ids ) . '>' . esc_html( $cat->name ) . '</option>';
236
							}
237
						}
238
						?>
239
					</select> <?php echo wc_help_tip( __( 'Product categories that the coupon will be applied to, or that need to be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
240
				</p>
241
242
				<?php // Exclude Categories. ?>
243
				<p class="form-field">
244
					<label for="exclude_product_categories"><?php _e( 'Exclude categories', 'woocommerce' ); ?></label>
245
					<select id="exclude_product_categories" name="exclude_product_categories[]" style="width: 50%;"  class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No categories', 'woocommerce' ); ?>">
246
						<?php
247
						$category_ids = $coupon->get_excluded_product_categories( 'edit' );
248
						$categories   = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
249
250 View Code Duplication
						if ( $categories ) {
251
							foreach ( $categories as $cat ) {
252
								echo '<option value="' . esc_attr( $cat->term_id ) . '"' . wc_selected( $cat->term_id, $category_ids ) . '>' . esc_html( $cat->name ) . '</option>';
253
							}
254
						}
255
						?>
256
					</select>
257
					<?php echo wc_help_tip( __( 'Product categories that the coupon will not be applied to, or that cannot be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
258
				</p>
259
			</div>
260
			<div class="options_group">
261
				<?php
262
				// Customers.
263
				woocommerce_wp_text_input(
264
					array(
265
						'id'                => 'customer_email',
266
						'label'             => __( 'Allowed emails', 'woocommerce' ),
267
						'placeholder'       => __( 'No restrictions', 'woocommerce' ),
268
						'description'       => __( 'Whitelist of billing emails to check against when an order is placed. Separate email addresses with commas. You can also use an asterisk (*) to match parts of an email. For example "*@gmail.com" would match all gmail addresses.', 'woocommerce' ),
269
						'value'             => implode( ', ', (array) $coupon->get_email_restrictions( 'edit' ) ),
270
						'desc_tip'          => true,
271
						'type'              => 'email',
272
						'class'             => '',
273
						'custom_attributes' => array(
274
							'multiple' => 'multiple',
275
						),
276
					)
277
				);
278
				?>
279
			</div>
280
			<?php do_action( 'woocommerce_coupon_options_usage_restriction', $coupon->get_id(), $coupon ); ?>
281
			</div>
282
			<div id="usage_limit_coupon_data" class="panel woocommerce_options_panel">
283
				<div class="options_group">
284
					<?php
285
					// Usage limit per coupons.
286
					woocommerce_wp_text_input(
287
						array(
288
							'id'                => 'usage_limit',
289
							'label'             => __( 'Usage limit per coupon', 'woocommerce' ),
290
							'placeholder'       => esc_attr__( 'Unlimited usage', 'woocommerce' ),
291
							'description'       => __( 'How many times this coupon can be used before it is void.', 'woocommerce' ),
292
							'type'              => 'number',
293
							'desc_tip'          => true,
294
							'class'             => 'short',
295
							'custom_attributes' => array(
296
								'step' => 1,
297
								'min'  => 0,
298
							),
299
							'value'             => $coupon->get_usage_limit( 'edit' ) ? $coupon->get_usage_limit( 'edit' ) : '',
300
						)
301
					);
302
303
					// Usage limit per product.
304
					woocommerce_wp_text_input(
305
						array(
306
							'id'                => 'limit_usage_to_x_items',
307
							'label'             => __( 'Limit usage to X items', 'woocommerce' ),
308
							'placeholder'       => esc_attr__( 'Apply to all qualifying items in cart', 'woocommerce' ),
309
							'description'       => __( 'The maximum number of individual items this coupon can apply to when using product discounts. Leave blank to apply to all qualifying items in cart.', 'woocommerce' ),
310
							'desc_tip'          => true,
311
							'class'             => 'short',
312
							'type'              => 'number',
313
							'custom_attributes' => array(
314
								'step' => 1,
315
								'min'  => 0,
316
							),
317
							'value'             => $coupon->get_limit_usage_to_x_items( 'edit' ) ? $coupon->get_limit_usage_to_x_items( 'edit' ) : '',
318
						)
319
					);
320
321
					// Usage limit per users.
322
					woocommerce_wp_text_input(
323
						array(
324
							'id'                => 'usage_limit_per_user',
325
							'label'             => __( 'Usage limit per user', 'woocommerce' ),
326
							'placeholder'       => esc_attr__( 'Unlimited usage', 'woocommerce' ),
327
							'description'       => __( 'How many times this coupon can be used by an individual user. Uses billing email for guests, and user ID for logged in users.', 'woocommerce' ),
328
							'desc_tip'          => true,
329
							'class'             => 'short',
330
							'type'              => 'number',
331
							'custom_attributes' => array(
332
								'step' => 1,
333
								'min'  => 0,
334
							),
335
							'value'             => $coupon->get_usage_limit_per_user( 'edit' ) ? $coupon->get_usage_limit_per_user( 'edit' ) : '',
336
						)
337
					);
338
					?>
339
				</div>
340
				<?php do_action( 'woocommerce_coupon_options_usage_limit', $coupon->get_id(), $coupon ); ?>
341
			</div>
342
			<?php do_action( 'woocommerce_coupon_data_panels', $coupon->get_id(), $coupon ); ?>
343
			<div class="clear"></div>
344
		</div>
345
		<?php
346
	}
347
348
	/**
349
	 * Save meta box data.
350
	 *
351
	 * @param int     $post_id
352
	 * @param WP_Post $post
353
	 */
354
	public static function save( $post_id, $post ) {
355
		// Check for dupe coupons.
356
		$coupon_code  = wc_format_coupon_code( $post->post_title );
357
		$id_from_code = wc_get_coupon_id_by_code( $coupon_code, $post_id );
358
359
		if ( $id_from_code ) {
360
			WC_Admin_Meta_Boxes::add_error( __( 'Coupon code already exists - customers will use the latest coupon with this code.', 'woocommerce' ) );
361
		}
362
363
		$product_categories         = isset( $_POST['product_categories'] ) ? (array) $_POST['product_categories'] : array();
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_POST
Loading history...
364
		$exclude_product_categories = isset( $_POST['exclude_product_categories'] ) ? (array) $_POST['exclude_product_categories'] : array();
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_POST
Loading history...
365
366
		$coupon = new WC_Coupon( $post_id );
367
		$coupon->set_props(
368
			array(
369
				'code'                        => $post->post_title,
370
				'discount_type'               => wc_clean( $_POST['discount_type'] ),
371
				'amount'                      => wc_format_decimal( $_POST['coupon_amount'] ),
372
				'date_expires'                => wc_clean( $_POST['expiry_date'] ),
373
				'individual_use'              => isset( $_POST['individual_use'] ),
374
				'product_ids'                 => isset( $_POST['product_ids'] ) ? array_filter( array_map( 'intval', (array) $_POST['product_ids'] ) ) : array(),
375
				'excluded_product_ids'        => isset( $_POST['exclude_product_ids'] ) ? array_filter( array_map( 'intval', (array) $_POST['exclude_product_ids'] ) ) : array(),
376
				'usage_limit'                 => absint( $_POST['usage_limit'] ),
377
				'usage_limit_per_user'        => absint( $_POST['usage_limit_per_user'] ),
378
				'limit_usage_to_x_items'      => absint( $_POST['limit_usage_to_x_items'] ),
379
				'free_shipping'               => isset( $_POST['free_shipping'] ),
380
				'product_categories'          => array_filter( array_map( 'intval', $product_categories ) ),
381
				'excluded_product_categories' => array_filter( array_map( 'intval', $exclude_product_categories ) ),
382
				'exclude_sale_items'          => isset( $_POST['exclude_sale_items'] ),
383
				'minimum_amount'              => wc_format_decimal( $_POST['minimum_amount'] ),
384
				'maximum_amount'              => wc_format_decimal( $_POST['maximum_amount'] ),
385
				'email_restrictions'          => array_filter( array_map( 'trim', explode( ',', wc_clean( $_POST['customer_email'] ) ) ) ),
386
			)
387
		);
388
		$coupon->save();
389
		do_action( 'woocommerce_coupon_options_save', $post_id, $coupon );
390
	}
391
}
392