Changeset 3341829
- Timestamp:
- 08/08/2025 09:23:21 PM (8 months ago)
- Location:
- bulk-sort-attributes-for-woocommerce
- Files:
-
- 3 added
- 1 deleted
- 2 edited
-
tags/1.2 (added)
-
tags/1.2/bulk-sort-attributes-for-woocommerce.php (added)
-
tags/1.2/readme.txt (added)
-
trunk/assets (deleted)
-
trunk/bulk-sort-attributes-for-woocommerce.php (modified) (4 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
bulk-sort-attributes-for-woocommerce/trunk/bulk-sort-attributes-for-woocommerce.php
r3063975 r3341829 3 3 Plugin Name: Bulk Sort Attributes for WooCommerce 4 4 Description: Bulk sort WooCommerce attributes when they are too numerous for custom sorting by hand. 5 Version: 1. 1.55 Version: 1.2 6 6 Author: Inbound Horizons 7 7 Author URI: https://www.inboundhorizons.com 8 License: GPLv2 or later 9 Requires Plugins: woocommerce 8 10 */ 9 11 … … 25 27 26 28 private function __construct() { 27 add_action('woocommerce_init', array($this, 'InitHooks')); 28 } 29 30 public function InitHooks() { 31 32 // Set a hook for every attribute taxonomy 33 $attribute_taxonomies = wc_get_attribute_taxonomies(); 34 if (!empty($attribute_taxonomies)) { 35 foreach ($attribute_taxonomies as $attribute) { 36 add_action('views_edit-' . 'pa_' . $attribute->attribute_name, function() use ($attribute) { 37 $this->OutputSortingButtonsHtml($attribute); 38 }); 39 } 29 if (is_admin()) { 30 add_action('woocommerce_init', array($this, 'WooCommerceHooks')); 31 } 32 } 33 34 public function WooCommerceHooks() { 35 36 // Ensure that the user has permission to be here 37 if (!current_user_can('manage_product_terms') && !current_user_can('manage_woocommerce')) { 38 return; 39 } 40 41 // Get all attribute taxonomies 42 $attribute_taxonomies = wc_get_attribute_taxonomies(); 43 44 // Check to make sure the $attribute_taxonomies is an array 45 if (!empty($attribute_taxonomies) && is_array($attribute_taxonomies)) { 46 47 // Loop over the attributes 48 foreach ($attribute_taxonomies as $attribute) { 49 50 // Set a hook for every attribute taxonomy to display the sorting dropdown 51 add_filter('views_edit-' . 'pa_' . $attribute->attribute_name, function($views) use ($attribute) { 52 $this->OutputSortingButtonsHtml($attribute); 53 return $views; 54 }); 40 55 } 41 42 // Listen for AJAX trigger 43 add_action('wp_ajax_WBSA_SORT_ATTRIBUTES', array($this, 'AJAXCustomOrderWooAttributes')); 44 56 } 57 58 // Listen for POST data 59 add_action('admin_post_BSAFW_SORT_ATTRIBUTES', array($this, 'AJAX_CustomOrderWooCommerceAttributes')); 60 } 61 62 public function AJAX_CustomOrderWooCommerceAttributes() { 63 64 // Ensure that the user has permission to be here 65 if (!current_user_can('manage_product_terms') && !current_user_can('manage_woocommerce')) { 66 wp_die(esc_html__('Insufficient permissions.', 'bulk-sort-attributes-for-woocommerce'), 403); 67 } 68 69 // Validate the nonce 70 check_admin_referer('bsafw-sort-attributes', 'bsafw_nonce'); 71 72 // Get the redirect URL 73 $redirect_url = wp_get_referer(); 74 75 // Get and sanitize POSTed data 76 $taxonomy = isset($_POST['taxonomy']) ? sanitize_text_field(wp_unslash($_POST['taxonomy'])) : ''; 77 $bsafw_sorting = isset($_POST['bsafw_sorting']) ? sanitize_text_field(wp_unslash($_POST['bsafw_sorting'])) : ''; 78 79 // Split the POSTed data into a sort by name and direction 80 $sorting_array = explode(" ", $bsafw_sorting); 81 82 // Get the sort by and direction 83 $sort_by = isset($sorting_array[0]) ? strtolower($sorting_array[0]) : ''; 84 $direction = isset($sorting_array[1]) ? strtolower($sorting_array[1]) : ''; 85 86 // Sort the attribute terms 87 $this->CustomOrderWooAttributes($taxonomy, $sort_by, $direction); 88 89 wp_safe_redirect($redirect_url); 90 exit; 45 91 } 46 92 47 93 public function OutputSortingButtonsHtml($attribute) { 48 94 49 $nonce = wp_create_nonce('wbsa-sort-attributes'); 50 95 // Get information about the attribute 51 96 $att_orderby = $attribute->attribute_orderby; 52 97 $taxonomy = 'pa_' . $attribute->attribute_name; 53 98 54 $is_custom_order_by = ($att_orderby == 'menu_order'); 55 56 57 $select_disabled = 'disabled'; 58 $btn_disabled = 'button-disabled'; 59 $warning_disabled = ''; 60 if ($is_custom_order_by) { 61 $warning_disabled = 'display:none;'; 62 $btn_disabled = ''; 63 $select_disabled = ''; 64 } 65 66 echo ' 67 <div style="margin-top:5px;"> 68 <select id="wbsa_sorting" '.esc_attr($select_disabled).'> 69 <option value="" selected disabled>- Bulk Sort Attributes for WooCommerce -</option> 70 71 <optgroup label="Sort By: ID"> 72 <option value="id asc">ID - ASC</option> 73 <option value="id desc">ID - DESC</option> 74 </optgroup> 99 // Check if we can customize the ordering of attribute terms 100 $is_custom_ordering = ($att_orderby === 'menu_order'); 101 102 // Wrap everything in a <div> 103 echo '<div>'; 104 105 if ($is_custom_ordering) { 106 107 echo ' 108 <form method="post" action="'.esc_url(admin_url('admin-post.php')).'"> 109 '; 110 111 // Output the nonce field 112 wp_nonce_field('bsafw-sort-attributes', 'bsafw_nonce', true); 113 114 echo ' 115 <input type="hidden" name="action" value="BSAFW_SORT_ATTRIBUTES" /> 116 <input type="hidden" name="taxonomy" value="'.esc_attr($taxonomy).'" /> 75 117 76 <optgroup label="Sort By: Name"> 77 <option value="name asc">Name - ASC</option> 78 <option value="name desc">Name - DESC</option> 79 </optgroup> 80 81 <optgroup label="Sort By: Name (Numeric)"> 82 <option value="name_num asc">Name (Numeric) - ASC</option> 83 <option value="name_num desc">Name (Numeric) - DESC</option> 84 </optgroup> 85 </select> 86 87 <button type="button" class="button button-secondary wbsa '.esc_attr($btn_disabled).'"> 88 Bulk Sort Attributes 89 </button> 90 91 92 <b style="'.esc_attr($warning_disabled).'"><span class="dashicons dashicons-warning" style="line-height:1.5;" title="Please edit the attribute and change the default sort order to "Custom ordering""></span></b> 93 94 <span id="wbsa-spinner" class="dashicons dashicons-update" style="display:none; animation:wbsa-spin 2s linear infinite"></span> 95 </div> 96 97 <style> 98 @keyframes wbsa-spin { 99 0% { transform: rotate(0deg); } 100 100% { transform: rotate(360deg); } 101 } 102 </style> 103 104 105 <script> 106 107 jQuery(document).ready(function() { 108 jQuery(document).on("click", ".wbsa:not(.button-disabled)", function() { 109 110 var val = jQuery("#wbsa_sorting").val(); 111 112 if (val && (val != "")) { 113 114 var sort_direction = val.split(" "); 115 116 var sort = sort_direction[0]; 117 var direction = sort_direction[1]; 118 var taxonomy = "'.esc_html($taxonomy).'"; 119 120 var data = { 121 "action": "WBSA_SORT_ATTRIBUTES", 122 "sort": sort, 123 "direction": direction, 124 "taxonomy": taxonomy, 125 "nonce": "'.esc_attr($nonce).'", 126 }; 127 128 jQuery("#wbsa-spinner").show(); 129 jQuery.post(ajaxurl, data, function(response) { 130 location.reload(); // Reload the page 131 }); 132 133 } 134 else { 135 alert("Please select how to sort the attributes."); 136 jQuery("#wbsa_sorting").focus(); 137 } 138 139 }); 140 }); 141 142 </script> 143 144 '; 145 } 146 147 public function AJAXCustomOrderWooAttributes() { 148 $ok = 0; 149 150 151 $nonce_verified = wp_verify_nonce($_POST['nonce'], 'wbsa-sort-attributes'); 152 153 if ($nonce_verified) { 154 $ok = 1; 155 156 // Get and sanitize POSTed data 157 $sort = isset($_POST['sort']) ? sanitize_text_field($_POST['sort']) : ''; 158 $direction = isset($_POST['direction']) ? sanitize_text_field($_POST['direction']) : ''; 159 $taxonomy = isset($_POST['taxonomy']) ? sanitize_text_field($_POST['taxonomy']) : ''; 160 161 // Convert the strings to lower case 162 $sort = strtolower($sort); 163 $direction = strtolower($direction); 164 165 // Sort the attribute terms 166 $this->CustomOrderWooAttributes($taxonomy, $sort, $direction); 167 168 } 169 170 $json = array( 171 'ok' => $ok, 172 ); 173 174 header('Content-Type: application/json'); 175 echo json_encode($json); 176 wp_die(); // This is required to terminate immediately and return a proper response 177 } 178 179 public function CustomOrderWooAttributes($taxonomy, $sort, $direction = 'asc') { 180 181 $possible_sorts = array( 118 <select name="bsafw_sorting" required> 119 <option value="" selected disabled>- Bulk Sort Attributes for WooCommerce -</option> 120 121 <optgroup label="Sort By: ID"> 122 <option value="id asc">ID - ASC</option> 123 <option value="id desc">ID - DESC</option> 124 </optgroup> 125 126 <optgroup label="Sort By: Name"> 127 <option value="name asc">Name - ASC</option> 128 <option value="name desc">Name - DESC</option> 129 </optgroup> 130 131 <optgroup label="Sort By: Name (Numeric)"> 132 <option value="name_num asc">Name (Numeric) - ASC</option> 133 <option value="name_num desc">Name (Numeric) - DESC</option> 134 </optgroup> 135 </select> 136 137 <button type="submit" class="button button-secondary"> 138 Bulk Sort Attributes 139 </button> 140 </form> 141 '; 142 } 143 else { 144 echo ' 145 <div class="notice notice-warning is-dismissible inline"> 146 <p> 147 <strong>'.esc_html__('Bulk Sort Attributes is Unavailable', 'bulk-sort-attributes-for-woocommerce').'</strong>: 148 Edit this attribute and set the default sort order to <code>' . esc_html__('Custom ordering', 'bulk-sort-attributes-for-woocommerce') . '</code> to enable bulk sorting. 149 150 </p> 151 </div> 152 '; 153 } 154 155 // End the wrapping <div> 156 echo '</div>'; 157 } 158 159 public function CustomOrderWooAttributes($taxonomy, $sort = '', $direction = 'asc') { 160 161 // Normalize the sort and direction 162 $sort = strtolower($sort); 163 $direction = strtolower($direction); 164 165 // Define the white-listed sorts and directions 166 $valid_sorts = array( 182 167 'id', 183 168 'name', … … 185 170 ); 186 171 187 $ possible_sort_directions = array(172 $valid_sort_directions = array( 188 173 'asc', 189 174 'desc', 190 175 ); 191 176 192 193 194 // 1.) Get the terms in an array 177 // Check if the sort and direction are valid 178 if (in_array($sort, $valid_sorts, true) && in_array($direction, $valid_sort_directions, true)) { 179 180 // Ensure that the taxonomy is a product attribute 181 if (!taxonomy_exists($taxonomy) || strpos($taxonomy, 'pa_') !== 0) { 182 return; 183 } 184 185 // Get the terms in an array 195 186 $terms = get_terms(array( 196 187 'taxonomy' => $taxonomy, … … 198 189 )); 199 190 200 201 // 2.) Sort the array of terms202 203 if (in_array($sort, $possible_sorts) && in_array($direction, $possible_sort_directions)) {204 205 if ($sort == 'name') {206 if ($direction == 'desc') {207 usort($terms, function($a, $b) {208 return strcmp($b->name, $a->name);209 });191 // Check if the terms are valid 192 if (!is_wp_error($terms) && !empty($terms)) { 193 194 // Sort the attribute terms 195 usort($terms, function($a, $b) use($sort, $direction) { 196 197 // Default to assuming we are sorting by 'id' (term ID) 198 $comparator = (intval($a->term_id) < intval($b->term_id)) ? -1 : 1; 199 if (intval($a->term_id) === intval($b->term_id)) { 200 $comparator = 0; 210 201 } 211 else { // Assume 'asc' 212 usort($terms, function($a, $b) { 213 return strcmp($a->name, $b->name); 214 }); 202 203 if ($sort === 'name') { 204 $comparator = strcmp($a->name, $b->name); 215 205 } 206 else if ($sort === 'name_num') { 207 $comparator = (intval($a->name) < intval($b->name)) ? -1 : 1; 208 if (intval($a->name) === intval($b->name)) { 209 $comparator = 0; 210 } 211 } 212 213 // Return the results based on the direction 214 return ($direction === 'desc') ? -$comparator : $comparator; 215 }); 216 217 // Commit the new order to the database 218 foreach ($terms as $index => $term) { 219 $term_id = intval($term->term_id); 220 wc_set_term_order($term_id, $index, $taxonomy); 216 221 } 217 else if ($sort == 'name_num') {218 if ($direction == 'desc') {219 usort($terms, function($a, $b) {220 return intval($b->name) > intval($a->name);221 });222 }223 else { // Assume 'asc'224 usort($terms, function($a, $b) {225 return intval($a->name) > intval($b->name);226 });227 }228 }229 else { // Assume 'id'230 if ($direction == 'desc') {231 usort($terms, function($a, $b) {232 return intval($b->term_id) > intval($a->term_id);233 });234 }235 else { // Assume 'asc'236 usort($terms, function($a, $b) {237 return intval($a->term_id) > intval($b->term_id);238 });239 }240 }241 242 243 // 3.) Commit the new order to the database244 for ($i = 0; $i < count($terms); $i++) {245 $term_id = intval($terms[$i]->term_id);246 wc_set_term_order($term_id, $i, $taxonomy);247 }248 249 222 250 223 } 224 } 225 251 226 252 227 } -
bulk-sort-attributes-for-woocommerce/trunk/readme.txt
r3063975 r3341829 2 2 Contributors: inboundhorizons, cliffbailey 3 3 Plugin Name: Bulk Sort Attributes for WooCommerce 4 Tags: woocommerce, attribute, bulk, custom, sorting, order by, orderby4 Tags: woocommerce, attribute, bulk, sorting, order by 5 5 Requires at least: 3.3 6 Tested up to: 6. 57 Stable tag: 1. 1.56 Tested up to: 6.8 7 Stable tag: 1.2 8 8 Requires PHP: 5.4 9 9 License: GPLv2 or later … … 34 34 == Changelog == 35 35 36 = 1.1.5 - 034/03/2024 = 36 = 1.2 - 08/08/2025 = 37 * Refactored and tightened sanitation checks. 38 39 = 1.1.5 - 04/03/2024 = 37 40 * Added icon and banner 38 41 * Confirmed compatibility with WP v6.5
Note: See TracChangeset
for help on using the changeset viewer.