=== Smart Waitlist for WooCommerce ===
Contributors:       abdennourlaoubi
Tags:               woocommerce, waitlist, out of stock, back in stock, notify
Requires at least:  6.0
Requires Plugins:   woocommerce
Tested up to:       7.1
Stable tag:         2.0.0
Requires PHP:       8.0
WC requires at least: 7.0
WC tested up to:    11.1
License:            GPL-2.0-or-later
License URI:        https://www.gnu.org/licenses/gpl-2.0.html

Let customers join a waitlist for out-of-stock products and receive automatic email notifications when stock is restored.

== Description ==

**Smart Waitlist for WooCommerce** automatically notifies customers when an out-of-stock product is back in stock.

When a product runs out of stock, a "Notify Me When Available" form appears on the product page. Customers enter their name and email to join the waitlist. The moment you restock the product, every pending subscriber receives a personalized notification email — automatically.

= Core Features =

* **Automatic restock detection** — hooks directly into WooCommerce stock management; no manual steps required.
* **Variable product support** — per-variation waitlists, so customers subscribe to the exact variant they want.
* **Double opt-in support** — require email confirmation before users are added to the waitlist (now a core free feature).
* **Smart form display** — form appears only on out-of-stock products; hidden when stock is available.
* **Duplicate prevention** — customers cannot accidentally subscribe twice.
* **Honeypot spam protection** — invisible field blocks automated spam submissions.
* **HMAC-signed unsubscribe links** — every notification email contains a secure, one-click unsubscribe link.
* **Batch notifications** — large waitlists are processed in background batches via WP-Cron to avoid timeouts.
* **Admin dashboard** — searchable, filterable, sortable subscriber list with bulk actions (delete, mark as notified).
* **Per-product settings** — enable or disable the waitlist individually for any product.
* **Waitlist capacity limits** — optionally cap the number of subscribers per product (or per variation) to control stock flow.
* **WooCommerce Settings integration** — configure waitlist emails under WooCommerce > Settings > Emails and waitlist behavior under WooCommerce > Settings > Products > Waitlist.
* **Theme-overridable templates** — copy templates to your theme for complete HTML customisation.
* **GDPR tools** — personal data export and erasure via WordPress Privacy Tools (Tools → Erase Personal Data).
* **Developer-friendly** — action and filter hooks throughout; documented phpdoc on every method.
* **WPCS-compliant** — all database queries use `$wpdb->prepare()`; all output is escaped; nonces on every form.
* **HPOS compatible** — declared compatible with WooCommerce High-Performance Order Storage.

= Pro Version =

