=== Wolfcourt Product Formats ===
Contributors: wolfcourt
Tags: woocommerce, product options, product sizes, portions, add-ons
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.18
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Let customers choose a format, portion, pack, or size with its own final price on simple WooCommerce products.

== Description ==

Wolfcourt Product Formats adds a focused format selector to simple WooCommerce products. Each choice has a label, a final unit price, an order, and a default selection.

The selected format is validated on the server and carried through the cart, checkout, order administration, emails, and exports. An optional global paid add-on can also be configured for common extras such as gift wrapping, engraving, or a birthday plaque.

Features:

* Up to 100 formats per simple product.
* Drag-and-drop ordering and a default choice.
* Server-side price and selection validation.
* Optional paid add-on with editable label and description.
* WooCommerce HPOS compatibility.
* Responsive and keyboard-friendly storefront controls.
* Automatic reuse of existing Temptation Product Portions data.

The format selector works with the classic WooCommerce product form. In our WooCommerce 11.1.2 test, the Add to Cart + Options block also rendered the selector and submitted it successfully through a regular HTML POST form; this is not a claim of compatibility with every product block. Standard catalogue buttons for simple products with formats link to the product page and say "Choose your format" instead of attempting an optionless cart request. Custom Store API clients may pass `wolfcpf_selected_option` as a non-negative format index and `wolfcpf_paid_addon` as `yes` or `true` to the add-item route. The server checks the choice and recalculates the price from saved product data; a request without a required format is rejected. Untested custom quick-add interfaces should link customers to a product form that visibly presents the choices.

Classic product forms use a cart security token tied to the visitor's WooCommerce session. The product-page script refreshes it before submission so that cached pages can still be used. If JavaScript is disabled on a cached page, reload the page before retrying an expired form. Store API clients continue to use WooCommerce's own Nonce or Cart-Token header.

No customer data is collected or sent to an external service.

== Installation ==

1. Install and activate WooCommerce.
2. Upload the plugin ZIP from Plugins > Add New > Upload Plugin.
3. Edit a simple product and open Formats & portions.
4. Enable formats, add the available choices, and update the product.
5. Configure the optional paid add-on under WooCommerce > Settings > Products > Product formats.

If migrating from Temptation Product Portions, deactivate the old plugin before activating this one. Existing format data and the existing birthday-plaque price are retained.

== Troubleshooting ==

* No selector on a product? Confirm that WooCommerce is active, the product is a simple product, formats are enabled in its Formats & portions panel, and at least one valid label and price have been saved.
* An option is rejected at add-to-cart? Reload the product page and try again. The server accepts only choices still present in the product's saved configuration.
* Using a product block or quick-add button? Add to Cart + Options passed a browser cart test on WooCommerce 11.1.2 using a regular POST form. Standard catalogue buttons link to the product page when a format is required. Other block and custom quick-add implementations may not present the choices; verify your product template.
* The cart price differs from the catalog price? A format uses its configured final unit price; the optional add-on is added on top. The original catalog price is not changed.
* Migrating an existing store? Deactivate Temptation Product Portions first and verify one product and one test order before using the new plugin on a live checkout.

== Privacy ==

The plugin stores format choices and add-on settings in WordPress product and site options. A customer's chosen format and add-on are stored with the WooCommerce order item. It sends no data to an external service and has no telemetry. Uninstall removes this plugin's add-on enable, label and description options, but deliberately retains legacy pricing, product-format metadata and order records for store continuity; remove those records through the store's own data-management process if required.

== Screenshots ==

1. Configure two product formats with their final prices and a default choice in the WooCommerce product editor.

== Frequently Asked Questions ==

= Does this change the original WooCommerce product price? =

Only cart items with a selected format or paid add-on are adjusted. The saved WooCommerce catalog price is not overwritten.

= Are variable products supported? =

Version 1.0 focuses on simple products. Variable products, conditional rules, per-product add-ons, imports, and bulk editing are suitable premium extensions.

= Does the plugin send data elsewhere? =

No. It has no telemetry and no external service dependency.

= Does the format selector work with every WooCommerce product block? =

Not every block. The classic product form is supported, and Add to Cart + Options passed a browser cart test with a regular POST form in our WooCommerce 11.1.2 test. The Store API can accept a format choice from a custom client. Standard catalogue buttons now open the product form when a format is required; other blocks and custom quick-add interfaces need separate verification or integration.

== Changelog ==

= 1.0.18 =

* Add nonce verification to the cart-token refresh request and simplify product-editor nonce and permission checks.
* Save product settings under Wolfcourt-specific metadata keys while retaining read-only compatibility with existing Temptation Product Portions data.
* Use WordPress.org language packs instead of shipping compiled translation files.

= 1.0.17 =

* Bind classic format and add-on submissions to the visitor's WooCommerce session and refresh the form token on cached product pages.

= 1.0.16 =

* Refuse cart additions when formats are enabled but no valid choice is saved, rather than falling back to the base price.

= 1.0.15 =

* Refuse cart additions when every saved format on an enabled product is malformed, rather than falling back to an unrelated base price.

= 1.0.14 =

* Ignore malformed legacy format rows when displaying choices or calculating cart prices, while preserving the saved data until the merchant edits it.

= 1.0.13 =

* Align the plugin source with automatically fixable WordPress coding-style rules. No intended feature or data-format change from 1.0.12.

= 1.0.12 =

* Move the main plugin class into its own class file for WordPress coding-standard structure; keep saved settings, hooks and storefront behavior unchanged.

= 1.0.11 =

* Make standard catalogue add-to-cart buttons open the product page with an accurate "Choose your format" label when a simple product requires a format. Keep server-side rejection of missing format choices.

= 1.0.10 =

* Clarify that the current WooCommerce Add to Cart + Options block renders the existing selector through its classic-form compatibility path; other product blocks remain unverified. No behavior change from 1.0.9.

= 1.0.9 =

* Accept server-validated format and optional add-on choices from custom Store API add-to-cart clients without trusting client-supplied prices. Product blocks still need a visual selector.

= 1.0.8 =

* Clarify the supported classic product-form flow and the current Store API/product-block limitation in the public documentation; plugin behavior is unchanged.

= 1.0.7 =

* Declare WooCommerce as a WordPress plugin dependency while keeping the runtime fallback for older WordPress versions.

= 1.0.6 =

* Use a more distinctive Wolfcourt-specific prefix for global PHP symbols before WordPress.org submission. Existing product metadata, settings and order data remain unchanged.

= 1.0.5 =

* Sanitize submitted format-editor rows and add-on selection before processing while retaining strict server-side validation.

= 1.0.4 =

* Reject malformed nested editor values and non-numeric storefront format choices before price and index processing.

= 1.0.3 =

* Adds a separate extension point for per-product add-on offers while preserving the free edition's global add-on behavior.

= 1.0.2 =

* Displays the lowest configured final format price instead of an unrelated product base price when formats are enabled.

= 1.0.1 =

* Adds an opt-in product-type extension point for separately installed add-ons. The free edition still enables formats on simple products only.

= 1.0.0 =

* First market-preparation release.
* Preserves legacy Temptation Product Portions product data.
* Adds dependency handling, nonces, capability checks, HPOS declaration, translatable strings, and neutral styling.
