=== Demfilz Fields and Filters ===
Contributors: demfilz
Tags: custom fields, filter, product filter, faceted search, woocommerce
Requires at least: 6.2
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.0.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Add custom fields to pages, posts and products, then let visitors filter content by fields, tags, taxonomies and WooCommerce attributes.

== Description ==

Demfilz Fields and Filters does two jobs that belong together:

1. **Custom fields** - define your own fields (text, number, select, radio, checkbox, date, URL, text area) and attach them to pages, posts, products or any public post type. Editors fill them in from a clean meta box on the edit screen.
2. **Front-end filters** - drop the `[dfaf_filters]` shortcode on any page to show a filter form plus a results grid. Visitors can filter by your custom fields, by tags, categories or any taxonomy, by WooCommerce global attributes (pa_*) and even by custom per-product attributes.

= Filtering features =

* Filter by any filterable custom field: choice dropdowns, multi-select checkbox lists, numeric min/max ranges, date ranges, yes/no toggles and keyword matching.
* Filter by any public taxonomy: tags, categories, product categories, product tags and WooCommerce global attributes.
* Filter by custom (per-product) WooCommerce attributes - the plugin indexes them into fast, queryable meta on every product save.
* Optional keyword search box and sort dropdown (newest, title, price for products).
* Paginated, responsive results grid (1-4 columns) with thumbnail, title, price and excerpt.
* Split mode: place the filter form on one page and point it at another page or your shop archive.
* Optional archive integration: apply active filters to blog, category, tag and shop archive pages.
* Shortcode builder in the admin so you never have to remember parameters.

= Works with or without WooCommerce =

WooCommerce is optional. Without it you can still define fields for posts and pages and filter them. With WooCommerce active, product support, price sorting and attribute filters light up automatically.

= For developers =

Field types live in a registry that the plugin itself uses for every built-in type. Register additional types through the `dfaf_field_types` filter, adjust queries with `dfaf_query_args`, decorate option labels with `dfaf_option_label` and customise result cards with `dfaf_result_card_html`.

= Pro version =

Everything above is free and fully functional. For sites that want more, [Fields and Filters Pro](https://demfilz.com/fields-and-filters) is a separate add-on plugin ($19.95 per year) that adds:

* Instant AJAX filtering - results update as visitors change filters, no page reload, shareable URLs.
* Live result counts on every filter option.
* Colour swatch field type with visual swatch filter controls.
* Star rating field type with "and up" filtering.
* Pill-style filter controls.

== External services ==

This plugin does not connect to any external service. No data leaves your site.

== Installation ==

1. Install and activate the plugin.
2. Go to **Fields & Filters -> Fields** and define your custom fields.
3. Edit a page, post or product and fill in the new fields in the **Custom fields** meta box.
4. Go to **Fields & Filters -> Filters**, build your shortcode and paste it into any page.
5. (WooCommerce stores) open **Fields & Filters -> Settings** and click **Rebuild attribute index** once so existing custom product attributes become filterable.

== Frequently Asked Questions ==

= How do I filter by WooCommerce global attributes? =

Global attributes are taxonomies named pa_something. Add them to the shortcode, for example: `[dfaf_filters post_type="product" taxonomies="pa_colour,pa_size"]`.

= How do I filter by custom (per-product) attributes? =

Use the attributes parameter, for example: `[dfaf_filters post_type="product" attributes="material"]`. The plugin indexes custom attribute values automatically when a product is saved; run **Rebuild attribute index** in Settings to index products that existed before the plugin was installed.

= Can visitors pick more than one value? =

Yes. List the field keys or taxonomies in the multi parameter and they render as checkbox lists, for example: `[dfaf_filters post_type="product" taxonomies="pa_colour" multi="pa_colour"]`.

= Can I put the filter form in a sidebar and the results on the shop page? =

Yes. Use `[dfaf_filters post_type="product" form_only="1" action="/shop/"]` for the form, then enable **Archive filtering** in Settings so the shop archive applies the filters.

= Does it slow my site down? =

No. Values are stored as normal post meta and queried with standard meta and taxonomy queries. Custom product attributes are pre-indexed on save specifically so filtering never has to parse serialized data.

= Where is the data stored? =

Field definitions are a single option; values are post meta prefixed with _dfaf_. On uninstall the plugin removes its options, and also the post meta if you opted in on the Settings page.

= Is there a Pro version? =

Yes. Fields and Filters Pro is a separate add-on plugin ($19.95 per year) that adds instant AJAX filtering, live result counts on filter options, colour swatch and star rating field types, and pill-style controls. See https://demfilz.com/fields-and-filters. The free plugin is complete on its own and never locks features.

== Screenshots ==

1. Defining custom fields in the admin.
2. The Custom fields meta box on a product.
3. The front-end filter form and results grid.
4. The shortcode builder.
5. Settings.

== Changelog ==

= 1.0.1 =
* Security hardening: all markup returned by field-type render callbacks and public filters is now sanitised with wp_kses before output (shortcode results, filter controls and the edit-screen meta box).

= 1.0.0 =
* Initial release: custom fields for pages, posts and products; front-end filtering by fields, tags, taxonomies, WooCommerce global attributes and custom product attributes; shortcode builder; archive integration; attribute index.

== Upgrade Notice ==

= 1.0.1 =
Output escaping hardening.

= 1.0.0 =
Initial release.
