=== Fast Filter for WooCommerce ===
Contributors: ssiinnaa
Tags: woocommerce, product filter, elementor, faceted search, filter
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 8.2
Tested PHP: 8.2 – 8.5
Stable tag: 3.0.1
License: GPLv2 or later

Fast, accurate, faceted product filter built for Elementor Pro Loop Grid and WooCommerce archives.

== Description ==

* **Accordion UI** – category tree (hierarchical), size sliders (length / width), shape, colour swatches, production type, material. Any source can be added as a list, swatch or range filter from the settings page.
* **Reads every kind of product data** – global attributes (taxonomies), custom per-product attributes (the text ones on the product edit screen), and shipping dimensions / weight (including variations) through a small product index that is kept fresh on every product save.
* **Full-height layout** by default (the Elementor popup scrolls); optional inner-scroll layout with sticky buttons.
* **Instant Apply** – the result page is prefetched (or prerendered) in the background while the user is still choosing.
* **OR inside a filter, AND between filters.** Counts next to every option are live (facet counts respect all *other* filters) so users never pick an empty combination.
* **Apply reloads the page** with clean URL parameters (`?ffwc_color=red,navy&ffwc_length=80-200`) and filters every Elementor Loop Grid / Posts widget whose *Query ID* matches, plus the main WooCommerce product query.
* **Category aware** – on a category page the category is pre-selected; choosing a sub-category (or another category) navigates to that category URL so the main route stays in sync. Multiple categories inside one branch stay on the branch URL with `ffwc_cat=`; categories from different branches go to the shop page.
* **Fast** – all counts are grouped SQL, cached in transients and auto-invalidated whenever products or terms change.
* **Dynamic** – terms, categories, colours and min/max values are read from the store, never hardcoded.

== Setup ==

1. Activate the plugin (requires WooCommerce; Elementor is optional).
2. WooCommerce → Fast Filter: check the auto-detected attribute mapping (length, width, shape, colour, production type, material) and adjust if needed.
3. In Elementor, add the **Fast Filter** widget (category "Fast Filter") inside a Popup or any container — or use the `[fast_filter]` shortcode.
4. In the Loop Grid widget: Query → **Query ID** = `fast_filter` (configurable).
5. Optional: Products → Attributes → Colour → edit a term → "Swatch colour" to override the auto-detected colour.

== Shortcode ==

`[fast_filter filters="cat,length,width,shape,color,production_type,material" nav="auto" counts="1" chips="1" title="Filters"]`

== Developer hooks ==

* `fast_filter_query_tax_query` – filter the tax_query clauses applied to product queries.
* `fast_filter_facet_tax_query` / `fast_filter_facet_base_where` – adjust facet counting SQL.
* `fast_filter_js_config` – adjust the front-end configuration.
* JS event `fastfilter:apply` on `document` (detail: `{ url, state }`) fires right before navigation.
* `elementor/query/{query_id}` is used for Loop Grid integration; `woocommerce_product_query` for the main query.

== Screenshots ==

1. Sidebar layout: category tree, size sliders (from shipping dimensions), colour swatches and live counts next to a filtered product grid.
2. Popup layout (Elementor popup / off-canvas): OR inside a filter, AND between filters; the Apply button always shows the exact number of matching products.
3. Mobile: inner-scroll layout with sticky Reset / Apply buttons.
4. Settings page (WooCommerce → Fast Filter): filters are auto-detected from your product data and can be re-ordered, renamed or added.

== Changelog ==

= 3.0.1 =
* WordPress.org review: every option, transient, cron hook, query var and URL parameter now uses the `ffwc_` prefix (URLs read `?ffwc_color=red`), `Requires Plugins: woocommerce` header added, and the settings option declares an array sanitize callback.

= 3.0.0 =
* Requires PHP 8.2+ (tested on PHP 8.5). Code base modernised: strict types, enums, readonly value objects, first-class callables.
* Smart queries: one id-set query per request feeds every unselected facet (one grouped query for all flat taxonomies, one per category tree, one for custom attributes); the product count is derived from the same id set.
* All filter term lists are stored in a single cache entry, so a page load does one cache read instead of one per filter.
* Facet cache entries are keyed by the effective clauses, so the live-count request and the resulting page share the same entry.

= 2.2.2 =
* Fewer per-request queries: no table check / status lookups on normal page loads, category link map cached, no id precompute for the empty selection.

= 2.2.1 =
* Index table: prefix indexes + InnoDB so creation no longer fails with "Specified key was too long" on utf8mb4/MyISAM hosts.
* No translation calls before `init` (WP 6.7 _load_textdomain_just_in_time notice).

= 2.2.0 =
* Matching product ids are precomputed while the shopper is choosing, so the Loop Grid / shop query after Apply is a plain "ID IN (…)".
* Live counts use a light early-exit endpoint (/?ffwc_facets=1) instead of the REST API; REST stays as fallback.
* Cache warming: sitemap of filter URLs for cache crawlers (/?ffwc_sitemap=1) and an optional built-in WP-Cron warmer.

= 2.1.0 =
* Shipping dimensions / weight are read directly from product meta (variations included) — no index table required.
* Attribute terms with no products are listed greyed out instead of hidden.
* Index table creation is verified; failures are shown in admin with the DB error. Index self-builds after plugin updates (no activation needed) and continues without WP-Cron.

= 1.1.0 =
* Product index: custom (per-product) attributes and shipping dimensions/weight, incl. variations, as filter sources.
* Auto-detection of sources in English and Persian; "Reset filters to auto-detected defaults".
* Full-height layout by default; inner-scroll layout optional.
* Prefetch / prerender of the result page for near-instant Apply.
* Fixes: Reset kept the old parameters; Apply was disabled when the count was 0; Elementor popup re-initialisation.

= 1.0.0 =
* Initial release.
