=== W3S API Extension for Woocommerce ===
Contributors: w3specialists
Tags: woocommerce, api, extension, categories
Requires at least: 6.7
Tested up to: 7.1
Requires PHP: 7.4
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html
Stable tag: 1.1.0

Enhances your store’s REST API by adding powerful, flexible endpoints. Stay tuned more Endpoints are coming!

== Description ==
Enhances your store’s REST API by adding powerful, flexible endpoints.
Stay tuned more are coming!

**Add or Remove a Single Category**

Easily append or remove one category at a time—by numeric ID or slug—using simple POST/PUT/PATCH or DELETE requests to
<code>/wp-json/wc/v3/products/{product_id}/categories/{identifier}</code>

**Batch Manage Multiple Categories**

In a single call, add or remove multiple categories at once via JSON payloads to
<code>/wp-json/wc/v3/products/{product_id}/categories</code>
Supply an array of IDs or slugs under the “categories” key to update your product’s category list in bulk.

**Automatic Slug Resolution**
Pass slugs like “summer-collection” — or non-Latin slugs such as “ανδρικά” — and the plugin will resolve them to the correct WooCommerce term IDs on the fly—no extra lookups required.

**Non-Destructive Updates**
Neither endpoint touches other product data. Categories are merged or pruned transparently without overwriting prices, stock, attributes, or any other fields.

**Plays Well With WooCommerce**
Changes are saved through the WooCommerce product API, so product caches are refreshed, `woocommerce_update_product` runs, `product.updated` webhooks fire, and the store’s default category is applied if a product is left without one.

Built-In Validation & Security

Sanitization of all inputs (IDs and slugs) to guard against bad data; the batch payload is validated against a schema.

Permission checks mirror WooCommerce core: only users allowed to edit the product (Shop Manager, Admin) can modify its categories.

Clear, standardized error codes (w3s_api_extension_invalid_product and w3s_api_extension_invalid_product_category) for consistent API responses. Unknown category IDs and slugs both return 404.

W3S API Extension for WooCommerce installs alongside the core WooCommerce REST API, requires no additional configuration, and works out of the box.

== Endpoints Documentation ==

**Product Categories**

<ul>
	<li>
		Add a single category
		<ul>
			<li><strong>Type:</strong> HTTP request</li>
			<li><strong>Endpoint:</strong> <code>/wp-json/wc/v3/products/{product_id}/categories/{identifier}</code></li>
			<li><strong>Methods:</strong> POST, PUT, PATCH</li>
			<li><strong>Examples:</strong>
				<code>curl -X PUT https://example.com/wp-json/wc/v3/products/125/categories/18 \
					-u consumer_key:consumer_secret</code>
				<code>curl -X PUT https://example.com/wp-json/wc/v3/products/125/categories/my-category \
					-u consumer_key:consumer_secret</code>
			</li>
		</ul>
	</li>
	<li>
		Remove a single category
		<ul>
			<li><strong>Type:</strong> HTTP request</li>
			<li><strong>Endpoint:</strong> <code>/wp-json/wc/v3/products/{product_id}/categories/{identifier}</code></li>
			<li><strong>Methods:</strong> DELETE</li>
			<li><strong>Examples:</strong>
				<code>curl -X DELETE https://example.com/wp-json/wc/v3/products/125/categories/18 \
					-u consumer_key:consumer_secret</code>
				<code>curl -X DELETE https://example.com/wp-json/wc/v3/products/125/categories/my-category \
					-u consumer_key:consumer_secret</code>
			</li>
		</ul>
	</li>
	<li>
		Batch add categories
		<ul>
			<li><strong>Type:</strong> HTTP request</li>
			<li><strong>Endpoint:</strong> <code>/wp-json/wc/v3/products/{product_id}/categories</code></li>
			<li><strong>Methods:</strong> POST, PUT, PATCH</li>
			<li><strong>Example:</strong>
				<code>curl -X PUT https://example.com/wp-json/wc/v3/products/125/categories \
					-u consumer_key:consumer_secret \
					-H "Content-Type: application/json" \
					-d '{"categories": [1,"my-category",3,"my-category-1"]}'</code>
			</li>
		</ul>
	</li>
	<li>
		Batch delete categories
		<ul>
			<li><strong>Type:</strong> HTTP request</li>
			<li><strong>Endpoint:</strong> <code>/wp-json/wc/v3/products/{product_id}/categories</code></li>
			<li><strong>Methods:</strong> DELETE</li>
			<li><strong>Example:</strong>
				<code>curl -X DELETE https://example.com/wp-json/wc/v3/products/125/categories \
					-u consumer_key:consumer_secret \
					-H "Content-Type: application/json" \
					-d '{"categories": [1,"my-category",3,"my-category-1"]}'</code>
			</li>
		</ul>
	</li>
</ul>

**Extra notes**
<ul>
 <li> Strings that include only digits are parsed as IDs, everything else as a slug. Slugs may contain any characters except "/"; URL-encode them when needed (the batch endpoint takes them in the JSON body, so no encoding is required there).</li>
 <li> The batch endpoints also accept form-encoded <code>categories[]=…</code> parameters or a comma-separated string. An empty or missing list returns a standard 400 <code>rest_missing_callback_param</code>/<code>rest_invalid_param</code> error.</li>
 <li> Removing a product’s last category assigns the store’s default category (“Uncategorized”), exactly as WooCommerce does in the admin.</li>
 <li> Every response is the product’s resulting list of category terms.</li>
</ul>

== Installation ==
1. Upload the `w3s-api-extension` folder to the `/wp-content/plugins/` directory.
2. Activate the plugin through the 'Plugins' menu in WordPress. WooCommerce must be installed and active.
3. No further configuration is required; the endpoints are available immediately.

== Changelog ==
= 1.1.0 =
* Compatibility: tested with WordPress 7.1 and WooCommerce 11.0. Now requires WordPress 6.7+ and WooCommerce 9.0+.
* Changed: category updates go through the WooCommerce product CRUD (`set_category_ids()` / `save()`). WooCommerce's product object cache (on by default for new stores since WooCommerce 11.0) is invalidated, and `woocommerce_update_product` and `product.updated` webhooks now fire.
* Fixed: numeric category IDs that do not exist (or belong to another taxonomy) now return 404 instead of silently succeeding.
* Added: the single-category endpoints accept any slug, including non-Latin (e.g. Greek) slugs.
* Added: the batch `categories` parameter is declared in the route schema; form-encoded and comma-separated values are accepted and invalid payloads return standard 400 errors.
* Added: item schema for API discovery (OPTIONS requests).
* Changed: permission checks mirror WooCommerce core (`wc_rest_check_post_permissions`), honouring the `woocommerce_rest_check_permissions` filter.
* Fixed: routes are no longer registered when WooCommerce is inactive (previously a fatal error on request).
* Removed: unnecessary rewrite-rule flush on activation/deactivation.

= 1.0.1 =
* Fixed: readme file modifications

= 1.0.0 =
* Initial release
