Completed
Pull Request — master (#11549)
by
unknown
09:22
created

WC_Admin_Attributes::add_attribute()   D

Complexity

Conditions 13
Paths 4

Size

Total Lines 259
Code Lines 109

Duplication

Lines 8
Ratio 3.09 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 13
eloc 109
c 1
b 0
f 1
nc 4
nop 0
dl 8
loc 259
rs 4.9922

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
2
/**
3
 * Attributes Page
4
 *
5
 * The attributes section lets users add custom attributes to assign to products - they can also be used in the layered nav widget.
6
 *
7
 * @author 		WooThemes
8
 * @category 	Admin
9
 * @package 	WooCommerce/Admin
10
 * @version   2.3.0
11
 */
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit; // Exit if accessed directly
15
}
16
17
/**
18
 * WC_Admin_Attributes Class
19
 */
20
class WC_Admin_Attributes {
21
22
	/**
23
	 * Handles output of the attributes page in admin.
24
	 *
25
	 * Shows the created attributes and lets you add new ones or edit existing ones.
26
	 * The added attributes are stored in the database and can be used for layered navigation.
27
	 */
28
	public static function output() {
29
			$result = '';
30
			$action = '';
31
32
			// Action to perform: add, edit, delete or none
33
			if ( ! empty( $_POST['add_new_attribute'] ) ) {
34
					$action = 'add';
35
			} elseif ( ! empty( $_POST['save_attribute'] ) && ! empty( $_GET['edit'] ) ) {
36
					$action = 'edit';
37
			} elseif ( ! empty( $_GET['delete'] ) ) {
38
					$action = 'delete';
39
			}
40
41
			switch ( $action ) {
42
					case 'add' :
43
							$result = self::process_add_attribute();
44
					break;
45
					case 'edit' :
46
							$result = self::process_edit_attribute();
47
					break;
48
					case 'delete' :
49
							$result = self::process_delete_attribute();
50
					break;
51
			}
52
53
			if ( is_wp_error( $result ) ) {
54
					echo '<div id="woocommerce_errors" class="error"><p>' . $result->get_error_message() . '</p></div>';
55
			}
56
57
			// Show admin interface
58
			if ( ! empty( $_GET['edit'] ) ) {
59
					self::edit_attribute();
60
			} else {
61
					self::add_attribute();
62
			}
63
	}
64
65
	/**
66
	 * Get and sanitize posted attribute data.
67
	 * @return array
68
	 */
69
	private static function get_posted_attribute() {
70
			$attribute = array(
71
					'attribute_label'   		=> isset( $_POST['attribute_label'] ) ? wc_clean( stripslashes( $_POST['attribute_label'] ) ) : '',
72
					'attribute_name'    		=> isset( $_POST['attribute_name'] ) ? wc_sanitize_taxonomy_name( stripslashes( $_POST['attribute_name'] ) ) : '',
73
					'attribute_type'    		=> isset( $_POST['attribute_type'] ) ? wc_clean( $_POST['attribute_type'] ) : 'select',
74
					'attribute_orderby' 		=> isset( $_POST['attribute_orderby'] ) ? wc_clean( $_POST['attribute_orderby'] ) : '',
75
					'attribute_public'  		=> isset( $_POST['attribute_public'] ) ? 1 : 0,
76
					'attribute_description' => isset( $_POST['attribute_description'] ) ? wc_clean( stripslashes( $_POST['attribute_description'] ) ) : '',
77
					'attribute_thumbnail_id' 		=> isset( $_POST['attribute_thumbnail_id'] ) ? absint( $_POST['attribute_thumbnail_id'] ) : ''
78
			);
79
80
			if ( empty( $attribute['attribute_type'] ) ) {
81
					$attribute['attribute_type'] = 'select';
82
			}
83
			if ( empty( $attribute['attribute_label'] ) ) {
84
					$attribute['attribute_label'] = ucfirst( $attribute['attribute_name'] );
85
			}
86
			if ( empty( $attribute['attribute_name'] ) ) {
87
					$attribute['attribute_name'] = wc_sanitize_taxonomy_name( $attribute['attribute_label'] );
88
			}
89
90
			return $attribute;
91
	}
92
93
	/**
94
	 * See if an attribute name is valid.
95
	 * @param  string $attribute_name
96
	 * @return bool|WP_error result
97
	 */
98
	private static function valid_attribute_name( $attribute_name ) {
99
			if ( strlen( $attribute_name ) >= 28 ) {
100
					return new WP_Error( 'error', sprintf( __( 'Slug "%s" is too long (28 characters max). Shorten it, please.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
101
			} elseif ( wc_check_if_attribute_name_is_reserved( $attribute_name ) ) {
102
					return new WP_Error( 'error', sprintf( __( 'Slug "%s" is not allowed because it is a reserved term. Change it, please.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
103
			}
104
105
			return true;
106
	}
107
108
	/**
109
	 * Add an attribute.
110
	 * @return bool|WP_Error
111
	 */
112
	private static function process_add_attribute() {
113
			global $wpdb;
114
			check_admin_referer( 'woocommerce-add-new_attribute' );
115
116
			$attribute = self::get_posted_attribute();
117
118
			if ( empty( $attribute['attribute_name'] ) || empty( $attribute['attribute_label'] ) ) {
119
					return new WP_Error( 'error', __( 'Please, provide an attribute name and slug.', 'woocommerce' ) );
120
			} elseif ( ( $valid_attribute_name = self::valid_attribute_name( $attribute['attribute_name'] ) ) && is_wp_error( $valid_attribute_name ) ) {
121
					return $valid_attribute_name;
122
			} elseif ( taxonomy_exists( wc_attribute_taxonomy_name( $attribute['attribute_name'] ) ) ) {
123
					return new WP_Error( 'error', sprintf( __( 'Slug "%s" is already in use. Change it, please.', 'woocommerce' ), sanitize_title( $attribute['attribute_name'] ) ) );
124
			}
125
126
			$wpdb->insert( $wpdb->prefix . 'woocommerce_attribute_taxonomies', $attribute );
127
128
			do_action( 'woocommerce_attribute_added', $wpdb->insert_id, $attribute );
129
130
			flush_rewrite_rules();
131
			delete_transient( 'wc_attribute_taxonomies' );
132
133
			return true;
134
	}
135
136
	/**
137
	 * Edit an attribute.
138
	 * @return bool|WP_Error
139
	 */
140
	private static function process_edit_attribute() {
141
			global $wpdb;
142
			$attribute_id = absint( $_GET['edit'] );
143
			check_admin_referer( 'woocommerce-save-attribute_' . $attribute_id );
144
145
			$attribute = self::get_posted_attribute();
146
147
			if ( empty( $attribute['attribute_name'] ) || empty( $attribute['attribute_label'] ) ) {
148
					return new WP_Error( 'error', __( 'Please, provide an attribute name and slug.', 'woocommerce' ) );
149
			} elseif ( ( $valid_attribute_name = self::valid_attribute_name( $attribute['attribute_name'] ) ) && is_wp_error( $valid_attribute_name ) ) {
150
					return $valid_attribute_name;
151
			}
152
153
			$taxonomy_exists    = taxonomy_exists( wc_attribute_taxonomy_name( $attribute['attribute_name'] ) );
154
			$old_attribute_name = $wpdb->get_var( "SELECT attribute_name FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = $attribute_id" );
155
			if ( $old_attribute_name != $attribute['attribute_name'] && wc_sanitize_taxonomy_name( $old_attribute_name ) != $attribute['attribute_name'] && $taxonomy_exists ) {
156
					return new WP_Error( 'error', sprintf( __( 'Slug "%s" is already in use. Change it, please.', 'woocommerce' ), sanitize_title( $attribute['attribute_name'] ) ) );
157
			}
158
159
			$wpdb->update( $wpdb->prefix . 'woocommerce_attribute_taxonomies', $attribute, array( 'attribute_id' => $attribute_id ) );
160
161
			do_action( 'woocommerce_attribute_updated', $attribute_id, $attribute, $old_attribute_name );
162
163
			if ( $old_attribute_name != $attribute['attribute_name'] && ! empty( $old_attribute_name ) ) {
164
					// Update taxonomies in the wp term taxonomy table
165
					$wpdb->update(
166
							$wpdb->term_taxonomy,
167
							array( 'taxonomy' => wc_attribute_taxonomy_name( $attribute['attribute_name'] ) ),
168
							array( 'taxonomy' => 'pa_' . $old_attribute_name )
169
					);
170
171
					// Update taxonomy ordering term meta
172
					if ( get_option( 'db_version' ) < 34370 ) {
173
							$wpdb->update(
174
									$wpdb->prefix . 'woocommerce_termmeta',
175
									array( 'meta_key' => 'order_pa_' . sanitize_title( $attribute['attribute_name'] ) ),
176
									array( 'meta_key' => 'order_pa_' . sanitize_title( $old_attribute_name ) )
177
							);
178
					} else {
179
							$wpdb->update(
180
									$wpdb->termmeta,
181
									array( 'meta_key' => 'order_pa_' . sanitize_title( $attribute['attribute_name'] ) ),
182
									array( 'meta_key' => 'order_pa_' . sanitize_title( $old_attribute_name ) )
183
							);
184
					}
185
186
					// Update product attributes which use this taxonomy
187
					$old_attribute_name_length = strlen( $old_attribute_name ) + 3;
188
					$attribute_name_length     = strlen( $attribute['attribute_name'] ) + 3;
189
190
					$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_value = REPLACE( meta_value, %s, %s ) WHERE meta_key = '_product_attributes_ext'",
191
							's:' . $old_attribute_name_length . ':"pa_' . $old_attribute_name . '"',
192
							's:' . $attribute_name_length . ':"pa_' . $attribute['attribute_name'] . '"'
193
					) );
194
195
					// Update variations which use this taxonomy
196
					$wpdb->update(
197
							$wpdb->postmeta,
198
							array( 'meta_key' => 'attribute_pa_' . sanitize_title( $attribute['attribute_name'] ) ),
199
							array( 'meta_key' => 'attribute_pa_' . sanitize_title( $old_attribute_name ) )
200
					);
201
			}
202
203
			echo '<div class="updated"><p>' . __( 'Attribute updated successfully', 'woocommerce' ) . '</p></div>';
204
205
			flush_rewrite_rules();
206
			delete_transient( 'wc_attribute_taxonomies' );
207
208
			return true;
209
	}
210
211
	/**
212
	 * Delete an attribute.
213
	 * @return bool
214
	 */
215
	private static function process_delete_attribute() {
216
			global $wpdb;
217
218
			$attribute_id = absint( $_GET['delete'] );
219
220
			check_admin_referer( 'woocommerce-delete-attribute_' . $attribute_id );
221
222
			$attribute_name = $wpdb->get_var( "SELECT attribute_name FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = $attribute_id" );
223
			$taxonomy       = wc_attribute_taxonomy_name( $attribute_name );
224
225
			do_action( 'woocommerce_before_attribute_delete', $attribute_id, $attribute_name, $taxonomy );
226
227
			if ( $attribute_name && $wpdb->query( "DELETE FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = $attribute_id" ) ) {
228
					if ( taxonomy_exists( $taxonomy ) ) {
229
							$terms = get_terms( $taxonomy, 'orderby=name&hide_empty=0' );
230
							foreach ( $terms as $term ) {
231
									wp_delete_term( $term->term_id, $taxonomy );
232
							}
233
					}
234
235
					do_action( 'woocommerce_attribute_deleted', $attribute_id, $attribute_name, $taxonomy );
236
					delete_transient( 'wc_attribute_taxonomies' );
237
					return true;
238
			}
239
240
			return false;
241
	}
242
243
	/**
244
	 * Edit Attribute admin panel.
245
	 *
246
	 * Shows the interface for changing an attributes type between select and text.
247
	 */
248
	public static function edit_attribute() {
249
			global $wpdb;
250
251
			$edit = absint( $_GET['edit'] );
252
253
			$attribute_to_edit = $wpdb->get_row( "SELECT * FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies WHERE attribute_id = '$edit'" );
254
255
			wp_enqueue_media();
256
			// echo '<pre>'; var_dump($attribute_to_edit); echo '</pre>';
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
257
			?>
258
			<div class="wrap woocommerce">
259
					<div class="icon32 icon32-attributes" id="icon-woocommerce"><br/></div>
260
					<h1><?php _e( 'Edit Attribute', 'woocommerce' ) ?></h1>
261
262
					<?php
263
264
							if ( ! $attribute_to_edit ) {
265
									echo '<div id="woocommerce_errors" class="error"><p>' . __( 'Error: non-existing attribute ID.', 'woocommerce' ) . '</p></div>';
266
							} else {
267
									$att_type    = $attribute_to_edit->attribute_type;
268
									$att_label   = $attribute_to_edit->attribute_label;
269
									$att_name    = $attribute_to_edit->attribute_name;
270
									$att_desc    = $attribute_to_edit->attribute_description;
271
									$att_orderby = $attribute_to_edit->attribute_orderby;
272
									$att_public  = $attribute_to_edit->attribute_public;
273
									$thumbnail_id = $attribute_to_edit->attribute_thumbnail_id;
274
									if ( $thumbnail_id ) {
275
											$image = wp_get_attachment_thumb_url( $thumbnail_id );
276
									} else {
277
											$image = wc_placeholder_img_src();
278
									}
279
280
281
							?>
282
283
							<form action="edit.php?post_type=product&amp;page=product_attributes&amp;edit=<?php echo absint( $edit ); ?>" method="post">
284
									<table class="form-table">
285
											<tbody>
286
													<tr class="form-field form-required">
287
															<th scope="row" valign="top">
288
																	<label for="attribute_label"><?php _e( 'Name', 'woocommerce' ); ?></label>
289
															</th>
290
															<td>
291
																	<input name="attribute_label" id="attribute_label" type="text" value="<?php echo esc_attr( $att_label ); ?>" />
292
																	<p class="description"><?php _e( 'Name for the attribute (shown on the front-end).', 'woocommerce' ); ?></p>
293
															</td>
294
													</tr>
295
													<tr class="form-field form-required">
296
															<th scope="row" valign="top">
297
																	<label for="attribute_name"><?php _e( 'Slug', 'woocommerce' ); ?></label>
298
															</th>
299
															<td>
300
																	<input name="attribute_name" id="attribute_name" type="text" value="<?php echo esc_attr( $att_name ); ?>" maxlength="28" />
301
																	<p class="description"><?php _e( 'Unique slug/reference for the attribute; must be shorter than 28 characters.', 'woocommerce' ); ?></p>
302
															</td>
303
													</tr>
304
													<tr class="form-field">
305
															<th scope="row" valign="top">
306
																	<label for="attribute_description"><?php _e( 'Description', 'woocommerce' ); ?></label>
307
															</th>
308
															<td>
309
																	<textarea name="attribute_description" id="attribute_description" rows="4"><?php echo esc_attr( $att_desc ); ?></textarea>
310
																	<p class="description"><?php _e( 'Description for the attribute, optional.', 'woocommerce' ); ?></p>
311
															</td>
312
													</tr>
313
													<tr class="form-field">
314
									            <th scope="row" valign="top">
315
																<label><?php _e( 'Attribute Graphic', 'woocommerce' ); ?></label>
316
															</th>
317
									            <td>
318
									                <div id="attribute_thumbnail" style="float: left; margin-right: 10px;"><img src="<?php echo esc_url( $image ); ?>" width="60px" height="60px" /></div>
319
									                <div style="line-height: 60px;">
320
									                    <input type="hidden" id="attribute_thumbnail_id" name="attribute_thumbnail_id" value="<?php echo $thumbnail_id; ?>" />
321
									                    <button type="button" class="upload_image_button button"><?php _e( 'Upload/Add image', 'woocommerce' ); ?></button>
322
									                    <button type="button" class="remove_image_button button"><?php _e( 'Remove image', 'woocommerce' ); ?></button>
323
									                </div>
324
									                <script type="text/javascript">
325
326
									                    // Only show the "remove image" button when needed
327
									                    if ( '0' === jQuery( '#attribute_thumbnail_id' ).val() ) {
328
									                        jQuery( '.remove_image_button' ).hide();
329
									                    }
330
331
									                    // Uploading files
332
									                    var file_frame;
333
334
									                    jQuery( document ).on( 'click', '.upload_image_button', function( event ) {
335
336
									                        event.preventDefault();
337
338
									                        // If the media frame already exists, reopen it.
339
									                        if ( file_frame ) {
340
									                            file_frame.open();
341
									                            return;
342
									                        }
343
344
									                        // Create the media frame.
345
									                        file_frame = wp.media.frames.downloadable_file = wp.media({
346
									                            title: '<?php _e( "Choose an image", "woocommerce" ); ?>',
347
									                            button: {
348
									                                text: '<?php _e( "Use image", "woocommerce" ); ?>'
349
									                            },
350
									                            multiple: false
351
									                        });
352
353
									                        // When an image is selected, run a callback.
354
									                        file_frame.on( 'select', function() {
355
									                            var attachment = file_frame.state().get( 'selection' ).first().toJSON();
356
357
									                            jQuery( '#attribute_thumbnail_id' ).val( attachment.id );
358
									                            jQuery( '#attribute_thumbnail' ).find( 'img' ).attr( 'src', attachment.url );
359
									                            jQuery( '.remove_image_button' ).show();
360
									                        });
361
362
									                        // Finally, open the modal.
363
									                        file_frame.open();
364
									                    });
365
366
									                    jQuery( document ).on( 'click', '.remove_image_button', function() {
367
									                        jQuery( '#attribute_thumbnail' ).find( 'img' ).attr( 'src', '<?php echo esc_js( wc_placeholder_img_src() ); ?>' );
368
									                        jQuery( '#attribute_thumbnail_id' ).val( '' );
369
									                        jQuery( '.remove_image_button' ).hide();
370
									                        return false;
371
									                    });
372
373
									                </script>
374
									                <div class="clear"></div>
375
									            </td>
376
									        </tr>
377
													<tr class="form-field form-required">
378
															<th scope="row" valign="top">
379
																	<label for="attribute_public"><?php _e( 'Enable Archives?', 'woocommerce' ); ?></label>
380
															</th>
381
															<td>
382
																	<input name="attribute_public" id="attribute_public" type="checkbox" value="1" <?php checked( $att_public, 1 ); ?> />
383
																	<p class="description"><?php _e( 'Enable this if you want this attribute to have product archives in your store.', 'woocommerce' ); ?></p>
384
															</td>
385
													</tr>
386
													<tr class="form-field form-required">
387
															<th scope="row" valign="top">
388
																	<label for="attribute_type"><?php _e( 'Type', 'woocommerce' ); ?></label>
389
															</th>
390
															<td>
391
																	<select name="attribute_type" id="attribute_type">
392
																			<?php foreach ( wc_get_attribute_types() as $key => $value ) : ?>
393
																					<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $att_type, $key ); ?>><?php echo esc_attr( $value ); ?></option>
394
																			<?php endforeach; ?>
395
396
																			<?php
397
398
																					/**
399
																					 * Deprecated action in favor of product_attributes_type_selector filter.
400
																					 *
401
																					 * @deprecated 2.4.0
402
																					 */
403
																					do_action( 'woocommerce_admin_attribute_types' );
404
																			?>
405
																	</select>
406
																	<p class="description"><?php _e( 'Determines how you select attributes for products. Under admin panel -> products -> product data -> attributes -> values, <strong>Text</strong> allows manual entry whereas <strong>select</strong> allows pre-configured terms in a drop-down list.', 'woocommerce' ); ?></p>
407
															</td>
408
													</tr>
409
													<tr class="form-field form-required">
410
															<th scope="row" valign="top">
411
																	<label for="attribute_orderby"><?php _e( 'Default sort order', 'woocommerce' ); ?></label>
412
															</th>
413
															<td>
414
																	<select name="attribute_orderby" id="attribute_orderby">
415
																			<option value="menu_order" <?php selected( $att_orderby, 'menu_order' ); ?>><?php _e( 'Custom ordering', 'woocommerce' ); ?></option>
416
																			<option value="name" <?php selected( $att_orderby, 'name' ); ?>><?php _e( 'Name', 'woocommerce' ); ?></option>
417
																			<option value="name_num" <?php selected( $att_orderby, 'name_num' ); ?>><?php _e( 'Name (numeric)', 'woocommerce' ); ?></option>
418
																			<option value="id" <?php selected( $att_orderby, 'id' ); ?>><?php _e( 'Term ID', 'woocommerce' ); ?></option>
419
																	</select>
420
																	<p class="description"><?php _e( 'Determines the sort order of the terms on the frontend shop product pages. If using custom ordering, you can drag and drop the terms in this attribute.', 'woocommerce' ); ?></p>
421
															</td>
422
													</tr>
423
											</tbody>
424
									</table>
425
									<p class="submit"><input type="submit" name="save_attribute" id="submit" class="button-primary" value="<?php esc_attr_e( 'Update', 'woocommerce' ); ?>"></p>
426
									<?php wp_nonce_field( 'woocommerce-save-attribute_' . $edit ); ?>
427
							</form>
428
					<?php } ?>
429
			</div>
430
			<?php
431
	}
432
433
	/**
434
	 * Add Attribute admin panel.
435
	 *
436
	 * Shows the interface for adding new attributes.
437
	 */
438
	public static function add_attribute() {
439
		wp_enqueue_media();
440
			?>
441
			<div class="wrap woocommerce">
442
					<div class="icon32 icon32-attributes" id="icon-woocommerce"><br/></div>
443
					<h1><?php _e( 'Attributes', 'woocommerce' ); ?></h1>
444
					<br class="clear" />
445
					<div id="col-container">
446
							<div id="col-right">
447
									<div class="col-wrap">
448
											<table class="widefat attributes-table wp-list-table ui-sortable" style="width:100%">
449
													<thead>
450
															<tr>
451
																	<th scope="col"><?php _e( 'Image', 'woocommerce' ); ?></th>
452
																	<th scope="col"><?php _e( 'Name', 'woocommerce' ); ?></th>
453
																	<th scope="col"><?php _e( 'Slug', 'woocommerce' ); ?></th>
454
																	<th scope="col"><?php _e( 'Type', 'woocommerce' ); ?></th>
455
																	<th scope="col"><?php _e( 'Order by', 'woocommerce' ); ?></th>
456
																	<th scope="col" colspan="2"><?php _e( 'Terms', 'woocommerce' ); ?></th>
457
															</tr>
458
													</thead>
459
													<tbody>
460
															<?php
461
																	if ( $attribute_taxonomies = wc_get_attribute_taxonomies() ) :
462
																			foreach ( $attribute_taxonomies as $tax ) :
463
																					?><tr>
464
																							<td>
465
																								<?php
466
																								$thumbnail_id = $tax->attribute_thumbnail_id;
467
468
																								if ( $thumbnail_id ) {
469
																										$image = wp_get_attachment_thumb_url( $thumbnail_id );
470
																								} else {
471
																										$image = wc_placeholder_img_src();
472
																								}
473
																								echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr__( 'Thumbnail', 'woocommerce' ) . '" class="wp-post-image" height="48" width="48" />';
474
																								?>
475
																							</td>
476
																							<td>
477
																									<strong><a href="edit-tags.php?taxonomy=<?php echo esc_html( wc_attribute_taxonomy_name( $tax->attribute_name ) ); ?>&amp;post_type=product"><?php echo esc_html( $tax->attribute_label ); ?></a></strong>
478
479
																									<div class="row-actions"><span class="edit"><a href="<?php echo esc_url( add_query_arg( 'edit', $tax->attribute_id, 'edit.php?post_type=product&amp;page=product_attributes_ext' ) ); ?>"><?php _e( 'Edit', 'woocommerce' ); ?></a> | </span><span class="delete"><a class="delete" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'delete', $tax->attribute_id, 'edit.php?post_type=product&amp;page=product_attributes_ext' ), 'woocommerce-delete-attribute_' . $tax->attribute_id ) ); ?>"><?php _e( 'Delete', 'woocommerce' ); ?></a></span></div>
480
																							</td>
481
																							<td><?php echo esc_html( $tax->attribute_name ); ?></td>
482
																							<td><?php echo esc_html( ucfirst( $tax->attribute_type ) ); ?> <?php echo $tax->attribute_public ? '(' . __( 'Public', 'woocommerce' ) . ')' : ''; ?></td>
483
																							<td><?php
484
																									switch ( $tax->attribute_orderby ) {
485
																											case 'name' :
486
																													_e( 'Name', 'woocommerce' );
487
																											break;
488
																											case 'name_num' :
489
																													_e( 'Name (numeric)', 'woocommerce' );
490
																											break;
491
																											case 'id' :
492
																													_e( 'Term ID', 'woocommerce' );
493
																											break;
494
																											default:
495
																													_e( 'Custom ordering', 'woocommerce' );
496
																											break;
497
																									}
498
																							?></td>
499
																							<td class="attribute-terms"><?php
500
																									$taxonomy = wc_attribute_taxonomy_name( $tax->attribute_name );
501
502
																									if ( taxonomy_exists( $taxonomy ) ) {
503
																											$terms = get_terms( $taxonomy, 'hide_empty=0' );
504
505 View Code Duplication
																											switch ( $tax->attribute_orderby ) {
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...
506
																													case 'name_num' :
507
																															usort( $terms, '_wc_get_product_terms_name_num_usort_callback' );
508
																													break;
509
																													case 'parent' :
510
																															usort( $terms, '_wc_get_product_terms_parent_usort_callback' );
511
																													break;
512
																											}
513
514
																											$terms_string = implode( ', ', wp_list_pluck( $terms, 'name' ) );
515
																											if ( $terms_string ) {
516
																													echo $terms_string;
517
																											} else {
518
																													echo '<span class="na">&ndash;</span>';
519
																											}
520
																									} else {
521
																											echo '<span class="na">&ndash;</span>';
522
																									}
523
																							?></td>
524
																							<td class="attribute-actions"><a href="edit-tags.php?taxonomy=<?php echo esc_html( wc_attribute_taxonomy_name( $tax->attribute_name ) ); ?>&amp;post_type=product" class="button alignright tips configure-terms" data-tip="<?php esc_attr_e( 'Configure terms', 'woocommerce' ); ?>"><?php _e( 'Configure terms', 'woocommerce' ); ?></a></td>
525
																					</tr><?php
526
																			endforeach;
527
																	else :
528
																			?><tr><td colspan="6"><?php _e( 'No attributes currently exist.', 'woocommerce' ) ?></td></tr><?php
529
																	endif;
530
															?>
531
													</tbody>
532
											</table>
533
									</div>
534
							</div>
535
							<div id="col-left">
536
									<div class="col-wrap">
537
											<div class="form-wrap">
538
													<h2><?php _e( 'Add New Attribute', 'woocommerce' ); ?></h2>
539
													<p><?php _e( 'Attributes let you define extra product data, such as size or colour. You can use these attributes in the shop sidebar using the "layered nav" widgets. Please note: you cannot rename an attribute later on.', 'woocommerce' ); ?></p>
540
													<form action="edit.php?post_type=product&amp;page=product_attributes" method="post">
541
															<div class="form-field">
542
																	<label for="attribute_label"><?php _e( 'Name', 'woocommerce' ); ?></label>
543
																	<input name="attribute_label" id="attribute_label" type="text" value="" />
544
																	<p class="description"><?php _e( 'Name for the attribute (shown on the front-end).', 'woocommerce' ); ?></p>
545
															</div>
546
547
															<div class="form-field">
548
																	<label for="attribute_name"><?php _e( 'Slug', 'woocommerce' ); ?></label>
549
																	<input name="attribute_name" id="attribute_name" type="text" value="" maxlength="28" />
550
																	<p class="description"><?php _e( 'Unique slug/reference for the attribute; must be shorter than 28 characters.', 'woocommerce' ); ?></p>
551
															</div>
552
553
															<div class="form-field">
554
																	<label for="attribute_description"><?php _e( 'Description', 'woocommerce' ); ?></label>
555
																	<textarea name="attribute_description" id="attribute_description" value="" rows="4"></textarea>
556
																	<p class="description"><?php _e( 'Description for the attribute, optional.', 'woocommerce' ); ?></p>
557
															</div>
558
559
															<div class="form-field term-thumbnail-wrap">
560
											            <label><?php _e( 'Attribute Graphic', 'woocommerce' ); ?></label>
561
											            <div id="attribute_thumbnail" style="float: left; margin-right: 10px;"><img src="<?php echo esc_url( wc_placeholder_img_src() ); ?>" width="60px" height="60px" /></div>
562
											            <div style="line-height: 60px;">
563
											                <input type="hidden" id="attribute_thumbnail_id" name="attribute_thumbnail_id" />
564
											                <button type="button" class="upload_image_button button"><?php _e( 'Upload/Add image', 'woocommerce' ); ?></button>
565
											                <button type="button" class="remove_image_button button"><?php _e( 'Remove image', 'woocommerce' ); ?></button>
566
											            </div>
567
											            <script type="text/javascript">
568
569
											                // Only show the "remove image" button when needed
570
											                if ( ! jQuery( '#attribute_thumbnail_id' ).val() ) {
571
											                    jQuery( '.remove_image_button' ).hide();
572
											                }
573
574
											                // Uploading files
575
											                var file_frame;
576
577
											                jQuery( document ).on( 'click', '.upload_image_button', function( event ) {
578
579
											                    event.preventDefault();
580
581
											                    // If the media frame already exists, reopen it.
582
											                    if ( file_frame ) {
583
											                        file_frame.open();
584
											                        return;
585
											                    }
586
587
											                    // Create the media frame.
588
											                    file_frame = wp.media.frames.downloadable_file = wp.media({
589
											                        title: '<?php _e( "Choose an image", "woocommerce" ); ?>',
590
											                        button: {
591
											                            text: '<?php _e( "Use image", "woocommerce" ); ?>'
592
											                        },
593
											                        multiple: false
594
											                    });
595
596
											                    // When an image is selected, run a callback.
597
											                    file_frame.on( 'select', function() {
598
											                        var attachment = file_frame.state().get( 'selection' ).first().toJSON();
599
600
											                        jQuery( '#attribute_thumbnail_id' ).val( attachment.id );
601
											                        jQuery( '#attribute_thumbnail' ).find( 'img' ).attr( 'src', attachment.thumbnail.url );
602
											                        jQuery( '.remove_image_button' ).show();
603
											                    });
604
605
											                    // Finally, open the modal.
606
											                    file_frame.open();
607
											                });
608
609
											                jQuery( document ).on( 'click', '.remove_image_button', function() {
610
											                    jQuery( '#attribute_thumbnail' ).find( 'img' ).attr( 'src', '<?php echo esc_js( wc_placeholder_img_src() ); ?>' );
611
											                    jQuery( '#attribute_thumbnail_id' ).val( '' );
612
											                    jQuery( '.remove_image_button' ).hide();
613
											                    return false;
614
											                });
615
616
											                jQuery( document ).ajaxComplete( function( event, request, options ) {
617
											                    if ( request && 4 === request.readyState && 200 === request.status
618
											                        && options.data && 0 <= options.data.indexOf( 'action=add-tag' ) ) {
619
620
											                        var res = wpAjax.parseAjaxResponse( request.responseXML, 'ajax-response' );
621
											                        if ( ! res || res.errors ) {
622
											                            return;
623
											                        }
624
											                        // Clear Thumbnail fields on submit
625
											                        jQuery( '#attribute_thumbnail' ).find( 'img' ).attr( 'src', '<?php echo esc_js( wc_placeholder_img_src() ); ?>' );
626
											                        jQuery( '#attribute_thumbnail_id' ).val( '' );
627
											                        jQuery( '.remove_image_button' ).hide();
628
											                        // Clear Display type field on submit
629
											                        jQuery( '#display_type' ).val( '' );
630
											                        return;
631
											                    }
632
											                } );
633
634
											            </script>
635
											            <div class="clear"></div>
636
											        </div>
637
638
															<div class="form-field">
639
																	<label for="attribute_public"><input name="attribute_public" id="attribute_public" type="checkbox" value="1" /> <?php _e( 'Enable Archives?', 'woocommerce' ); ?></label>
640
641
																	<p class="description"><?php _e( 'Enable this if you want this attribute to have product archives in your store.', 'woocommerce' ); ?></p>
642
															</div>
643
644
															<div class="form-field">
645
																	<label for="attribute_type"><?php _e( 'Type', 'woocommerce' ); ?></label>
646
																	<select name="attribute_type" id="attribute_type">
647
																			<?php foreach ( wc_get_attribute_types() as $key => $value ) : ?>
648
																					<option value="<?php echo esc_attr( $key ); ?>"><?php echo esc_attr( $value ); ?></option>
649
																			<?php endforeach; ?>
650
651
																			<?php
652
653
																					/**
654
																					 * Deprecated action in favor of product_attributes_type_selector filter.
655
																					 *
656
																					 * @deprecated 2.4.0
657
																					 */
658
																					do_action( 'woocommerce_admin_attribute_types' );
659
																			?>
660
																	</select>
661
																	<p class="description"><?php _e( 'Determines how you select attributes for products. Under admin panel -> products -> product data -> attributes -> values, <strong>Text</strong> allows manual entry whereas <strong>select</strong> allows pre-configured terms in a drop-down list.', 'woocommerce' ); ?></p>
662
															</div>
663
664
															<div class="form-field">
665
																	<label for="attribute_orderby"><?php _e( 'Default sort order', 'woocommerce' ); ?></label>
666
																	<select name="attribute_orderby" id="attribute_orderby">
667
																			<option value="menu_order"><?php _e( 'Custom ordering', 'woocommerce' ); ?></option>
668
																			<option value="name"><?php _e( 'Name', 'woocommerce' ); ?></option>
669
																			<option value="name_num"><?php _e( 'Name (numeric)', 'woocommerce' ); ?></option>
670
																			<option value="id"><?php _e( 'Term ID', 'woocommerce' ); ?></option>
671
																	</select>
672
																	<p class="description"><?php _e( 'Determines the sort order of the terms on the frontend shop product pages. If using custom ordering, you can drag and drop the terms in this attribute.', 'woocommerce' ); ?></p>
673
															</div>
674
675
															<p class="submit"><input type="submit" name="add_new_attribute" id="submit" class="button button-primary" value="<?php esc_attr_e( 'Add Attribute', 'woocommerce' ); ?>"></p>
676
															<?php wp_nonce_field( 'woocommerce-add-new_attribute' ); ?>
677
													</form>
678
											</div>
679
									</div>
680
							</div>
681
					</div>
682
					<script type="text/javascript">
683
					/* <![CDATA[ */
684
685
							jQuery( 'a.delete' ).click( function() {
686
									if ( window.confirm( '<?php _e( "Are you sure you want to delete this attribute?", "woocommerce" ); ?>' ) ) {
687
											return true;
688
									}
689
									return false;
690
							});
691
692
					/* ]]> */
693
					</script>
694
			</div>
695
			<?php
696
	}
697
698
}
699