# 📈 Factorize Catalog

> Every list in the store, sorted like a merchandiser would.
>
> **Suite identity:** icon 📈 · accent `#e8b04b` · part of the [Factorize suite](../README-FACTORIZE.md)

## What it does

Drives the storefront's default product ordering with a single precomputed rank meta (`_et_rank`) that encodes in-stock status, weekly sales, lifetime sales, and percent-off into one integer, so listings sort by what matters (in stock first, proven sellers up, deepest discount wins) with a plain indexed query. It adds "Best deals" (default) and "Most popular" catalog sorts, widens site search to match SKUs (with exact-SKU redirect straight to the product), sinks out-of-stock items to the bottom of every catalog sort and search, renders "x sold this week" badges, auto-picks Featured products from an industry-popularity score (`et_popularity`), and replaces numbered pagination with infinite scroll on shop, category, and search archives.

## Configuration

| Key | Default | Effect |
| --- | --- | --- |
| `featured_limit` | `4` | How many products `empire_tools_refresh_featured()` selects as Featured when called without an explicit limit. |

Configuration is read through `empire_catalog_config( $key )`. Values come from the `factorize-catalog_options` option (an array stored via `update_option`; the legacy `empire-catalog-ranking_options` option is still honored as a fallback) merged over the defaults above, and the merged array then passes through the `factorize-catalog_config` filter, so either mechanism can override any key. Defaults are identical to the values previously hardcoded in the theme.

## Works with

- **WooCommerce** (required for anything useful): products, orders, `wc_get_orders()`, `wc_get_product_id_by_sku()`, the `wc_product_meta_lookup` table, and Woo's catalog ordering hooks. All Woo calls are either hooked to Woo actions or guarded with `function_exists()`, so the plugin is inert without WooCommerce.
- **Calls `empire_tools_discount_pct()`** (ships with Factorize Essentials / the theme's `inc/woocommerce.php`) inside `empire_tools_calculate_rank()`. This plugin is a declared dependency of the others and expects that function to exist; keep Factorize Essentials active alongside it.
- **Called by siblings**: Factorize Auctions' hourly tick calls `empire_tools_refresh_featured()`, and the popularity bootstrap (`popularity-seed.php`) seeds `et_popularity`, which powers the Featured picker and the "Most popular" sort here. Without those, Featured falls back to the best-ranked deals and "Most popular" simply sorts whatever `et_popularity` values exist.
- `empire_tools_rebuild_ranks()` is available for a one-time backfill after imports: `wp eval "empire_tools_rebuild_ranks();"`.

## Hooks it registers

- `woocommerce_update_product`, `woocommerce_new_product` — recompute `_et_rank` on save/create.
- `woocommerce_product_set_stock` — recompute rank on stock change.
- `woocommerce_order_status_changed` — recompute rank for ordered products, bust the weekly-sales cache.
- `woocommerce_catalog_orderby` — add "Best deals" / "Most popular", remove Woo's popularity sort.
- `woocommerce_default_catalog_orderby` (priority 20) — default to "Best deals".
- `woocommerce_get_catalog_ordering_args` — map the two custom sorts to their meta keys.
- `posts_clauses` (priority 20) — search: join SKU meta, order exact-SKU hit first, then in-stock, then relevance.
- `posts_clauses` (priority 30) — every catalog query: in-stock items first via `wc_product_meta_lookup`.
- `posts_search` — splice a SKU LIKE match inside WordPress's search group.
- `template_redirect` — exact SKU search redirects to the product.
- `woocommerce_after_shop_loop_item_title` (6), `woocommerce_single_product_summary` (11) — "x sold this week" badge.
- `save_post_product` (priority 20) — seed `et_popularity` when missing.
- `wp_enqueue_scripts` — enqueue `empire-tools-infinite-scroll` on shop / product taxonomy / search pages.

## Publishing

`readme.txt` (WordPress.org listing format) and `QUICKSTART.md` (5-minute setup guide) live alongside this file and carry the public-facing copy for the WordPress.org listing.
