PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 8.9.3
WooCommerce v8.9.3
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 1 year ago importers 1 year ago list-tables 1 year ago marketplace-suggestions 1 year ago meta-boxes 1 year ago notes 1 year ago plugin-updates 1 year ago reports 1 year ago settings 1 year ago views 1 year ago class-wc-admin-addons.php 1 year ago class-wc-admin-api-keys-table-list.php 1 year ago class-wc-admin-api-keys.php 1 year ago class-wc-admin-assets.php 1 year ago class-wc-admin-attributes.php 1 year ago class-wc-admin-customize.php 1 year ago class-wc-admin-dashboard-setup.php 1 year ago class-wc-admin-dashboard.php 1 year ago class-wc-admin-duplicate-product.php 1 year ago class-wc-admin-exporters.php 1 year ago class-wc-admin-help.php 1 year ago class-wc-admin-importers.php 1 year ago class-wc-admin-log-table-list.php 1 year ago class-wc-admin-marketplace-promotions.php 1 year ago class-wc-admin-menus.php 1 year ago class-wc-admin-meta-boxes.php 1 year ago class-wc-admin-notices.php 1 year ago class-wc-admin-permalink-settings.php 1 year ago class-wc-admin-pointers.php 1 year ago class-wc-admin-post-types.php 1 year ago class-wc-admin-profile.php 1 year ago class-wc-admin-reports.php 1 year ago class-wc-admin-settings.php 1 year ago class-wc-admin-setup-wizard.php 1 year ago class-wc-admin-status.php 1 year ago class-wc-admin-taxonomies.php 1 year ago class-wc-admin-upload-downloadable-product.php 1 year ago class-wc-admin-webhooks-table-list.php 1 year ago class-wc-admin-webhooks.php 1 year ago class-wc-admin.php 1 year ago wc-admin-functions.php 1 year ago wc-meta-box-functions.php 1 year ago
class-wc-admin-attributes.php
511 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 }
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 </div>
288 <?php
289 }
290
291 /**
292 * Add Attribute admin panel.
293 *
294 * Shows the interface for adding new attributes.
295 */
296 public static function add_attribute() {
297 ?>
298 <div class="wrap woocommerce">
299 <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
300
301 <br class="clear" />
302 <div id="col-container">
303 <div id="col-right">
304 <div class="col-wrap">
305 <table class="widefat attributes-table wp-list-table ui-sortable" style="width:100%">
306 <thead>
307 <tr>
308 <th scope="col"><?php esc_html_e( 'Name', 'woocommerce' ); ?></th>
309 <th scope="col"><?php esc_html_e( 'Slug', 'woocommerce' ); ?></th>
310 <?php if ( wc_has_custom_attribute_types() ) : ?>
311 <th scope="col"><?php esc_html_e( 'Type', 'woocommerce' ); ?></th>
312 <?php endif; ?>
313 <th scope="col"><?php esc_html_e( 'Order by', 'woocommerce' ); ?></th>
314 <th scope="col"><?php esc_html_e( 'Terms', 'woocommerce' ); ?></th>
315 </tr>
316 </thead>
317 <tbody>
318 <?php
319 $attribute_taxonomies = wc_get_attribute_taxonomies();
320 if ( $attribute_taxonomies ) {
321 /**
322 * Filters the maximum number of terms that will be displayed for each taxonomy in the Attributes page.
323 *
324 * @param int @default_max_terms_to_display Default value.
325 * @returns int Actual value to use, may be zero.
326 *
327 * @since 6.9.0
328 */
329 $max_terms_to_display = apply_filters( 'woocommerce_max_terms_displayed_in_attributes_page', 100 );
330 foreach ( $attribute_taxonomies as $tax ) :
331 ?>
332 <tr>
333 <td>
334 <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>
335
336 <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>
337 </td>
338 <td><?php echo esc_html( $tax->attribute_name ); ?></td>
339 <?php if ( wc_has_custom_attribute_types() ) : ?>
340 <td><?php echo esc_html( wc_get_attribute_type_label( $tax->attribute_type ) ); ?> <?php echo $tax->attribute_public ? esc_html__( '(Public)', 'woocommerce' ) : ''; ?></td>
341 <?php endif; ?>
342 <td>
343 <?php
344 switch ( $tax->attribute_orderby ) {
345 case 'name':
346 esc_html_e( 'Name', 'woocommerce' );
347 break;
348 case 'name_num':
349 esc_html_e( 'Name (numeric)', 'woocommerce' );
350 break;
351 case 'id':
352 esc_html_e( 'Term ID', 'woocommerce' );
353 break;
354 default:
355 esc_html_e( 'Custom ordering', 'woocommerce' );
356 break;
357 }
358 ?>
359 </td>
360 <td class="attribute-terms">
361 <?php
362 $taxonomy = wc_attribute_taxonomy_name( $tax->attribute_name );
363
364 if ( taxonomy_exists( $taxonomy ) ) {
365 $total_count = (int) get_terms(
366 array(
367 'taxonomy' => $taxonomy,
368 'fields' => 'count',
369 'hide_empty' => false,
370 )
371 );
372 if ( 0 === $total_count ) {
373 echo '<span class="na">&ndash;</span>';
374 } elseif ( $max_terms_to_display > 0 ) {
375 $terms = get_terms(
376 array(
377 'taxonomy' => $taxonomy,
378 'number' => $max_terms_to_display,
379 'fields' => 'names',
380 'hide_empty' => false,
381 )
382 );
383 $terms_string = implode( ', ', $terms );
384 if ( $total_count > $max_terms_to_display ) {
385 $remaining = $total_count - $max_terms_to_display;
386 /* translators: 1: Comma-separated terms list, 2: how many terms are hidden */
387 $terms_string = sprintf( __( '%1$s... (%2$s more)', 'woocommerce' ), $terms_string, $remaining );
388 }
389 echo esc_html( $terms_string );
390 } elseif ( 1 === $total_count ) {
391 echo esc_html( __( '1 term', 'woocommerce' ) );
392 } else {
393 /* translators: %s: Total count of terms available for the attribute */
394 echo esc_html( sprintf( __( '%s terms', 'woocommerce' ), $total_count ) );
395 }
396 } else {
397 echo '<span class="na">&ndash;</span><br />';
398 }
399 ?>
400 <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>
401 </td>
402 </tr>
403 <?php
404 endforeach;
405 } else {
406 ?>
407 <tr>
408 <td colspan="6"><?php esc_html_e( 'No attributes currently exist.', 'woocommerce' ); ?></td>
409 </tr>
410 <?php
411 }
412 ?>
413 </tbody>
414 </table>
415 </div>
416 </div>
417 <div id="col-left">
418 <div class="col-wrap">
419 <div class="form-wrap">
420 <h2><?php esc_html_e( 'Add new attribute', 'woocommerce' ); ?></h2>
421 <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>
422 <form action="edit.php?post_type=product&amp;page=product_attributes" method="post">
423 <?php do_action( 'woocommerce_before_add_attribute_fields' ); ?>
424
425 <div class="form-field">
426 <label for="attribute_label"><?php esc_html_e( 'Name', 'woocommerce' ); ?></label>
427 <input name="attribute_label" id="attribute_label" type="text" value="" />
428 <p class="description"><?php esc_html_e( 'Name for the attribute (shown on the front-end).', 'woocommerce' ); ?></p>
429 </div>
430
431 <div class="form-field">
432 <label for="attribute_name"><?php esc_html_e( 'Slug', 'woocommerce' ); ?></label>
433 <input name="attribute_name" id="attribute_name" type="text" value="" maxlength="28" />
434 <p class="description"><?php esc_html_e( 'Unique slug/reference for the attribute; must be no more than 28 characters.', 'woocommerce' ); ?></p>
435 </div>
436
437 <div class="form-field">
438 <label for="attribute_public"><input name="attribute_public" id="attribute_public" type="checkbox" value="1" /> <?php esc_html_e( 'Enable Archives?', 'woocommerce' ); ?></label>
439
440 <p class="description"><?php esc_html_e( 'Enable this if you want this attribute to have product archives in your store.', 'woocommerce' ); ?></p>
441 </div>
442
443 <?php
444 /**
445 * Attribute types can change the way attributes are displayed on the frontend and admin.
446 *
447 * By Default WooCommerce only includes the `select` type. Others can be added with the
448 * `product_attributes_type_selector` filter. If there is only the default type registered,
449 * this setting will be hidden.
450 */
451 if ( wc_has_custom_attribute_types() ) {
452 ?>
453 <div class="form-field">
454 <label for="attribute_type"><?php esc_html_e( 'Type', 'woocommerce' ); ?></label>
455 <select name="attribute_type" id="attribute_type">
456 <?php foreach ( wc_get_attribute_types() as $key => $value ) : ?>
457 <option value="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $value ); ?></option>
458 <?php endforeach; ?>
459 <?php
460 /**
461 * Deprecated action in favor of product_attributes_type_selector filter.
462 *
463 * @todo Remove in 4.0.0
464 * @deprecated 2.4.0
465 */
466 do_action( 'woocommerce_admin_attribute_types' );
467 ?>
468 </select>
469 <p class="description"><?php esc_html_e( "Determines how this attribute's values are displayed.", 'woocommerce' ); ?></p>
470 </div>
471 <?php
472 }
473 ?>
474
475 <div class="form-field">
476 <label for="attribute_orderby"><?php esc_html_e( 'Default sort order', 'woocommerce' ); ?></label>
477 <select name="attribute_orderby" id="attribute_orderby">
478 <option value="menu_order"><?php esc_html_e( 'Custom ordering', 'woocommerce' ); ?></option>
479 <option value="name"><?php esc_html_e( 'Name', 'woocommerce' ); ?></option>
480 <option value="name_num"><?php esc_html_e( 'Name (numeric)', 'woocommerce' ); ?></option>
481 <option value="id"><?php esc_html_e( 'Term ID', 'woocommerce' ); ?></option>
482 </select>
483 <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>
484 </div>
485
486 <?php do_action( 'woocommerce_after_add_attribute_fields' ); ?>
487
488 <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>
489 <?php wp_nonce_field( 'woocommerce-add-new_attribute' ); ?>
490 </form>
491 </div>
492 </div>
493 </div>
494 </div>
495 <script type="text/javascript">
496 /* <![CDATA[ */
497
498 jQuery( 'a.delete' ).on( 'click', function() {
499 if ( window.confirm( '<?php esc_html_e( 'Are you sure you want to delete this attribute?', 'woocommerce' ); ?>' ) ) {
500 return true;
501 }
502 return false;
503 });
504
505 /* ]]> */
506 </script>
507 </div>
508 <?php
509 }
510 }
511