PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 10.9.4
WooCommerce v10.9.4
10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / includes / admin / class-wc-admin-attributes.php
woocommerce / includes / admin Last commit date
helper 2 months ago importers 1 year ago list-tables 1 month ago marketplace-suggestions 11 months ago meta-boxes 1 month ago notes 2 months ago plugin-updates 2 years ago reports 3 months ago settings 6 days ago views 1 month ago class-wc-admin-addons.php 9 months ago class-wc-admin-api-keys-table-list.php 2 years ago class-wc-admin-api-keys.php 11 months ago class-wc-admin-assets.php 1 month ago class-wc-admin-attributes.php 1 month ago class-wc-admin-brands.php 4 months ago class-wc-admin-customize.php 5 years ago class-wc-admin-dashboard-setup.php 1 month ago class-wc-admin-dashboard.php 4 months ago class-wc-admin-duplicate-product.php 5 months ago class-wc-admin-exporters.php 1 year ago class-wc-admin-help.php 2 years ago class-wc-admin-importers.php 11 months ago class-wc-admin-log-table-list.php 4 months ago class-wc-admin-marketplace-promotions.php 4 months ago class-wc-admin-menus.php 1 month ago class-wc-admin-meta-boxes.php 1 month ago class-wc-admin-notices.php 1 month ago class-wc-admin-permalink-settings.php 5 years ago class-wc-admin-pointers.php 3 years ago class-wc-admin-post-types.php 1 year ago class-wc-admin-profile.php 1 year ago class-wc-admin-reports.php 4 months ago class-wc-admin-settings.php 3 months ago class-wc-admin-setup-wizard.php 1 month ago class-wc-admin-status.php 1 year ago class-wc-admin-taxonomies.php 1 month ago class-wc-admin-upload-downloadable-product.php 2 years ago class-wc-admin-webhooks-table-list.php 1 month ago class-wc-admin-webhooks.php 1 month ago class-wc-admin.php 3 months ago wc-admin-functions.php 7 months ago wc-meta-box-functions.php 1 year ago woocommerce-legacy-reports.php 1 year ago
class-wc-admin-attributes.php
514 lines
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 "Filter Products by Attribute" widget.
6 *
7 * @package WooCommerce\Admin
8 * @version 2.3.0
9 */
10
11 defined( 'ABSPATH' ) || exit;
12
13 /**
14 * WC_Admin_Attributes Class.
15 */
16 class WC_Admin_Attributes {
17
18 /**
19 * Edited attribute ID.
20 *
21 * @var int
22 */
23 private static $edited_attribute_id;
24
25 /**
26 * Handles output of the attributes page in admin.
27 *
28 * Shows the created attributes and lets you add new ones or edit existing ones.
29 * The added attributes are stored in the database and can be used for layered navigation.
30 */
31 public static function output() {
32 $result = '';
33 $action = '';
34
35 // Action to perform: add, edit, delete or none.
36 if ( ! empty( $_POST['add_new_attribute'] ) ) { // WPCS: CSRF ok.
37 $action = 'add';
38 } elseif ( ! empty( $_POST['save_attribute'] ) && ! empty( $_GET['edit'] ) ) { // WPCS: CSRF ok.
39 $action = 'edit';
40 } elseif ( ! empty( $_GET['delete'] ) ) {
41 $action = 'delete';
42 }
43
44 switch ( $action ) {
45 case 'add':
46 $result = self::process_add_attribute();
47 break;
48 case 'edit':
49 $result = self::process_edit_attribute();
50 break;
51 case 'delete':
52 $result = self::process_delete_attribute();
53 break;
54 }
55
56 if ( is_wp_error( $result ) ) {
57 echo '<div id="woocommerce_errors" class="error"><p>' . wp_kses_post( $result->get_error_message() ) . '</p></div>';
58 }
59
60 // Show admin interface.
61 if ( ! empty( $_GET['edit'] ) ) {
62 self::edit_attribute();
63 } else {
64 self::add_attribute();
65 }
66 }
67
68 /**
69 * Get and sanitize posted attribute data.
70 *
71 * @return array
72 */
73 private static function get_posted_attribute() {
74 $attribute = array(
75 'attribute_label' => isset( $_POST['attribute_label'] ) ? wc_clean( wp_unslash( $_POST['attribute_label'] ) ) : '', // WPCS: input var ok, CSRF ok.
76 'attribute_name' => isset( $_POST['attribute_name'] ) ? wc_sanitize_taxonomy_name( wp_unslash( $_POST['attribute_name'] ) ) : '', // WPCS: input var ok, CSRF ok, sanitization ok.
77 'attribute_type' => isset( $_POST['attribute_type'] ) ? wc_clean( wp_unslash( $_POST['attribute_type'] ) ) : 'select', // WPCS: input var ok, CSRF ok.
78 'attribute_orderby' => isset( $_POST['attribute_orderby'] ) ? wc_clean( wp_unslash( $_POST['attribute_orderby'] ) ) : '', // WPCS: input var ok, CSRF ok.
79 'attribute_public' => isset( $_POST['attribute_public'] ) ? 1 : 0, // WPCS: input var ok, CSRF ok.
80 );
81
82 if ( empty( $attribute['attribute_type'] ) ) {
83 $attribute['attribute_type'] = 'select';
84 }
85 if ( empty( $attribute['attribute_label'] ) ) {
86 $attribute['attribute_label'] = ucfirst( $attribute['attribute_name'] );
87 }
88 if ( empty( $attribute['attribute_name'] ) ) {
89 $attribute['attribute_name'] = wc_sanitize_taxonomy_name( $attribute['attribute_label'] );
90 }
91
92 return $attribute;
93 }
94
95 /**
96 * Add an attribute.
97 *
98 * @return bool|WP_Error
99 */
100 private static function process_add_attribute() {
101 check_admin_referer( 'woocommerce-add-new_attribute' );
102
103 $attribute = self::get_posted_attribute();
104 $args = array(
105 'name' => $attribute['attribute_label'],
106 'slug' => $attribute['attribute_name'],
107 'type' => $attribute['attribute_type'],
108 'order_by' => $attribute['attribute_orderby'],
109 'has_archives' => $attribute['attribute_public'],
110 );
111
112 $id = wc_create_attribute( $args );
113
114 if ( is_wp_error( $id ) ) {
115 return $id;
116 }
117
118 return true;
119 }
120
121 /**
122 * Edit an attribute.
123 *
124 * @return bool|WP_Error
125 */
126 private static function process_edit_attribute() {
127 $attribute_id = isset( $_GET['edit'] ) ? absint( $_GET['edit'] ) : 0;
128 check_admin_referer( 'woocommerce-save-attribute_' . $attribute_id );
129
130 $attribute = self::get_posted_attribute();
131 $args = array(
132 'name' => $attribute['attribute_label'],
133 'slug' => $attribute['attribute_name'],
134 'type' => $attribute['attribute_type'],
135 'order_by' => $attribute['attribute_orderby'],
136 'has_archives' => $attribute['attribute_public'],
137 );
138
139 $id = wc_update_attribute( $attribute_id, $args );
140
141 if ( is_wp_error( $id ) ) {
142 return $id;
143 }
144
145 self::$edited_attribute_id = $id;
146
147 return true;
148 }
149
150 /**
151 * Delete an attribute.
152 *
153 * @return bool
154 */
155 private static function process_delete_attribute() {
156 $attribute_id = isset( $_GET['delete'] ) ? absint( $_GET['delete'] ) : 0;
157 check_admin_referer( 'woocommerce-delete-attribute_' . $attribute_id );
158
159 return wc_delete_attribute( $attribute_id );
160 }
161
162 /**
163 * Edit Attribute admin panel.
164 *
165 * Shows the interface for changing an attributes type between select and text.
166 */
167 public static function edit_attribute() {
168 global $wpdb;
169
170 $edit = isset( $_GET['edit'] ) ? absint( $_GET['edit'] ) : 0;
171
172 $attribute_to_edit = $wpdb->get_row(
173 $wpdb->prepare(
174 "
175 SELECT attribute_type, attribute_label, attribute_name, attribute_orderby, attribute_public
176 FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = %d
177 ",
178 $edit
179 )
180 );
181
182 ?>
183 <div class="wrap woocommerce">
184 <h1><?php esc_html_e( 'Edit attribute', 'woocommerce' ); ?></h1>
185
186 <?php
187 if ( ! $attribute_to_edit ) {
188 echo '<div id="woocommerce_errors" class="error"><p>' . esc_html__( 'Error: non-existing attribute ID.', 'woocommerce' ) . '</p></div>';
189 } else {
190 if ( self::$edited_attribute_id > 0 ) {
191 echo '<div id="message" class="updated"><p>' . esc_html__( 'Attribute updated successfully', 'woocommerce' ) . '</p><p><a href="' . esc_url( admin_url( 'edit.php?post_type=product&amp;page=product_attributes' ) ) . '">' . esc_html__( 'Back to Attributes', 'woocommerce' ) . '</a></p></div>';
192 self::$edited_attribute_id = null;
193 }
194 $att_type = $attribute_to_edit->attribute_type;
195 $att_label = format_to_edit( $attribute_to_edit->attribute_label );
196 $att_name = $attribute_to_edit->attribute_name;
197 $att_orderby = $attribute_to_edit->attribute_orderby;
198 $att_public = $attribute_to_edit->attribute_public;
199 ?>
200 <form action="edit.php?post_type=product&amp;page=product_attributes&amp;edit=<?php echo absint( $edit ); ?>" method="post">
201 <table class="form-table">
202 <tbody>
203 <?php do_action( 'woocommerce_before_edit_attribute_fields' ); ?>
204 <tr class="form-field form-required">
205 <th scope="row" valign="top">
206 <label for="attribute_label"><?php esc_html_e( 'Name', 'woocommerce' ); ?></label>
207 </th>
208 <td>
209 <input name="attribute_label" id="attribute_label" type="text" value="<?php echo esc_attr( $att_label ); ?>" />
210 <p class="description"><?php esc_html_e( 'Name for the attribute (shown on the front-end).', 'woocommerce' ); ?></p>
211 </td>
212 </tr>
213 <tr class="form-field form-required">
214 <th scope="row" valign="top">
215 <label for="attribute_name"><?php esc_html_e( 'Slug', 'woocommerce' ); ?></label>
216 </th>
217 <td>
218 <input name="attribute_name" id="attribute_name" type="text" value="<?php echo esc_attr( $att_name ); ?>" maxlength="28" />
219 <p class="description"><?php esc_html_e( 'Unique slug/reference for the attribute; must be no more than 28 characters.', 'woocommerce' ); ?></p>
220 </td>
221 </tr>
222 <tr class="form-field form-required">
223 <th scope="row" valign="top">
224 <label for="attribute_public"><?php esc_html_e( 'Enable archives?', 'woocommerce' ); ?></label>
225 </th>
226 <td>
227 <input name="attribute_public" id="attribute_public" type="checkbox" value="1" <?php checked( $att_public, 1 ); ?> />
228 <p class="description"><?php esc_html_e( 'Enable this if you want this attribute to have product archives in your store.', 'woocommerce' ); ?></p>
229 </td>
230 </tr>
231 <?php
232 /**
233 * Attribute types can change the way attributes are displayed on the frontend and admin.
234 *
235 * By Default WooCommerce only includes the `select` type. Others can be added with the
236 * `product_attributes_type_selector` filter. If there is only the default type registered,
237 * this setting will be hidden.
238 */
239 if ( wc_has_custom_attribute_types() ) {
240 ?>
241 <tr class="form-field form-required">
242 <th scope="row" valign="top">
243 <label for="attribute_type"><?php esc_html_e( 'Type', 'woocommerce' ); ?></label>
244 </th>
245 <td>
246 <select name="attribute_type" id="attribute_type">
247 <?php foreach ( wc_get_attribute_types() as $key => $value ) : ?>
248 <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $att_type, $key ); ?>><?php echo esc_html( $value ); ?></option>
249 <?php endforeach; ?>
250 <?php
251 /**
252 * Deprecated action in favor of product_attributes_type_selector filter.
253 *
254 * @todo Remove in 4.0.0
255 * @deprecated 2.4.0
256 */
257 do_action( 'woocommerce_admin_attribute_types' );
258 ?>
259 </select>
260 <p class="description"><?php esc_html_e( "Determines how this attribute's values are displayed.", 'woocommerce' ); ?></p>
261 </td>
262 </tr>
263 <?php
264 }//end if
265 ?>
266 <tr class="form-field form-required">
267 <th scope="row" valign="top">
268 <label for="attribute_orderby"><?php esc_html_e( 'Default sort order', 'woocommerce' ); ?></label>
269 </th>
270 <td>
271 <select name="attribute_orderby" id="attribute_orderby">
272 <option value="menu_order" <?php selected( $att_orderby, 'menu_order' ); ?>><?php esc_html_e( 'Custom ordering', 'woocommerce' ); ?></option>
273 <option value="name" <?php selected( $att_orderby, 'name' ); ?>><?php esc_html_e( 'Name', 'woocommerce' ); ?></option>
274 <option value="name_num" <?php selected( $att_orderby, 'name_num' ); ?>><?php esc_html_e( 'Name (numeric)', 'woocommerce' ); ?></option>
275 <option value="id" <?php selected( $att_orderby, 'id' ); ?>><?php esc_html_e( 'Term ID', 'woocommerce' ); ?></option>
276 </select>
277 <p class="description"><?php esc_html_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>
278 </td>
279 </tr>
280 <?php do_action( 'woocommerce_after_edit_attribute_fields' ); ?>
281 </tbody>
282 </table>
283 <p class="submit"><button type="submit" name="save_attribute" id="submit" class="button-primary" value="<?php esc_attr_e( 'Update', 'woocommerce' ); ?>"><?php esc_html_e( 'Update', 'woocommerce' ); ?></button></p>
284 <?php wp_nonce_field( 'woocommerce-save-attribute_' . $edit ); ?>
285 </form>
286 <?php
287 }//end if
288 ?>
289 </div>
290 <?php
291 }
292
293 /**
294 * Add Attribute admin panel.
295 *
296 * Shows the interface for adding new attributes.
297 */
298 public static function add_attribute() {
299 ?>
300 <div class="wrap woocommerce">
301 <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
302
303 <br class="clear" />
304 <div id="col-container">
305 <div id="col-right">
306 <div class="col-wrap">
307 <table class="widefat attributes-table wp-list-table ui-sortable" style="width:100%">
308 <thead>
309 <tr>
310 <th scope="col"><?php esc_html_e( 'Name', 'woocommerce' ); ?></th>
311 <th scope="col"><?php esc_html_e( 'Slug', 'woocommerce' ); ?></th>
312 <?php if ( wc_has_custom_attribute_types() ) : ?>
313 <th scope="col"><?php esc_html_e( 'Type', 'woocommerce' ); ?></th>
314 <?php endif; ?>
315 <th scope="col"><?php esc_html_e( 'Order by', 'woocommerce' ); ?></th>
316 <th scope="col"><?php esc_html_e( 'Terms', 'woocommerce' ); ?></th>
317 </tr>
318 </thead>
319 <tbody>
320 <?php
321 $attribute_taxonomies = wc_get_attribute_taxonomies();
322 if ( $attribute_taxonomies ) {
323 /**
324 * Filters the maximum number of terms that will be displayed for each taxonomy in the Attributes page.
325 *
326 * @param int @default_max_terms_to_display Default value.
327 * @returns int Actual value to use, may be zero.
328 *
329 * @since 6.9.0
330 */
331 $max_terms_to_display = apply_filters( 'woocommerce_max_terms_displayed_in_attributes_page', 100 );
332 foreach ( $attribute_taxonomies as $tax ) :
333 ?>
334 <tr>
335 <td>
336 <strong><a href="edit-tags.php?taxonomy=<?php echo esc_attr( wc_attribute_taxonomy_name( $tax->attribute_name ) ); ?>&amp;post_type=product"><?php echo esc_html( $tax->attribute_label ); ?></a></strong>
337
338 <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 esc_html_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 esc_html_e( 'Delete', 'woocommerce' ); ?></a></span></div>
339 </td>
340 <td><?php echo esc_html( $tax->attribute_name ); ?></td>
341 <?php if ( wc_has_custom_attribute_types() ) : ?>
342 <td><?php echo esc_html( wc_get_attribute_type_label( $tax->attribute_type ) ); ?> <?php echo $tax->attribute_public ? esc_html__( '(Public)', 'woocommerce' ) : ''; ?></td>
343 <?php endif; ?>
344 <td>
345 <?php
346 switch ( $tax->attribute_orderby ) {
347 case 'name':
348 esc_html_e( 'Name', 'woocommerce' );
349 break;
350 case 'name_num':
351 esc_html_e( 'Name (numeric)', 'woocommerce' );
352 break;
353 case 'id':
354 esc_html_e( 'Term ID', 'woocommerce' );
355 break;
356 default:
357 esc_html_e( 'Custom ordering', 'woocommerce' );
358 break;
359 }
360 ?>
361 </td>
362 <td class="attribute-terms">
363 <?php
364 $taxonomy = wc_attribute_taxonomy_name( $tax->attribute_name );
365
366 if ( taxonomy_exists( $taxonomy ) ) {
367 $total_count = (int) get_terms(
368 array(
369 'taxonomy' => $taxonomy,
370 'fields' => 'count',
371 'hide_empty' => false,
372 )
373 );
374 if ( 0 === $total_count ) {
375 echo '<span class="na">&ndash;</span>';
376 } elseif ( $max_terms_to_display > 0 ) {
377 $terms = get_terms(
378 array(
379 'taxonomy' => $taxonomy,
380 'number' => $max_terms_to_display,
381 'fields' => 'names',
382 'hide_empty' => false,
383 )
384 );
385 $terms_string = implode( ', ', $terms );
386 if ( $total_count > $max_terms_to_display ) {
387 $remaining = $total_count - $max_terms_to_display;
388 /* translators: 1: Comma-separated terms list, 2: how many terms are hidden */
389 $terms_string = sprintf( __( '%1$s... (%2$s more)', 'woocommerce' ), $terms_string, $remaining );
390 }
391 echo esc_html( $terms_string );
392 } elseif ( 1 === $total_count ) {
393 echo esc_html( __( '1 term', 'woocommerce' ) );
394 } else {
395 /* translators: %s: Total count of terms available for the attribute */
396 echo esc_html( sprintf( __( '%s terms', 'woocommerce' ), $total_count ) );
397 }//end if
398 } else {
399 echo '<span class="na">&ndash;</span><br />';
400 }//end if
401 ?>
402 <br /><a href="edit-tags.php?taxonomy=<?php echo esc_attr( wc_attribute_taxonomy_name( $tax->attribute_name ) ); ?>&amp;post_type=product" class="configure-terms"><?php esc_html_e( 'Configure terms', 'woocommerce' ); ?></a>
403 </td>
404 </tr>
405 <?php
406 endforeach;
407 } else {
408 $column_count = wc_has_custom_attribute_types() ? '5' : '4';
409 ?>
410 <tr>
411 <td colspan="<?php echo esc_attr( $column_count ); ?>"><?php esc_html_e( 'No attributes currently exist.', 'woocommerce' ); ?></td>
412 </tr>
413 <?php
414 }//end if
415 ?>
416 </tbody>
417 </table>
418 </div>
419 </div>
420 <div id="col-left">
421 <div class="col-wrap">
422 <div class="form-wrap">
423 <h2><?php esc_html_e( 'Add new attribute', 'woocommerce' ); ?></h2>
424 <p><?php esc_html_e( 'Attributes let you define extra product data, such as size or color. You can use these attributes in the shop sidebar using the "layered nav" widgets.', 'woocommerce' ); ?></p>
425 <form action="edit.php?post_type=product&amp;page=product_attributes" method="post">
426 <?php do_action( 'woocommerce_before_add_attribute_fields' ); ?>
427
428 <div class="form-field">
429 <label for="attribute_label"><?php esc_html_e( 'Name', 'woocommerce' ); ?></label>
430 <input name="attribute_label" id="attribute_label" type="text" value="" />
431 <p class="description"><?php esc_html_e( 'Name for the attribute (shown on the front-end).', 'woocommerce' ); ?></p>
432 </div>
433
434 <div class="form-field">
435 <label for="attribute_name"><?php esc_html_e( 'Slug', 'woocommerce' ); ?></label>
436 <input name="attribute_name" id="attribute_name" type="text" value="" maxlength="28" />
437 <p class="description"><?php esc_html_e( 'Unique slug/reference for the attribute; must be no more than 28 characters.', 'woocommerce' ); ?></p>
438 </div>
439
440 <div class="form-field">
441 <label for="attribute_public"><input name="attribute_public" id="attribute_public" type="checkbox" value="1" /> <?php esc_html_e( 'Enable Archives?', 'woocommerce' ); ?></label>
442
443 <p class="description"><?php esc_html_e( 'Enable this if you want this attribute to have product archives in your store.', 'woocommerce' ); ?></p>
444 </div>
445
446 <?php
447 /**
448 * Attribute types can change the way attributes are displayed on the frontend and admin.
449 *
450 * By Default WooCommerce only includes the `select` type. Others can be added with the
451 * `product_attributes_type_selector` filter. If there is only the default type registered,
452 * this setting will be hidden.
453 */
454 if ( wc_has_custom_attribute_types() ) {
455 ?>
456 <div class="form-field">
457 <label for="attribute_type"><?php esc_html_e( 'Type', 'woocommerce' ); ?></label>
458 <select name="attribute_type" id="attribute_type">
459 <?php foreach ( wc_get_attribute_types() as $key => $value ) : ?>
460 <option value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $value ); ?></option>
461 <?php endforeach; ?>
462 <?php
463 /**
464 * Deprecated action in favor of product_attributes_type_selector filter.
465 *
466 * @todo Remove in 4.0.0
467 * @deprecated 2.4.0
468 */
469 do_action( 'woocommerce_admin_attribute_types' );
470 ?>
471 </select>
472 <p class="description"><?php esc_html_e( "Determines how this attribute's values are displayed.", 'woocommerce' ); ?></p>
473 </div>
474 <?php
475 }//end if
476 ?>
477
478 <div class="form-field">
479 <label for="attribute_orderby"><?php esc_html_e( 'Default sort order', 'woocommerce' ); ?></label>
480 <select name="attribute_orderby" id="attribute_orderby">
481 <option value="menu_order"><?php esc_html_e( 'Custom ordering', 'woocommerce' ); ?></option>
482 <option value="name"><?php esc_html_e( 'Name', 'woocommerce' ); ?></option>
483 <option value="name_num"><?php esc_html_e( 'Name (numeric)', 'woocommerce' ); ?></option>
484 <option value="id"><?php esc_html_e( 'Term ID', 'woocommerce' ); ?></option>
485 </select>
486 <p class="description"><?php esc_html_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>
487 </div>
488
489 <?php do_action( 'woocommerce_after_add_attribute_fields' ); ?>
490
491 <p class="submit"><button type="submit" name="add_new_attribute" id="submit" class="button button-primary" value="<?php esc_attr_e( 'Add attribute', 'woocommerce' ); ?>"><?php esc_html_e( 'Add attribute', 'woocommerce' ); ?></button></p>
492 <?php wp_nonce_field( 'woocommerce-add-new_attribute' ); ?>
493 </form>
494 </div>
495 </div>
496 </div>
497 </div>
498 <script type="text/javascript">
499 /* <![CDATA[ */
500
501 jQuery( 'a.delete' ).on( 'click', function() {
502 if ( window.confirm( '<?php esc_html_e( 'Are you sure you want to delete this attribute?', 'woocommerce' ); ?>' ) ) {
503 return true;
504 }
505 return false;
506 });
507
508 /* ]]> */
509 </script>
510 </div>
511 <?php
512 }
513 }
514