PHPackages                             eighteen73/universal-product-sort - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. eighteen73/universal-product-sort

ActiveWordpress-plugin[Utility &amp; Helpers](/categories/utility)

eighteen73/universal-product-sort
=================================

Per-category WooCommerce product sorting plugin.

v0.1.0(1mo ago)05[5 PRs](https://github.com/eighteen73/universal-product-sort/pulls)GPL-2.0-or-laterPHPPHP &gt;=7.4CI passing

Since Apr 17Pushed yesterdayCompare

[ Source](https://github.com/eighteen73/universal-product-sort)[ Packagist](https://packagist.org/packages/eighteen73/universal-product-sort)[ RSS](/packages/eighteen73-universal-product-sort/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (1)Versions (9)Used By (0)

Universal Product Sort
======================

[](#universal-product-sort)

Category-specific product ordering for [WooCommerce](https://woocommerce.com/). 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
------------

[](#requirements)

- **WordPress** 6.8 or higher.
- **PHP** 7.4 or higher.
- **WooCommerce** — the plugin targets WooCommerce products (`product`), the `product_cat` taxonomy, and Woo’s “Sorting” list behaviour in admin. WooCommerce should be active before relying on this plugin.

What it does
------------

[](#what-it-does)

### Admin: per-category manual order

[](#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 `orderby` value is `menu_order title`)
- **Category filter:** a single **product category** selected in the URL (`product_cat=`)

…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

[](#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

[](#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_cat` query var, or a `tax_query` that includes `product_cat`), and
- The request has **not** set an explicit `orderby` query parameter — in that case the plugin only applies custom order if the resolved orderby is effectively “menu order” style (`menu_order`, `menu_order title`, or `post__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

[](#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
-----------

[](#development)

- **PHP** namespace: `Eighteen73\UniversalProductSort` — PSR-4 autoload from `includes/classes/`.
- **Composer scripts:** `composer run lint` / `composer run format` (PHPCS / PHPCBF).
- **npm scripts:** `lint`, `format`, `build`, etc. — see `package.json`.

License
-------

[](#license)

GPL-2.0-or-later.

###  Health Score

35

—

LowBetter than 77% of packages

Maintenance95

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity29

Early-stage or recently created project

 Bus Factor1

Top contributor holds 72.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

53d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/73229?v=4)[Brett Mason ](/maintainers/brettsmason)[@brettsmason](https://github.com/brettsmason)

---

Top Contributors

[![brettsmason](https://avatars.githubusercontent.com/u/73229?v=4)](https://github.com/brettsmason "brettsmason (8 commits)")[![DanielHudson2](https://avatars.githubusercontent.com/u/35522603?v=4)](https://github.com/DanielHudson2 "DanielHudson2 (3 commits)")

### Embed Badge

![Health badge](/badges/eighteen73-universal-product-sort/health.svg)

```
[![Health](https://phpackages.com/badges/eighteen73-universal-product-sort/health.svg)](https://phpackages.com/packages/eighteen73-universal-product-sort)
```

###  Alternatives

[flyeralarm/php-code-validator

A custom coding standard for FLYERALARM

2227.1k6](/packages/flyeralarm-php-code-validator)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
