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

WC_Admin_Attributes::edit_attribute()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 101
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
dl 0
loc 101
rs 8.2857
c 0
b 0
f 0
eloc 50
nc 2
nop 0

How to fix   Long Method   

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;
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'] ) ) : '',
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

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