=== FlexWoo Memberships ===
Contributors: fresheradvice
Tags: membership, woocommerce, restrict content, subscriptions, members
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 8.2
Stable tag: 1.44.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Sell membership plans and subscriptions with WooCommerce and restrict posts, pages and products to members.

== Description ==

FlexWoo Memberships lets you sell membership plans and subscriptions through
WooCommerce, use them to restrict pages, posts and products, and gives members
their own Memberships and Subscriptions tabs in My Account.

FlexWoo Memberships (this plugin) runs entirely on its own -- no other
Flex Memberships build is required for it to work. FlexWoo Memberships
Pro is a separate, optional add-on that extends this plugin with premium
features; Pro itself requires this Free plugin to be installed and
active (see Pro's own "Requires Plugins" header).

= Free features =
* Unlimited membership plans: free, fixed-length and subscription plans sold through WooCommerce products
* Subscriptions billed through WooCommerce with native Stripe and PayPal recurring payments, renewing every 1-7 days or 1-3 weeks
* Content restriction for posts, pages and products, with restriction rules, access rules and RSS feed protection
* Manual and automatic membership assignment, and approval after purchase
* Membership and subscription lists, detail pages, pause / resume / cancel rules and an activity ledger
* My Account "Memberships" and "Subscriptions" tabs (card layout)
* Membership, subscription and account e-mails with editable templates
* Login protection (failed-login lockouts) and new-user approval
* Tools: data export, database tools, scheduled tasks, audit log and system status

= Pro features (FlexWoo Memberships Pro, a separate plugin) =
* Monthly / yearly billing cycles, signup fees, free trials, one-time purchase and discount pricing on subscriptions
* Renewal synchronization and Subscription box products
* Download credits, protected files and the credits override per product
* Drip content ("available N days after signup") and the partial-content locking shortcode
* Member discounts, gift memberships and subscriptions
* Paywall restriction mode, content blocks and the FlexWoo Gutenberg / Elementor blocks
* Two-factor e-mail login codes
* Member self-service (switch plan, cancel, pause), bulk actions, members CSV import
* Advanced analytics and reports, and additional My Account layouts

The Pro features are not included in this plugin: FlexWoo Memberships Pro is a separate plugin, sold at https://flexwoomemberships.com. This plugin's screens only mention them; everything listed under "Free features" works without Pro.

== External Services ==

FlexWoo Memberships integrates with the following third-party services to deliver subscription billing and administration functionality:

1. Stripe API
* Service URL: https://api.stripe.com
* Purpose: Native recurring payments, automated subscription renewals, customer management, and webhook event processing.
* Data Sent: Customer email, order ID, product/plan amounts, currency, and subscription lifecycle metadata.
* Terms of Service: https://stripe.com/legal/ssa
* Privacy Policy: https://stripe.com/privacy

2. PayPal API
* Service URL: https://api-m.paypal.com and https://api-m.sandbox.paypal.com
* Purpose: Subscription agreement verification and recurring billing webhook event synchronization.
* Data Sent: Order identifiers, customer email, subscription tokens, and transaction amounts.
* Terms of Service: https://www.paypal.com/legalhub/useragreement-full
* Privacy Policy: https://www.paypal.com/legalhub/privacy-full

3. Public IP lookup (ipify / icanhazip) -- off by default
* Service URLs: https://api.ipify.org and https://icanhazip.com (a site can replace the list with the `flexwoomemberships_external_ip_services` filter)
* Purpose: only when Settings > "Use external services to get user IP Address" is turned on AND the visitor's address is a loopback address (the site runs on the same machine, e.g. local development), the site asks one of these services for its public IP address so audit and membership records do not all show 127.0.0.1. The answer is cached for 6 hours.
* Data Sent: an ordinary HTTPS GET request from the server; no visitor, member or order data is sent.
* ipify Terms / Privacy: https://www.ipify.org (the service states it does not log visitor data)
* icanhazip Terms / Privacy: https://www.cloudflare.com/website-terms/ and https://www.cloudflare.com/privacypolicy/ (operated by Cloudflare)

4. Freemius -- only after the site administrator opts in
* Service URLs: https://api.freemius.com and https://wp.freemius.com
* Purpose: optional update and security e-mails and usage data, the Account and Add-Ons screens under FW Memberships, and licence activation and updates for FlexWoo Memberships Pro (a Freemius add-on of this plugin). Nothing is sent before the administrator clicks "Allow & Continue" on the opt-in screen; "Skip" keeps the plugin fully working with no data sent.
* Data Sent (after opt-in only): the administrator's name and e-mail, site URL, WordPress, PHP and plugin versions, active plugins and theme, and activation, deactivation and uninstall events of this plugin.
* Terms of Service: https://freemius.com/terms/
* Privacy Policy: https://freemius.com/privacy/

== Installation ==

1. Upload the plugin files to /wp-content/plugins/flexwoo-memberships, or
   install the zip through Plugins > Add New > Upload Plugin.
2. Activate the plugin. WooCommerce must be installed and active.
3. Go to FlexWoo Memberships in the admin menu to create your first plan.

== Changelog ==

= 1.44.1 =
* Fixed: the plan editor's Permissions panel now shows "Pages / Posts / Products available: Immediately or After N days from signup" for each plan. The setting was saved and applied by Pro but its control was never displayed. Without Pro, an upgrade notice is shown in its place.
* Changed: "WC tested up to" 11.2.1.

= 1.44.0 =
* Added: Freemius SDK 2.13.4 (vendor/freemius): an optional opt-in screen (with Skip) for update and security e-mails and usage data, and Account and Add-Ons screens under FW Memberships. Nothing is sent to Freemius unless the site administrator opts in; every FlexWoo screen stays usable before the choice is made.
* Added: FlexWoo Memberships Pro is licensed and updated through Freemius as an add-on of this plugin. New filter `flexwoomemberships_pro_licensed` lets Pro report whether its licence allows its features.
* Fixed: with "Hide price and add to cart buttons for members" on, the Price column on the Products screen showed "–" for products of a plan the store owner also belonged to. The setting now applies to the shop only; prices always show in the WordPress admin.

= 1.43.3 =
* Fixed: activating or updating the plugins logged "Translation loading for the flexwoo-memberships domain was triggered too early" (and the same for WooCommerce and other plugins). Recurring jobs are now scheduled on init, and the cron heartbeat's label is never translated before init.

= 1.43.2 =
* Security: request data handed to other code is sanitized first. The restriction and General settings hooks receive only sanitized fields (never the raw request), and every JSON payload from the admin screens (e-mails, access timing, access rules, linked content) is sanitized as it is decoded.
* Security: alternate content and the paywall that replace restricted content are escaped before they are shown (forms from shortcodes and the paywall card's styling are kept); the paywall's search-engine data is printed in the footer.
* Changed: FlexWoo Memberships notices (cron not running, Pro no longer active, Pro too old) show only on FlexWoo Memberships screens, the Dashboard and the Plugins screen.
* Changed: translations load through WordPress.org language packs (no load_plugin_textdomain()); the plugin description lists only what this plugin does.

= 1.43.1 =
* Fixed: Tools > Cron Jobs showed "Cron job from your host: Not seen yet" although the host's cron job ran. Every call the host makes to wp-cron.php is now recorded, not only the ones that happen to run the five-minute check; while WP-Cron is still on, page visits usually ran that check first. (wp-cron.php always answers with a blank page; that is normal.)

= 1.43.0 =
* Added: a "FlexWoo Memberships" widget on the WordPress dashboard. This month's subscription signups and signup revenue, trials and trial revenue, renewals and renewal revenue (net of refunds), cancellations and failed renewal payments, plus new and active memberships, monthly recurring revenue and memberships ending in the next 30 days. Each figure is compared with the same days of last month and links to the matching list. Move or hide it under Screen Options; revenue is shown only to users who can view WooCommerce reports.
* Developers: the `flexwoomemberships_dashboard_widget_sections` filter adds sections to the widget (Pro adds Gifts).

= 1.42.0 =
* Added: FlexWoo Razorpay Payments support. A subscription whose renewals all cost the same runs in Razorpay Subscriptions (renewal orders are recorded from Razorpay's charges, and its customer is linked in Razorpay); otherwise the first payment is taken by Razorpay and the site invoices each renewal, with the reason in an order note. Razorpay appears in the gateway labels, the subscription screen's dashboard link, "Renewal payments: Charged by Stripe / PayPal / Razorpay" and Tools > Cron Jobs.
* Fixed: paying a renewal invoice with PayPal or Razorpay could start a second gateway subscription. A renewal order is now always paid once.
* Fixed: pausing or resuming from the admin (Subscriptions and Memberships screens, row buttons, Quick Actions and bulk actions) only changed the membership here; Stripe, PayPal and Razorpay kept billing. The subscription is now paused / resumed at the gateway too, and when the gateway refuses, nothing changes and its reason is shown.
* Fixed: a Razorpay subscription that has not started billing cannot be paused (Razorpay would cancel it). Pause is refused with the reason and the member's Pause button is hidden until billing starts; "cancel at the end of the term" cancels it at Razorpay right away and keeps access to the end of the paid period.
* Fixed: when a paused membership's time limit ran out while Stripe, PayPal or Razorpay could not be reached, the member got access back while billing stayed paused. The gateway is now resumed first; until it answers, the membership stays paused and the automatic resume tries again on the next run.
* Developers: GatewayBilling::set_gateway_paused_first() pauses / resumes the gateway subscription before the membership changes (used by Pro's member self-service).
* Changed: the payment plugins' menus are named FlexWoo Stripe Payments and FlexWoo PayPal Payments in System Status hints.

= 1.41.0 =
* Added: Tools > Cron Jobs. Shows what really runs the scheduled tasks of FlexWoo Memberships, Pro, FlexWoo Stripe Payments and FlexWoo PayPal Payments (a small heartbeat job records every cron run and whether a page visit, the host's cron job or WP-CLI started it), walks through setting up a cron job with the host (ready-to-copy wget / curl / WP-CLI / crontab commands, a "Test wp-cron.php now" button) and turning off the page-load WP-Cron with define( 'DISABLE_WP_CRON', true ), with a check for each step. It lists every scheduled job of the four plugins and WooCommerce's queue, flags late ones, and warns administrators when WP-Cron is off and no cron job has run recently. System Status, Scheduled Tasks, the Troubleshooter and the Tools Overview show the same cron state.
* Fixed: deleting a WordPress account left its row in the members table behind (one per deleted account). It is now removed with the account whenever no membership still points at it; with "Delete data on account deletion" off, kept memberships keep theirs.
* Fixed: Tools > Scheduled Tasks cut off the "Run Now" buttons (the status table's right column had become too narrow for them). The column now fits the button, and on narrow screens each task stacks its name, schedule and button.
* Fixed: System Status checked PHP 7.4 / WordPress 6.0 as the minimum; it now checks what the plugin requires (PHP 8.2, WordPress 6.4).
* Fixed: uninstalling also removes pending Stripe / PayPal cancel and billing-stop retries.

= 1.40.0 =
* Added: Subscriptions > Settings > "Renewal payments". With "Charged by Stripe / PayPal" (the new default), a subscription paid with FlexWoo Stripe Payments is created as a Stripe Billing subscription, so it is listed in the Stripe Dashboard's Subscriptions tab and Stripe charges each renewal. With "Charged by this site", the site charges the saved card or PayPal account for each renewal, as before.
* Added: Stripe renewals keep every price this site sets. Shortly before each renewal, the renewal order is created here with the cycle's price, renewal coupon, tax and shipping, and Stripe's invoice is adjusted to that total. Stripe charges it, and the renewal order is marked paid with Stripe's payment.
* Added: a failed Stripe renewal follows the failed-payment schedule in Subscriptions > Settings. If the customer pays the renewal order on its Pay page, Stripe's invoice is marked paid without a second charge.
* Added: cancelling, cancelling at the end of the term (and undoing it), pausing, resuming and changing the card on this site are sent to Stripe. A subscription cancelled in the Stripe Dashboard stops renewing here.
* Added: a PayPal subscription is run by PayPal (it shows under Subscriptions in the PayPal account) whenever its renewal prices fit a PayPal plan: the same price for every renewal, or a discounted run of renewals followed by one regular price, with nothing that depends on a date. Otherwise it is bought with the saved PayPal method and this site charges the renewals; an order note says why.
* Added: PayPal's renewal payments, failures, suspensions and cancellations are recorded on the subscription. Pausing it suspends PayPal's billing, and resuming re-activates it.
* Added: if a webhook is missed, the hourly renewal run asks Stripe and PayPal what happened to each due renewal. A Stripe renewal invoice still waiting as a draft (Stripe could not deliver a webhook to the site) is finalized and charged then.
* Added: if a customer buys a plan they already have with PayPal, the second PayPal subscription is cancelled at PayPal with an order note, so the customer is not billed twice. Refunding that payment is left to the merchant.
* Added: a PayPal-run subscription takes its next payment date from PayPal (PayPal bills at its own time of day), and the membership lasts at least until PayPal charges.
* Added: if Stripe or PayPal does not confirm a cancellation, an order note says so and it is retried automatically.
* Added: My Account > Subscriptions shows how each subscription renews. A Stripe-run subscription can switch to another saved Stripe card, which changes the card Stripe charges. A PayPal-run subscription is changed in the PayPal account.
* Added: Tools > Scheduled Tasks and System Status warn when a scheduled task is over an hour late (WordPress only runs them when someone visits the site), and explain how to set up a server cron job. The hourly "Process Subscription Renewals" job is now listed there without Pro too.
* Fixed: Tools > System Status lays out its cards properly. Long values (table names, file paths) wrap in their own column instead of squeezing the others. The Database card shows the server first, then each table by a readable name with its table name underneath.
* Added: System Status > "Payments, Webhooks & License" shows how renewals are charged, FlexWoo Stripe / PayPal Payments' version, test or live mode, connection and webhook state, and how many subscriptions each one runs.
* Fixed: System Status details. The timezone reads "UTC+05:30" (was "UTC5.5"), and the store's base location shows country and state names. WP Rocket, LiteSpeed and other page caches are named correctly. WP-Cron is listed once. Account sign-up at WooCommerce checkout counts as open registration.
* Fixed: Tools > Database Tools > Database Cleanup no longer deletes a deleted user's memberships with a bare database query. A membership that is still active is cancelled first, so Stripe / PayPal stop charging. Each one is then removed with its history and billing record. Billing records left without a membership are removed too (stopped at Stripe / PayPal first).
* Fixed: Tools no longer warns "not scheduled" about activity pruning when no retention period is set; it reads "Off". The Troubleshooter flags scheduled tasks that are running late, and the Overview checks the plugin's tables live. Diagnostics names page-cache plugins correctly.
* Fixed: the renewal billing table is listed as a required Free Memberships table (it was marked "Pro"), and Tools > Database Tools > "Re-run Migrations" now recreates it.
* Fixed: deleting a subscription when its order is cancelled, or deleting a customer's account, now stops Stripe / PayPal billing first.
* Fixed: a PayPal-run subscription limited to a number of payments was billed one payment too many when it had no trial.
* Fixed: a PayPal-run subscription now gets a trial only when the shopper would get one at checkout (a returning customer pays for a full first period).
* Subscriptions that already exist are unchanged and keep being charged the way they were.

= 1.39.0 =
* Added: subscriptions paid with FlexWoo PayPal Payments 0.5.0 (a PayPal account or a card) are renewed by the site with the payment method saved in PayPal's Vault -- each renewal is a real order with its own price, tax and renewal coupon, like FlexWoo Stripe Payments. A renewal that needs the customer can be paid from its Pay page, and the subscription then renews with the method they paid with.
* Added: a PayPal method that PayPal confirms only after the purchase switches a subscription that started on renewal invoices to automatic renewals.
* Changed: when the PayPal account cannot save payment methods, FlexWoo PayPal Payments still sells the plan as a PayPal-run subscription (billed by PayPal at the plan's price). Existing PayPal-run subscriptions keep running until they end.
* Fixed: a billing row whose membership was deleted without cancelling it first is removed instead of being charged.
* Changed: FlexWoo Memberships Pro older than 1.17.0 is paused (it would create PayPal-run subscriptions for FlexWoo PayPal Payments orders the site renews itself).
* Fixed: activating WooCommerce Subscriptions while FlexWoo Memberships was active stopped with a fatal error ("Cannot redeclare wcs_is_subscription()").
* Added: WooCommerce Subscriptions integration. A membership plan sold through a WooCommerce Subscriptions product follows its subscription: renewed with each paid renewal, paused while it is on hold, kept until the end date when it is set to cancel, cancelled or expired with it. WooCommerce Subscriptions does the billing -- the site's renewal engine, FlexWoo Stripe / PayPal-run subscriptions and Pro stay out of it, and a renewal order never starts a second membership. The subscription appears on the Subscriptions screens (gateway, renewal orders, a link to edit it); Pause / Resume there puts it on hold / reactivates it, cancelling the membership cancels it, and My Account > Subscriptions links to its page to manage the payment.
* Fixed: the admin subscription screen listed a refund of the first order as a "Renewal".
* Fixed: a subscription with a trial was first charged a full billing cycle after the purchase instead of when the trial ended (the membership itself ended at the trial end). The first renewal now falls on the trial end, or on the synchronized renewal day.
* Fixed: a plan limited to a number of payments counted the trial as one of them ("3 payments after a 7-day trial" took only 2 full payments).
* Fixed: a customer who had held the plan before (and so paid the full price, with no trial) got a trial-length first period; a membership that waited for approval got no trial or synchronized first period at all. Both now follow the same rule as the cart price.
* Fixed: with FlexWoo Memberships Pro inactive, a trial stored on a plan still shortened the first period although nothing charged the trial price.

= 1.38.0 =
* Added: the site's own renewal engine (moved here from FlexWoo Memberships Pro). Each renewal is a real WooCommerce order -- the subscription's product at the cycle's price, tax, the purchase's shipping for physical products, and a coupon line for a renewal discount -- charged to the customer's saved payment method off-session, or sent as a renewal invoice when there is none.
* Added: FlexWoo Stripe Payments renewals are charged through its renewal contract: cards, SEPA and other saved methods, 3-D Secure recovery (the customer gets one "confirm your payment" e-mail with a Pay link, not a second "payment failed" one), bank debits that settle later (a later failure puts the subscription back on the failed-payment schedule), and a failed renewal paid on its Pay page renews the subscription with the payment method used.
* Added: "Change payment method" for these subscriptions in My Account > Subscriptions, and a Renewal Payment Method card on the admin subscription screen.
* Changed: new subscriptions paid with FlexWoo Stripe Payments are renewed by the site instead of creating a Stripe Billing subscription. Existing Stripe Billing subscriptions paid with it move to the site at their next renewal (Stripe is told to stop at the end of the paid period; the customer is billed once per period). PayPal subscriptions are unchanged.
* Changed: renewal amounts are stored with 4 decimals; renewal reminder e-mails and Upcoming Payments show the coming cycle's price (with any renewal discount).
* Changed: FlexWoo Memberships Pro older than 1.16.0 is paused (it would run a second renewal engine).
* Developer: filters `flexwoomemberships_billing_capture_data`, `flexwoomemberships_renewal_discount`, `flexwoomemberships_renewal_use_scheduled_payment_hook`, `flexwoomemberships_renewal_requires_authentication`, `flexwoomemberships_migrate_native_stripe_subscription`; actions `flexwoomemberships_subscription_payment_method_changed`, `flexwoomemberships_native_stripe_subscription_migrated`, `flexwoomemberships_subscription_detail_after_upcoming`.

= 1.37.0 =
* Changed (WordPress.org guideline 5): this plugin no longer contains the code of Pro features. Drip timing, the credits override and protected files per product, signup fees / trials / one-time purchase / discount pricing, renewal synchronization, subscription boxes, gifting, the paywall mode, two-factor login codes, member self-service, bulk actions, members CSV import, the staging notice and the Pro reports moved into FlexWoo Memberships Pro. Pro plugs in through documented extension points (`FlexWooMemberships\Core\Extensions` services and `flexwoomemberships_*` filters and actions). Stored settings and data are untouched.
* Changed: Pro features are no longer shown as disabled (locked) controls. Every admin screen now shows a short "available in Pro" notice with an upgrade link in their place: plans (Lifetime type, signup fee, month / year durations, end-of-plan actions, credits, member discount, drip timing), product and post Membership Options, product Subscription Options, memberships and subscriptions lists (bulk actions, adding by hand), membership and subscription details, Memberships and Subscriptions Customization, Subscriptions Settings, General Settings, Restriction Rules, Restrict Products, Notifications and the Settings overview. Saving without Pro keeps every stored Pro setting as it is.
* Fixed: saving a Lifetime plan without Pro turned it into a Free plan, and saving a plan with a month / year duration turned it into the same number of days. Both are kept now; choosing them still needs Pro.
* Changed: an installed FlexWoo Memberships Pro older than 1.15.0 is paused (with a notice to update it) instead of loading against code that has moved.
* Removed: the Elementor and Gutenberg "Pro" placeholder widgets and blocks. Saved FlexWoo blocks stay closed (they print nothing) while Pro is not active, so locked content is never shown.
* Security: the native Stripe webhook accepts any of the `v1` signatures Stripe sends while a signing secret is being rolled.
* Security: with "Use external services to get user IP Address" on, a private-network peer's X-Forwarded-For is only believed for a known proxy (`flexwoomemberships_trusted_proxies`, or the new `flexwoomemberships_trust_private_network_proxies` filter).
* Changed: page scripts and styles are added through `wp_add_inline_script()` / `wp_add_inline_style()` instead of printed `<script>` / `<style>` tags.
* Added: translation template `languages/flexwoo-memberships.pot`.
* Changed: every code-standard exception now states its reason; `WC tested up to` 11.1.2; upgrade links point to flexwoomemberships.com.
* Compliance: WordPress Plugin Check (all categories incl. low-severity and experimental) reports no errors or warnings. Customization preview labels come from WooCommerce's own menu instead of borrowing its text domain; a missing translators comment added; redundant `suppress_filters` removed from two `get_posts()` calls; request values read with `sanitize_key( wp_unslash() )`.
* Readme: the opt-in public-IP lookup services are listed under External Services; the feature list shows what this plugin does and what Pro adds.

= 1.36.0 =
* Added: per-plan "Approval after purchase" (Memberships > Membership Plans > edit): use the store setting, automatic, or manual. A plan can require your approval while the rest stay automatic; gifts and native gateway payment notices follow the plan, and switching a plan off manual releases its waiting purchases. `flexwoomemberships_order_grants_access` now receives the plan as a fourth argument; new action `flexwoomemberships_plan_approval_mode_changed`. The plans table gains an `approval_mode` column (added automatically on update, database version 2.8.0).
* Fixed: saving a plan from the admin screen ended in a fatal error (class `SubscriptionsSettingsService` was used without its import in `PlanAdminService`).
* Fixed: every date comparison and offset now uses a single `SiteClock` helper instead of `current_time( 'timestamp' )`, which trusts the gmt_offset option and is an hour off after a daylight-saving change until Settings > General is saved again.
* Security: the native Stripe webhook refuses bodies over 1 MB before hashing or parsing them; the status-colour CSS is added with `wp_add_inline_style` (validated #hex colours only) instead of an echoed `<style>` block.
* Changed: Plans > edit > Permissions now says that chosen content is unlocked for the plan's members and that restricting it needs an Access Rule or a default restriction; Notifications shows a "switched off" hint on e-mails that are off (the paused and resumed e-mails are off by default).
* Added: Settings > General > Shop Settings > "Grant membership when the order is": "Paid (Processing or Completed) - automatic approval" (default, unchanged behaviour) or "Completed only - manual approval". With manual approval a paid purchase waits, without access, until the admin marks the WooCommerce order Completed; the member then gets the new "Membership approved" e-mail (Notifications > Membership Emails) instead of "Welcome". Gift purchases wait for the same approval, native Stripe/PayPal payment notices cannot activate a waiting membership, and switching back to automatic approval activates every membership that was waiting for an already paid order. New filter `flexwoomemberships_order_grants_access`, action `flexwoomemberships_grant_mode_changed`.
* Added: New User Approval (Settings > Security > Registration & Signup Restrictions). Choose Automatic (default, nothing changes), Email verification (new members must click the link we e-mail them before they can log in) or Manual approval (the site admin e-mail is notified; approve from the link or from Users > Approve / Pending approval, and the member gets an "Account Approved" e-mail). Only new self-registrations are held back; existing accounts, administrators, editors, WP-CLI, CSV imports and gift-claim accounts never are. This makes the Email Verification, Admin: New Registration Awaiting Approval and Account Approved templates work.
* Added: the Membership Expired e-mail is now sent when a membership reaches its end date (new action `flexwoomemberships_membership_expired`).
* Removed: the Welcome, Cancelled and Order Confirmation templates from Settings > Email Templates. Welcome and Cancelled were never sent from there (they are edited in the Membership Emails card on the same screen); order e-mails remain WooCommerce's.
* Added: the five "Subscription & Renewal" e-mails (renewal reminder, renewal receipt, payment failed, subscription cancelled, trial ending soon) are now actually sent. Renewal reminders and trial-ending notices go out the configured number of days ahead (new "Reminder e-mails" setting on Subscriptions > Settings, 0 = off); receipts, failed-payment and cancellation e-mails follow the Stripe, PayPal and saved-card events. Each is sent once per cycle and respects its template switch and custom text.
* Fixed: the per-member discount set on a membership (Memberships > edit > Member Discount) was saved but never used when calculating prices. It now replaces the plan's discount for that member's plan, in both the "original" and "latest" discount modes, and is ignored once the membership is expired or past its end date.
* Fixed: members flagged "expiring" lost access, discounts and download credits before their paid term ended; "expiring" now counts as entitled everywhere (new `MembershipStatus::entitled_statuses()`).
* Fixed: the admin "Resumed" status stored an invalid value and locked the member out; it now stores "active", extends the term by the paused days once and sends the "resumed" e-mail.
* Fixed: restricted pages and other supported post types appeared, with their body text, in search/archive listings.
* Fixed: drip ("available N days after signup") was never enforced for pages and posts; it now applies to page views, REST and listings.
* Fixed: opening Subscriptions > Activities on an empty ledger invented sample transactions. Nothing seeds automatically any more; the demo generators need `FLEXWOO_MEMBERSHIPS_DEMO_DATA` in wp-config.php.
* Fixed: the five subscription e-mail toggles could not be switched off (the saved flag was ignored).
* Fixed: the WooCommerce Subscriptions stand-in functions/classes were declared even when the real plugin is active, which could fatal it; they are now skipped when WooCommerce Subscriptions is active.
* Fixed: the default "original discount" mode used the plan's current percentage instead of the percentage recorded when the member joined; variable-product price ranges ignored the member discount.
* Fixed: the daily expiry job could expire a member while a saved-card renewal or its failed-payment retry was still pending (new filter `flexwoomemberships_expiry_protected_membership_ids`).
* Fixed: a NUL byte in a download path caused a PHP 8 fatal; `MemberRepository::for_order()` omitted the user id; plans without a name or valid type are refused at insert; "paragraph" wrappers are restored in the subscription customization editor texts.
* Added: `WC tested up to` 11.1.1.

= 1.35.2 =
* Security: Implemented two-way forward and reverse DNS verification for search engine bots to eliminate User-Agent paywall bypass.
* Security: Hardened RSS/Atom paywall feed protection so restricted content is suppressed by default.
* Enhancement: Multi-membership credit balance pooling and deferred credit deduction on one-time protected downloads.
* Enhancement: Fully wired frontend customer-facing subscription box builder and WooCommerce checkout pipeline.
* Enhancement: Hardened plan insertion schema with default arguments to prevent runtime warnings on partial payloads.

= 1.35.1 =
* Maintenance and stability release: comprehensive feature validation and verification across all core membership, access restriction, and download features.

= 1.34.1 =
* Admin: Memberships list Gateway column now shows a clean "Stripe"/"PayPal" label instead of the raw WooCommerce gateway title (e.g. "Credit / Debit Card (Stripe)").
* Admin: removed the underline styling from plan-name links in the Memberships list.
* Admin: Membership/Subscription Customization -- the Welcome Banner's Headline and Message fields now stack directly below the toggle instead of being squeezed into a narrow side-by-side layout.

= 1.32.1 =
* Security: fixed PayPal order/vault metadata lookups only recognizing another gateway plugin's meta key convention, leaving native PayPal subscriptions with no real order/vault reference. Now recognizes FlexWoo PayPal Payments' own meta keys.
* Security: subscription lifecycle events received directly from PayPal (a customer cancelling in the PayPal dashboard, or PayPal suspending a subscription) are now synced to the local membership -- previously invisible to this plugin. Requires FlexWoo PayPal Payments 0.4.3+.
* "Run expiration check now" (Tools > Membership & Access) now uses the granular subscriptions-management capability instead of requiring full Administrator access.

= 1.32.0 =
* Content Restriction: the Access Rules matrix is now the single authoritative source of truth -- content not explicitly granted is denied by default (BREAKING CHANGE; review your content after upgrading).
* Content Restriction: child pages now inherit their parent page's access rule when they have none of their own.
* Content Restriction: a plan's specific post/page/product/category/tag assignments now correctly sync into the Access Rules matrix, with clean removal on resave.
* Security: fixed restricted post content leaking via RSS/Atom feeds, comments, excerpts, and attachment page URLs.
* WooCommerce: blocked direct add-to-cart URL/POST bypasses of restricted products; variable product variations now inherit their parent's restriction.
* Added support for gating Custom Post Types via the new `flexwoomemberships_supported_post_types` filter.
* Added an option to hide restricted content from navigation menus.

= 1.31.1 =
* Content Restriction: fixed "Logged-in Members" access rules being bypassed for anonymous visitors.
* Content Restriction: fixed "Hide"/"Redirect" restriction modes incorrectly blocking eligible members and plan purchase products.
* Content Restriction: fixed "Everyone" access rules being incorrectly denied to members holding an unrelated plan (this affected WooCommerce's own My Account/Cart/Checkout pages).
* Memberships: fixed the My Account "Memberships" tab, credits ledger, and subscription-per-product limit all failing silently due to a database error.
* Internal: corrected the PlanType enum's constants to match the values actually used in the database.

= 1.31.0 =
* Security hardening: Database-atomic subscription membership creation under concurrent payment/order hooks.
* Security hardening: Dedicated webhook events table with atomic claiming for Stripe webhook events.
* Privacy: Added WordPress Privacy Policy suggested content and Personal Data Exporter & Eraser implementations.
* Compliance: Declared explicit WooCommerce Cart & Checkout Blocks compatibility and refined capability checks.

= 1.30.0 =
* Subscriptions: Added 10-digit unique alphanumeric Subscription No (SUB...) for all orders and records.
* Subscriptions: Added dedicated detailed subscription view page and quick-edit popup modal.
* Memberships: Pro feature locks for credit, discount, signup fee, and trial period.

= 1.29.0 =
* Restriction rules: Content Blocks selection support for non-members.

= 1.28.0 =
* Security and quality improvements for WordPress.org compliance.

= 1.26.6 =
* Permissions panel: the "After" drip-timing option is now cleaner in each edition.
* Plan Type cards: removed redundant helper text under the product picker.
* Linked-product picker: aligned search bar and Create Product button heights.

= 1.26.5 =
* Linked-product picker: View/Edit modal supports Regular and Sale Price.
* Subscription/Recurring linked products: picker includes subscription limits and pausing settings.
* Permissions panel: inline layout improvements for drip timing options.

= 1.26.4 =
* Membership Plans admin page: Paid Plan (Lifetime) panel support.
* Permissions panel: unified item, category, and tag picker access.
* Subscription/Recurring plan type: moved lifecycle settings to central settings card.

= 1.26.3 =
* Permissions panel: inline Immediately / After timing selection.
* Individual product/post/page drip override support.

= 1.26.2 =
* Enforce Pro capability gating cleanly on server and client.

= 1.26.1 =
* Product picker optimization and improved popup management.

= 1.26.0 =
* Release consistency updates and version synchronization.

= 1.24.0 =
* Added Native Stripe Subscriptions for recurring billing.

= Earlier versions =
* Please refer to CHANGELOG.md for the complete version history.

== Upgrade Notice ==

= 1.44.1 =
Shows the plan-level drip timing ("available after N days from signup") in the plan editor. No database changes.

= 1.44.0 =
Adds the Freemius SDK (optional opt-in, Pro licensing and updates) and shows prices again in the Products list when "Hide price and add to cart buttons for members" is on. Update together with FlexWoo Memberships Pro 1.21.0. No database changes.

= 1.43.3 =
Stops the "translation loading triggered too early" notices logged when the plugins are activated or updated. Update together with Pro 1.20.2. No database changes.

= 1.43.2 =
Security hardening from the WordPress.org review (sanitized hooks and JSON, escaped restricted content) and notices limited to FlexWoo screens. Works with Pro 1.20.0 or newer. No database changes.

= 1.43.1 =
Tools > Cron Jobs now recognises your host's cron job. Works with Pro 1.20.0. No database changes.

= 1.43.0 =
Adds a FlexWoo Memberships widget to the WordPress dashboard (signups, trials, renewals, cancellations and revenue this month). Update together with Pro 1.20.0. No database changes.

= 1.42.0 =
Adds FlexWoo Razorpay Payments support; admin Pause / Resume now reach Stripe, PayPal and Razorpay. Update together with Pro 1.19.1, Stripe 0.11.1, PayPal 0.8.1 and Razorpay 1.0.1. No database changes.

= 1.41.0 =
Adds Tools > Cron Jobs and stops deleted accounts leaving member rows behind. Update the other FlexWoo plugins too: Pro 1.19.0, Stripe Payments 0.11.0, PayPal Payments 0.8.0. No database changes.

= 1.40.0 =
New subscriptions are run by Stripe / PayPal (Subscriptions > Settings > Renewal payments). Update FlexWoo Stripe Payments to 0.10.0 and FlexWoo PayPal Payments to 0.7.0 first, then sync the Stripe webhook. Existing subscriptions are unchanged.

= 1.39.0 =
If you use FlexWoo Memberships Pro, update Pro to 1.17.0 first. If you use FlexWoo PayPal Payments, update it to 0.5.0.

= 1.38.0 =
If you use FlexWoo Memberships Pro, update Pro to 1.16.0 first: an older Pro is paused by this version.

= 1.37.0 =
If you use FlexWoo Memberships Pro, update Pro to 1.15.0 or newer first: an older Pro is paused by this version.

= 1.36.0 =
Adds one column to the plans table (runs automatically after updating). Nothing changes until you choose manual approval in Settings > General or on a plan; the new e-mails and New User Approval are off or automatic by default.
