=== PBJ Access Control ===
Contributors: pbjtech
Tags: membership, restrict content, pages, woocommerce, login, approval, notifications
Requires at least: 5.5
Tested up to: 6.7
Requires PHP: 7.4
Stable tag: 2.4.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Gate pages behind login, block WooCommerce to logged-out visitors (optionally with access to the registration form), customise the restricted-content message, and require admin approval for new registrations — with IP and detected location captured for each signup.

== Description ==

PBJ Access Control gives you four levers in one plugin:

* **Per-page login gating** — a checkbox on every Page to lock it to logged-in users only. Logged-out visitors see your customised restricted-content message.
* **WooCommerce blocking** — when enabled, the entire Woo area (shop, cart, checkout, account) is gated behind login. An opt-in setting keeps the My Account registration form reachable so visitors can still create an account.
* **Customised restricted message** — a WYSIWYG editor for the message shown to logged-out visitors, with a one-click "Reset to default" button. Inline `<style>` tags are stripped server-side for safety.
* **Admin approval for new registrations** — newly registered users are marked pending and cannot log in until approved on the **Users → PBJ User Approvals** page. The signup IP address and detected city / region / country are captured automatically and shown alongside each pending user, so admins can spot bot signups or out-of-region accounts at a glance. Email notifications can be routed to any number of addresses.

The plugin is safe-mode by design: hooks defer to `init`, admin / AJAX / REST requests are never blocked, and editor / WooCommerce fallbacks keep activation safe on minimal sites.

== Installation ==

1. Upload `pbj-access-control.zip` via Plugins → Add New → Upload Plugin, or extract into `wp-content/plugins/`.
2. Activate the plugin.
3. Go to **Settings → Access Control** to choose what to block and customise the message.
4. Optional: toggle **Require admin approval for new registrations**, then visit **Users → PBJ User Approvals** to review pending accounts.

== Upgrade Notice ==

= 2.2.0 =
Adds the built-in User Guide tab on Settings → Access Control. Includes all
2.1.0 security hardening — upgrade straight to this one.

= 2.1.0 =
Security hardening: restricted pages no longer leak their content through the
REST API, search results, or oEmbed, and blocked responses can no longer be
stored by page/edge caches (incl. pbj-seo's LiteSpeed module). Recommended for
every install.

= 2.0.0 =
Full refactor to multi-file structure with a self-hosted updater. Settings, per-page restriction toggles, and existing pending users are preserved by an automatic schema migration. Adds IP address and detected location columns to the User Approvals page and the approval-notification email. Highly recommended upgrade.

= 1.06.5 =
Fix: add missing settings field callbacks to prevent activation/admin fatals.

== Changelog ==

= 2.4.0 =
* Added: Setup checklist at the top of Settings → Access Control — live status
  rows (green tick / red triangle) showing how many Pages are currently
  restricted, whether WooCommerce blocking is on (shown only when WooCommerce
  is active), whether registration approval is on plus how many users are
  waiting in the approval queue, and whether the restricted-content message is
  set — each with a one-line plain-English explanation and a button linking
  straight to where you fix it.
* Added: a numbered "How to use this plugin" walkthrough in the same card
  covering the full workflow: restrict a Page via its meta box, optionally
  block WooCommerce, customise the visitor message, turn on registration
  approval, and approve/deny signups (with IP + location) from
  Users → PBJ User Approvals.
* Improved: every settings field now carries a plain-English "what it does"
  description, so nothing on the Settings tab is left to guessing.

= 2.3.0 =
* Added a License section in the plugin's settings where you enter your PBJ license key to unlock automatic updates. The plugin is fully functional without a key; a key covers up to 3 sites, and on pbj.tech itself no key is required.

= 2.2.0 =
* Added: built-in User Guide — a new tab on Settings → Access Control covering
  page restriction, WooCommerce gating, the approvals workflow, verification,
  troubleshooting, and a quick reference. Also linked from the Plugins list row.

= 2.1.0 =
* Security: restricted pages' content and excerpt are now blanked in REST API
  responses (`/wp-json/wp/v2/pages/<id>`) for logged-out requests — previously
  the full content was publicly readable there even though the page itself was
  blocked. The oEmbed endpoint is blanked the same way.
* Security: restricted pages are excluded from front-end search results for
  logged-out visitors and emit `noindex` robots directives.
* Fixed: blocked responses now send `X-LiteSpeed-Cache-Control: no-cache` +
  `nocache_headers()` and hook pbj-seo's `pbj_seo_cacheable` filter, so a
  page/edge cache can never store the 403 message as a public page (or serve a
  cached anonymous copy to logged-in members).
* Added: applicants now receive a one-line "account approved" email when an
  admin approves them.
* Added: expired approve/deny email links (nonces last ~24h) now show an
  "expired, use the buttons below" notice instead of silently doing nothing.
* Added: `pbj_access_control_post_types` filter to extend per-entry restriction
  beyond Pages, and `pbj_access_control_login_redirect` filter to 302 blocked
  visitors to the login form (with redirect back) instead of the 403 message.
* Fixed: the message sanitizer no longer strips arbitrary `{...}` from message
  text (it destroyed shortcode args / literal braces); only CSS-shaped rules
  are removed.
* Removed: `sslverify => false` on the (plain-HTTP) ip-api lookup; unused
  `Domain Path` header.

= 2.0.0 =
* Refactored: single-file plugin split into a bootstrap + `includes/class-*.php` files matching the rest of the PBJ plugin suite (orchestrator, frontend, admin, approvals, updater).
* Added: signup IP address and best-effort city / region / country are captured for every new registration and surfaced as columns on **Users → PBJ User Approvals**. The same fields are included in the approval-notification email so admins can triage from inbox.
* Added: self-hosted updater. Point the `Update URI` plugin header at a JSON manifest hosted on your server to enable real auto-updates (see `includes/class-pbj-access-control-updater.php` header docblock for the expected shape). Falls back silently when no manifest is available.
* Added: `Update URI` plugin header to lock the slug — no risk of a same-slug WordPress.org plugin auto-replacing this one.
* Added: settings schema versioning + idempotent migration runner (`pbj_access_control_db_version` option). Migration `1 → 2` ensures all new defaults exist on existing installs and runs the message-content CSS-bleed scrub once instead of every load.
* Added: migration hook `do_action( 'pbj_access_control_migrated', $from, $to )` for downstream consumers.
* Added: `uninstall.php` cleans up plugin options, the updater transient, and the cached ip-api lookups.
* Changed: WP 6.7+ textdomain loading moved to `init` priority 1 to avoid the "loaded too early" notice.

= 1.06.5 =
* Fix: add missing settings field callbacks to prevent activation/admin fatals.
* Safe-mode: hooks deferred to init; never blocks admin/AJAX/REST; editor fallback; CSS bleed sanitizer.
