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:
Complex classes like WC_Admin_Attributes often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use WC_Admin_Attributes, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 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'", |
||
| 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&page=product_attributes&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 ) ); ?>&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&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&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">–</span>'; |
||
| 695 |