Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
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 | <style type="text/css"> |
||
31 | #edit-slug-box, #minor-publishing-actions { display:none } |
||
32 | </style> |
||
33 | <div id="coupon_options" class="panel-wrap coupon_data"> |
||
34 | |||
35 | <div class="wc-tabs-back"></div> |
||
36 | |||
37 | <ul class="coupon_data_tabs wc-tabs" style="display:none;"> |
||
38 | <?php |
||
39 | $coupon_data_tabs = apply_filters( 'woocommerce_coupon_data_tabs', array( |
||
40 | 'general' => array( |
||
41 | 'label' => __( 'General', 'woocommerce' ), |
||
42 | 'target' => 'general_coupon_data', |
||
43 | 'class' => 'general_coupon_data', |
||
44 | ), |
||
45 | 'usage_restriction' => array( |
||
46 | 'label' => __( 'Usage Restriction', 'woocommerce' ), |
||
47 | 'target' => 'usage_restriction_coupon_data', |
||
48 | 'class' => '', |
||
49 | ), |
||
50 | 'usage_limit' => array( |
||
51 | 'label' => __( 'Usage Limits', 'woocommerce' ), |
||
52 | 'target' => 'usage_limit_coupon_data', |
||
53 | 'class' => '', |
||
54 | ) |
||
55 | ) ); |
||
56 | |||
57 | View Code Duplication | foreach ( $coupon_data_tabs as $key => $tab ) { |
|
|
|||
58 | ?><li class="<?php echo $key; ?>_options <?php echo $key; ?>_tab <?php echo implode( ' ' , (array) $tab['class'] ); ?>"> |
||
59 | <a href="#<?php echo $tab['target']; ?>"><?php echo esc_html( $tab['label'] ); ?></a> |
||
60 | </li><?php |
||
61 | } |
||
62 | ?> |
||
63 | </ul> |
||
64 | <div id="general_coupon_data" class="panel woocommerce_options_panel"><?php |
||
65 | |||
66 | // Type |
||
67 | woocommerce_wp_select( array( 'id' => 'discount_type', 'label' => __( 'Discount type', 'woocommerce' ), 'options' => wc_get_coupon_types() ) ); |
||
68 | |||
69 | // Amount |
||
70 | woocommerce_wp_text_input( array( 'id' => 'coupon_amount', 'label' => __( 'Coupon amount', 'woocommerce' ), 'placeholder' => wc_format_localized_price( 0 ), 'description' => __( 'Value of the coupon.', 'woocommerce' ), 'data_type' => 'price', 'desc_tip' => true ) ); |
||
71 | |||
72 | // Free Shipping |
||
73 | woocommerce_wp_checkbox( array( 'id' => 'free_shipping', 'label' => __( 'Allow free shipping', 'woocommerce' ), 'description' => sprintf( __( 'Check this box if the coupon grants free shipping. The <a href="%s">free shipping method</a> must be enabled and be set to require "a valid free shipping coupon" (see the "Free Shipping Requires" setting).', 'woocommerce' ), admin_url('admin.php?page=wc-settings&tab=shipping§ion=WC_Shipping_Free_Shipping')) ) ); |
||
74 | |||
75 | // Expiry date |
||
76 | woocommerce_wp_text_input( array( 'id' => 'expiry_date', 'label' => __( 'Coupon expiry date', 'woocommerce' ), 'placeholder' => _x( 'YYYY-MM-DD', 'placeholder', 'woocommerce' ), 'description' => '', 'class' => 'date-picker', 'custom_attributes' => array( 'pattern' => "[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" ) ) ); |
||
77 | |||
78 | do_action( 'woocommerce_coupon_options' ); |
||
79 | |||
80 | ?></div> |
||
81 | <div id="usage_restriction_coupon_data" class="panel woocommerce_options_panel"><?php |
||
82 | |||
83 | echo '<div class="options_group">'; |
||
84 | |||
85 | // minimum spend |
||
86 | woocommerce_wp_text_input( array( 'id' => 'minimum_amount', 'label' => __( 'Minimum spend', 'woocommerce' ), 'placeholder' => __( 'No minimum', 'woocommerce' ), 'description' => __( 'This field allows you to set the minimum spend (subtotal, including taxes) allowed to use the coupon.', 'woocommerce' ), 'data_type' => 'price', 'desc_tip' => true ) ); |
||
87 | |||
88 | // maximum spend |
||
89 | woocommerce_wp_text_input( array( 'id' => 'maximum_amount', 'label' => __( 'Maximum spend', 'woocommerce' ), 'placeholder' => __( 'No maximum', 'woocommerce' ), 'description' => __( 'This field allows you to set the maximum spend (subtotal, including taxes) allowed when using the coupon.', 'woocommerce' ), 'data_type' => 'price', 'desc_tip' => true ) ); |
||
90 | |||
91 | // Individual use |
||
92 | woocommerce_wp_checkbox( array( 'id' => 'individual_use', 'label' => __( 'Individual use only', 'woocommerce' ), 'description' => __( 'Check this box if the coupon cannot be used in conjunction with other coupons.', 'woocommerce' ) ) ); |
||
93 | |||
94 | // Exclude Sale Products |
||
95 | woocommerce_wp_checkbox( array( 'id' => 'exclude_sale_items', 'label' => __( 'Exclude sale items', 'woocommerce' ), '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 no sale items in the cart.', 'woocommerce' ) ) ); |
||
96 | |||
97 | echo '</div><div class="options_group">'; |
||
98 | |||
99 | // Product ids |
||
100 | ?> |
||
101 | <p class="form-field"><label><?php _e( 'Products', 'woocommerce' ); ?></label> |
||
102 | <input type="hidden" class="wc-product-search" data-multiple="true" style="width: 50%;" name="product_ids" data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-selected="<?php |
||
103 | $product_ids = array_filter( array_map( 'absint', explode( ',', get_post_meta( $post->ID, 'product_ids', true ) ) ) ); |
||
104 | $json_ids = array(); |
||
105 | |||
106 | View Code Duplication | foreach ( $product_ids as $product_id ) { |
|
107 | $product = wc_get_product( $product_id ); |
||
108 | if ( is_object( $product ) ) { |
||
109 | $json_ids[ $product_id ] = wp_kses_post( $product->get_formatted_name() ); |
||
110 | } |
||
111 | } |
||
112 | |||
113 | echo esc_attr( json_encode( $json_ids ) ); |
||
114 | ?>" value="<?php echo implode( ',', array_keys( $json_ids ) ); ?>" /> <?php echo wc_help_tip( __( 'Products which need to be in the cart to use this coupon or, for "Product Discounts", which products are discounted.', 'woocommerce' ) ); ?></p> |
||
115 | <?php |
||
116 | |||
117 | // Exclude Product ids |
||
118 | ?> |
||
119 | <p class="form-field"><label><?php _e( 'Exclude products', 'woocommerce' ); ?></label> |
||
120 | <input type="hidden" class="wc-product-search" data-multiple="true" style="width: 50%;" name="exclude_product_ids" data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-selected="<?php |
||
121 | $product_ids = array_filter( array_map( 'absint', explode( ',', get_post_meta( $post->ID, 'exclude_product_ids', true ) ) ) ); |
||
122 | $json_ids = array(); |
||
123 | |||
124 | View Code Duplication | foreach ( $product_ids as $product_id ) { |
|
125 | $product = wc_get_product( $product_id ); |
||
126 | if ( is_object( $product ) ) { |
||
127 | $json_ids[ $product_id ] = wp_kses_post( $product->get_formatted_name() ); |
||
128 | } |
||
129 | } |
||
130 | |||
131 | echo esc_attr( json_encode( $json_ids ) ); |
||
132 | ?>" value="<?php echo implode( ',', array_keys( $json_ids ) ); ?>" /> <?php echo wc_help_tip( __( 'Products which must not be in the cart to use this coupon or, for "Product Discounts", which products are not discounted.', 'woocommerce' ) ); ?></p> |
||
133 | <?php |
||
134 | |||
135 | echo '</div><div class="options_group">'; |
||
136 | |||
137 | // Categories |
||
138 | ?> |
||
139 | <p class="form-field"><label for="product_categories"><?php _e( 'Product categories', 'woocommerce' ); ?></label> |
||
140 | <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' ); ?>"> |
||
141 | <?php |
||
142 | $category_ids = (array) get_post_meta( $post->ID, 'product_categories', true ); |
||
143 | $categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' ); |
||
144 | |||
145 | View Code Duplication | if ( $categories ) foreach ( $categories as $cat ) { |
|
146 | echo '<option value="' . esc_attr( $cat->term_id ) . '"' . selected( in_array( $cat->term_id, $category_ids ), true, false ) . '>' . esc_html( $cat->name ) . '</option>'; |
||
147 | } |
||
148 | ?> |
||
149 | </select> <?php echo wc_help_tip( __( 'A product must be in this category for the coupon to remain valid or, for "Product Discounts", products in these categories will be discounted.', 'woocommerce' ) ); ?></p> |
||
150 | <?php |
||
151 | |||
152 | // Exclude Categories |
||
153 | ?> |
||
154 | <p class="form-field"><label for="exclude_product_categories"><?php _e( 'Exclude categories', 'woocommerce' ); ?></label> |
||
155 | <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' ); ?>"> |
||
156 | <?php |
||
157 | $category_ids = (array) get_post_meta( $post->ID, 'exclude_product_categories', true ); |
||
158 | $categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' ); |
||
159 | |||
160 | View Code Duplication | if ( $categories ) foreach ( $categories as $cat ) { |
|
161 | echo '<option value="' . esc_attr( $cat->term_id ) . '"' . selected( in_array( $cat->term_id, $category_ids ), true, false ) . '>' . esc_html( $cat->name ) . '</option>'; |
||
162 | } |
||
163 | ?> |
||
164 | </select> <?php echo wc_help_tip( __( 'Product must not be in this category for the coupon to remain valid or, for "Product Discounts", products in these categories will not be discounted.', 'woocommerce' ) ); ?></p> |
||
165 | <?php |
||
166 | |||
167 | echo '</div><div class="options_group">'; |
||
168 | |||
169 | // Customers |
||
170 | woocommerce_wp_text_input( array( 'id' => 'customer_email', 'label' => __( 'Email restrictions', 'woocommerce' ), 'placeholder' => __( 'No restrictions', 'woocommerce' ), 'description' => __( 'List of allowed emails to check against the customer\'s billing email when an order is placed. Separate email addresses with commas.', 'woocommerce' ), 'value' => implode(', ', (array) get_post_meta( $post->ID, 'customer_email', true ) ), 'desc_tip' => true, 'type' => 'email', 'class' => '', 'custom_attributes' => array( |
||
171 | 'multiple' => 'multiple' |
||
172 | ) ) ); |
||
173 | |||
174 | echo '</div>'; |
||
175 | |||
176 | do_action( 'woocommerce_coupon_options_usage_restriction' ); |
||
177 | |||
178 | ?></div> |
||
179 | <div id="usage_limit_coupon_data" class="panel woocommerce_options_panel"><?php |
||
180 | |||
181 | echo '<div class="options_group">'; |
||
182 | |||
183 | // Usage limit per coupons |
||
184 | woocommerce_wp_text_input( array( 'id' => 'usage_limit', 'label' => __( 'Usage limit per coupon', 'woocommerce' ), 'placeholder' => _x('Unlimited usage', 'placeholder', 'woocommerce'), 'description' => __( 'How many times this coupon can be used before it is void.', 'woocommerce' ), 'type' => 'number', 'desc_tip' => true, 'class' => 'short', 'custom_attributes' => array( |
||
185 | 'step' => '1', |
||
186 | 'min' => '0' |
||
187 | ) ) ); |
||
188 | |||
189 | // Usage limit per product |
||
190 | woocommerce_wp_text_input( array( 'id' => 'limit_usage_to_x_items', 'label' => __( 'Limit usage to X items', 'woocommerce' ), 'placeholder' => _x( 'Apply to all qualifying items in cart', 'placeholder', 'woocommerce' ), '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' ), 'desc_tip' => true, 'class' => 'short', 'type' => 'number', 'custom_attributes' => array( |
||
191 | 'step' => '1', |
||
192 | 'min' => '0' |
||
193 | ) ) ); |
||
194 | |||
195 | // Usage limit per users |
||
196 | woocommerce_wp_text_input( array( 'id' => 'usage_limit_per_user', 'label' => __( 'Usage limit per user', 'woocommerce' ), 'placeholder' => _x( 'Unlimited usage', 'placeholder', 'woocommerce' ), 'description' => __( 'How many times this coupon can be used by an invidual user. Uses billing email for guests, and user ID for logged in users.', 'woocommerce' ), 'desc_tip' => true, 'class' => 'short', 'type' => 'number', 'custom_attributes' => array( |
||
197 | 'step' => '1', |
||
198 | 'min' => '0' |
||
199 | ) ) ); |
||
200 | |||
201 | echo '</div>'; |
||
202 | |||
203 | do_action( 'woocommerce_coupon_options_usage_limit' ); |
||
204 | |||
205 | ?></div> |
||
206 | <?php do_action( 'woocommerce_coupon_data_panels' ); ?> |
||
207 | <div class="clear"></div> |
||
208 | </div> |
||
209 | <?php |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Save meta box data. |
||
214 | * |
||
215 | * @param int $post_id |
||
216 | * @param WP_Post $post |
||
217 | */ |
||
218 | public static function save( $post_id, $post ) { |
||
281 | } |
||
282 |
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.