=== Multiple Category Selection Widget ===
Contributors: zackdesign
Donate link: https://zackdesign.biz
Tags: widget, category, post, subcategory, filter
Requires at least: 6.0
Tested up to: 6.9.1
Stable tag: 4.0.0
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Filter posts by selecting multiple categories using dropdown menus. Available as a widget, block, or shortcode.

== Description ==

Turn your WordPress post categories into a search powerhouse! This plugin gives you a set of dropdown menus based on parent categories and their sub-categories. Users select one sub-category per parent, and the plugin filters posts matching the selected combination.

**Available as:**

* **Gutenberg Block** — "Multi-Category Filter" in the block inserter (new in v4)
* **Classic Widget** — "Multi-Category Selection" in Appearance > Widgets
* **Shortcode** — `[mcsw]` on any page or post

**Features:**

* AND / OR category filtering — find posts matching ALL or ANY selected categories
* AJAX chained drilldown — selecting a parent dynamically loads its children
* Pretty permalink URLs (`/categories/3,5/search_type/and/order/title/`)
* Ordering by title or default
* Configurable blank search behavior
* Exclude specific categories
* Lightweight — no jQuery, no external dependencies
* Pagination support
* Display form above results on category pages (optional)

**Sample use case:**

Real estate — set up parent categories like "Bedrooms", "Bathrooms", "Price Range" with sub-categories beneath them. Users filter listings by selecting from each dropdown.

**Upgrading from v3.x:**

* PHP sessions have been removed entirely — the URL now carries all state, which means better compatibility with caching plugins, load balancers, and modern hosting
* jQuery has been replaced with vanilla JavaScript
* CSS classes have changed from `wpmcsw`/`wpmm` to BEM-style `mcsw-*` classes — update any custom CSS
* The old `select-chain.js` in the plugin root has been replaced by `js/select-chain.js`

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/`
2. Activate through the Plugins menu
3. Create parent categories with sub-categories beneath them
4. Add posts and assign them to the sub-categories

**As a block:**
In the block editor, search for "Multi-Category Filter" and add it.

**As a widget:**
Go to Appearance > Widgets and add "Multi-Category Selection" to a sidebar.

**As a shortcode:**
Add `[mcsw]` to any page or post. Configure the shortcode form settings under Settings > Multiple Category Selection.

**AJAX chaining example:**

Create a category hierarchy like:
Country
 - Australia
   - State
     - Vic
     - NSW
 - New Zealand
   - State
     - Auckland
     - Wellington

Enable "AJAX Chaining" in Settings > Multiple Category Selection. Selecting "Australia" will dynamically show the Australian states.

== Frequently Asked Questions ==

= ANY vs ALL is not working? =

Click the "Reset" button first to clear the current filter, then try again.

= The dropdowns aren't appearing =

Dropdowns only appear for parent categories that have sub-categories with published posts. Make sure your categories have posts assigned.

= Can I style the dropdowns? =

Yes. The form uses `.mcsw-form`, each dropdown is in `.mcsw-select-wrap`, and AJAX-chained results use `.mcsw-chained`. See the plugin's `css/style.css` for the full class list.

== Screenshots ==

1. Widget settings in Appearance > Widgets
2. Category filter form on the frontend
3. Block settings in the editor sidebar

== Changelog ==

= 4.0.0 =

* New: Gutenberg block — "Multi-Category Filter" available in the block editor
* New: Lightweight CSS file with clean BEM-style classes
* Removed: PHP sessions — all search state now carried in URL query parameters
* Removed: jQuery dependency — AJAX chaining rewritten in vanilla JavaScript
* Fixed: AJAX chaining now sends the nonce (was broken since v3.2.0)
* Fixed: Shortcode now returns output instead of echoing (proper shortcode behavior)
* Fixed: Rewrite rules no longer flushed on every page load (only on activation)
* Fixed: AJAX handler uses wp_send_json_success() instead of print/die
* Changed: Admin settings page uses dedicated slug instead of __FILE__
* Changed: All redirect calls use wp_safe_redirect()
* Changed: Requires WordPress 6.0+
* Security: Tightened input validation with sanitize_key(), absint(), whitelist checks

= 3.2.0 =

* PHP 8.x compatibility: replaced create_function() with anonymous function
* Security: ABSPATH guards, nonce verification, input sanitization, output escaping
* Replaced get_bloginfo('url') with home_url()

= 3.1.6 =

* Tested in WP 4.3.1
* Updated widget implementation to PHP 5 methodology

= 3.1.5 =

* Tested in WP 3.8
* Fixed overriding the navigation menu WP script

= 3.1.4 =

* Tested in WP 3.7
* Fixed media library files missing after plugin search

= 3.1.3 =

* Tested in WP 3.5.2
* Fixed AND/IN rewrite rules

= 3.1.1 =

* Extensive testing on any/all search
* Reverted select box layout

= 3.1 =

* Created admin settings page
* Added shortcode [mcsw]
* AJAX on/off toggle
* Form display above results toggle

= 3.0 =

* Support for multiple forms on a page
* Shortcode support
* Rewrite rule fixes

= 2.4 =

* Rewrite rules only flush on activation

= 2.3 =

* Fixed variable checking
* Added title ordering

= 2.2 =

* AJAX chained select boxes

= 2.1 =

* WordPress 2.8+ widget class with multiple instances

= 2.0 =

* Fixed permalink issues
* All-in-one-SEO and WP Smart Sort compatibility

= 1.0 =

* First release
