eighteen73 / universal-product-sort
Per-category WooCommerce product sorting plugin.
Package info
github.com/eighteen73/universal-product-sort
Type:wordpress-plugin
pkg:composer/eighteen73/universal-product-sort
Requires
- php: >=7.4
Requires (Dev)
This package is auto-updated.
Last update: 2026-04-20 10:43:12 UTC
README
Category-specific product ordering for WooCommerce. Each product category can have its own drag-and-drop order in the admin; that order is applied on the storefront when customers browse that category (subject to the rules below).
Requirements
- WordPress 6.8 or higher.
- PHP 7.4 or higher.
- WooCommerce — the plugin targets WooCommerce products (
product), theproduct_cattaxonomy, and Woo’s “Sorting” list behaviour in admin. WooCommerce should be active before relying on this plugin.
What it does
Admin: per-category manual order
WooCommerce’s default product ordering UI uses a single menu_order on each product. This plugin stores a separate ordered list of product IDs per category in term meta, so “position 3 in Category A” does not have to match “position 3 in Category B.”
When you are on the Products list with:
- Screen: Products (
edit-product) - Order: “Custom ordering” / sort by Menu order (the
orderbyvalue ismenu_order title) - Category filter: a single product category selected in the URL (
product_cat=<slug>)
…the plugin replaces Woo’s default ordering script with **assets/js/admin-product-ordering.js**. Drag-and-drop sends an AJAX request (action: universal_product_sort_ordering) that:
- Verifies capability (
edit_products) and a dedicated nonce. - Ensures the product belongs to the filtered category.
- Recomputes the category’s product order and saves it.
The response includes updated menu_order values for the list UI so the table stays consistent with the new sequence.
Where the order is stored
- Term meta key:
_universal_product_sort_category_order - Value: array of product IDs in display order for that category.
The repository (CategoryOrderRepository) reconciles stored IDs with products actually in the category: unknown IDs are dropped; products in the category but missing from the saved list are appended (after stored IDs), using Woo’s default menu_order title query as the basis for “current” category membership.
Frontend: when custom order applies
CategoryQueryOrdering hooks pre_get_posts and posts_clauses to apply the saved order when:
- The query is for WooCommerce products and relates to
product_cat(taxonomy archive,product_catquery var, or atax_querythat includesproduct_cat), and - The request has not set an explicit
orderbyquery parameter — in that case the plugin only applies custom order if the resolved orderby is effectively “menu order” style (menu_order,menu_order title, orpost__in).
Ordering uses SQL FIELD() on the resolved ID list, with products not in the list sorted after, then menu_order and post_title as tie-breakers.
Internal lookups (e.g. loading all product IDs in a category) set a query flag so the plugin does not recurse into its own ordering logic.
Caches
Resolved order per category is cached in the object cache (wp_cache_*) under the group universal_product_sort. Caches are invalidated when product–category relationships change, when categories are created/edited/deleted, and when order is saved.
Development
- PHP namespace:
Eighteen73\UniversalProductSort— PSR-4 autoload fromincludes/classes/. - Composer scripts:
composer run lint/composer run format(PHPCS / PHPCBF). - npm scripts:
lint,format,build, etc. — seepackage.json.
License
GPL-2.0-or-later.