Upgrade to the Pro Version (available at https://payhip.com/b/aH2Oq ) for advanced features:

* WhatsApp Business API notifications
* Coupon-with-notification (send discount codes alongside the restock alert)

= Privacy =

This plugin stores subscriber names, email addresses, and optionally phone numbers in a dedicated database table (`{prefix}swfwc_waitlist`). Data is retained until manually deleted by the site administrator or until the subscriber unsubscribes. No data is shared with third parties. Plugin data is fully removed on uninstall.

Personal data can be exported and erased via **Tools → Erase Personal Data** in compliance with GDPR Article 17 and Article 20.

Consider updating your site's Privacy Policy to reflect this data collection.

== Installation ==

= Upload Installation =

1. Download the plugin ZIP file.
2. Log in to your WordPress admin panel.
3. Go to **Plugins → Add New → Upload Plugin**.
4. Choose the ZIP file and click **Install Now**, then **Activate**.

= After Activation =

1. Go to **WooCommerce → Settings → Products → Waitlist** to configure the plugin.
2. Review the waitlist emails under **WooCommerce > Settings > Emails**.
3. Customise email subjects, headings, and email types from WooCommerce's email settings.
4. The waitlist form will automatically appear on any out-of-stock product.

== Email Setup Guide ==

= Email Configuration =

1. Configure a reliable SMTP or transactional email plugin first.
2. Send a test email from the SMTP plugin and confirm it arrives.
3. Go to **WooCommerce → Settings → Emails**.
4. Enable and review **Waitlist Signup Confirmation**.
5. Enable and review **Waitlist Restock Notification**.
6. Test the waitlist flow with one out-of-stock product and one real email address.

= Email Production Checklist =

* SMTP or transactional email test succeeds.
* SPF, DKIM, and DMARC are configured for the sending domain.
* Signup confirmation email arrives.
* Restock notification email arrives after stock changes to `instock`.
* Unsubscribe links work.
* Emails are not consistently landing in spam.

= Pro Version Features Setup =

If you upgrade to the Pro version, you will get access to:
* **WhatsApp Cloud API Integration** for template-based restock messages.
* **Auto-generated WooCommerce Coupons** sent directly inside email alerts.

== Frequently Asked Questions ==

= Does this work with variable products? =

Yes. The form appears when a customer selects a specific variation that is out of stock. Subscribers are tracked per variation, so notifications are only sent when that exact variation comes back in stock.

= Can I customise the form appearance? =

Yes. Copy `templates/notify-form.php` from the plugin folder to `{your-theme}/smart-waitlist-for-woocommerce/notify-form.php` and modify it freely. CSS custom properties in `public/css/swfwc-public.css` make colour/spacing changes easy without overriding templates.

= Can I customise the notification email? =

Yes. Go to **WooCommerce > Settings > Emails** and update the waitlist email subjects, headings, and email types. You can also customise the HTML template by copying `templates/emails/email-notification.php` to your theme.

= What merge tags are available in the email? =

`{product_name}`, `{product_url}`, `{customer_name}`, `{site_name}`, `{unsubscribe_url}`

= How do customers unsubscribe? =

Every notification email contains a signed unsubscribe link. Clicking it marks the subscriber as unsubscribed immediately — no login required.

= Is the unsubscribe link secure? =

Yes. Each link contains an HMAC-SHA256 token signed with your site's WordPress auth salt. Tokens expire after 90 days and cannot be guessed or forged.

= Does it work with WooCommerce HPOS? =

Yes. The plugin declares compatibility with WooCommerce High-Performance Order Storage (HPOS / custom order tables).

= What happens if I have thousands of subscribers? =

For waitlists with more than 50 subscribers, notifications are automatically queued in batches of 25 via WP-Cron, with 30 seconds between batches. This prevents PHP timeouts and server overload.

= Will my data be deleted if I uninstall the plugin? =

Yes. The uninstall routine drops the `swfwc_waitlist` table and removes all plugin options. This action is irreversible.

= Can I disable the waitlist for specific products? =

Yes. Each product has a "Waitlist" meta box in the product editor where you can set it to Enabled, Disabled, or "Inherit global setting".

= Does the plugin support GDPR right-to-erasure requests? =

Yes. The plugin integrates with WordPress Privacy Tools (Tools → Erase Personal Data). Submitting an erasure request for a customer's email will permanently delete all their waitlist records.

= Can I limit how many people join a single product's waitlist? =

Yes. Go to **WooCommerce → Settings → Products → Waitlist** and set **Max Subscribers per Product**. Leave it at `0` for unlimited (the default).

= Can I use the plugin behind a reverse proxy or load balancer? =

Yes. Define your trusted proxy IP addresses using the `swfwc_trusted_proxy_ips` filter or the `SWFWC_TRUSTED_PROXY_IPS` constant, and the plugin will correctly identify real client IPs from the `X-Forwarded-For` header. Without this configuration the direct connection IP is used, which is the safe default.

== Screenshots ==

1. Waitlist signup form on an out-of-stock product page.
2. Restock notification email received by a subscriber.
3. Admin subscribers dashboard with search, filters, and bulk actions.
4. Waitlist panel on the product edit page.
5. Plugin settings page (WooCommerce → Settings → Products → Waitlist).

== Changelog ==

= 2.0.0 =
* **Breaking (internal only):** Renamed every internal identifier — classes, functions, hooks, options, the custom database table, post meta, cron hooks, nonces, and asset handles — from the "SWW"/"sww_" prefix to "SWFWC"/"swfwc_". The old prefix was too short and collision-prone for the WordPress.org Plugin Directory. A one-time, automatic migration preserves all existing waitlist data, settings, and per-product toggles on upgrade; no action needed.
* Fix: "Max Subscribers per Product" is now a free, fully configurable setting under WooCommerce → Settings → Products → Waitlist. The subscriber-cap enforcement was already active in the free plugin; only the control to configure it was previously (incorrectly) hidden.
* Fix: Removed all inline `<style>`/`<script>` blocks from PHP templates. CSS moved into `admin/css/swfwc-admin.css`; JS moved into `admin/js/swfwc-admin.js` using `wp_localize_script()` for nonces/strings.
* Fix: Plain-text double opt-in confirmation email now escapes the confirmation link with `esc_url()` instead of `esc_url_raw()` at the point of output.
* Fix: Corrected Plugin URI and Author URI to resolve correctly; corrected the readme Contributors field.
* Fix: Added `Requires Plugins: woocommerce` header plus a defensive activation-time WooCommerce check for older WordPress versions.
* Housekeeping: Text domain corrected to `smart-waitlist-for-woocommerce` (matching the plugin slug) throughout.

= 1.1.2 =
* Critical fix: Bulk status updates now pass dynamic parameters to `$wpdb->prepare()` with variadic binding, restoring bulk mark-as-notified compatibility.
* Email: Double opt-in confirmation now uses a dedicated WooCommerce email class with HTML/plain-text templates and WooCommerce Settings > Emails controls.
* Cleanup: Removed legacy Gumroad license code and Pro features to focus on a lightweight freemium-first build.
* Fix: Addressed casing issues in activation and deactivation hooks.
* Documentation: Updated plugin version and compatibility metadata.

= 1.1.1 =
* Security: Rate limiter now only trusts X-Forwarded-For headers from configured trusted proxy IPs (SEC-02).
* Security: Removed `SWFWC_get_pending_subscribers_extra_where` filter to eliminate SQL injection surface (SEC-01). Replaced with typed `$confirmed_only` boolean parameter.
* Security: Unsubscribe tokens now include a 90-day expiry timestamp with backwards compatibility for existing tokens (SEC-06).
* Bug fix: Re-subscribing after unsubscribing no longer silently fails to send the confirmation email. MySQL's `insert_id=0` on `ON DUPLICATE KEY UPDATE` is now handled by re-fetching the row ID (BUG-01).
* Performance: Removed blocking `sleep()` call inside the WhatsApp cron worker. Retries are now scheduled as async events to avoid blocking the cron queue (PERF-01).
* Performance: Batch processing now fetches all subscriber rows in a single `IN()` query instead of N individual SELECTs (BUG-02).
* Performance: Admin list table status counts now use a single `GROUP BY` query instead of four separate `COUNT(*)` queries (WC-04).
* Reliability: Notification lock transient prevents duplicate batches when the stock-change hook fires more than once in quick succession (WC-01).
* Database: Added `user_id` index to `swfwc_waitlist` table schema (DB-01).
* Database: `delete_by_product()` now busts caches for all variation IDs, not only variation 0 (DB-04).
* GDPR: Added personal data exporter (`wp_privacy_personal_data_exporters`) hook for data portability compliance.
* GDPR: Added personal data eraser (`wp_privacy_personal_data_erasers`) hook for right-to-erasure compliance.
* GDPR: Added optional GDPR consent checkbox (disabled by default; enable via `SWFWC_show_consent_checkbox` filter).
* GDPR: Privacy policy URL appended to form privacy note via `wp_get_privacy_policy_url()`.
* Architecture: `SWFWC_Email_Confirmation` now accepts `SWFWC_Database` via constructor, restoring the DI contract (ARCH-01).
* Architecture: Button position option is now read at render-time instead of at hook-registration time (ARCH-02).
* Architecture: Singleton `__clone()` now throws an exception instead of silently succeeding (ARCH-03).
* Compatibility: Bumped DB schema version to 1.2.0 to trigger `dbDelta` on existing installs for the new index.

= 1.0.0 =
* Initial release.
* Core waitlist functionality: subscribe, notify on restock, unsubscribe via link.
* Variable product / variation support.
* Admin dashboard with WP_List_Table (search, filter, bulk actions).
* WooCommerce email class integration.
* Async batch processing via WP-Cron.
* HMAC-signed unsubscribe URLs.
* Honeypot spam protection.
* WooCommerce HPOS compatibility declaration.
* Theme-overridable templates.
* Full uninstall cleanup.

== Upgrade Notice ==

= 2.0.0 =
Internal identifier rename for WordPress.org compliance (SWW → SWFWC prefix). All existing data migrates automatically. Max Subscribers per Product is now a free, configurable setting.

= 1.1.2 =
Critical compatibility and stability update. Fixes database activation and deactivation hooks, and upgrades double opt-in controls. Highly recommended.

= 1.1.1 =
Security and reliability update. Fixes a critical bug where re-subscribing after unsubscribing silently failed to send the confirmation email. Adds GDPR personal data export/erasure hooks. Upgrades the database schema (adds `user_id` index). Recommended for all users.

= 1.0.0 =
Initial release.

== License ==

Smart Waitlist for WooCommerce is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or any later version.

Smart Waitlist for WooCommerce is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
