Skip to content

fix(release): restore v2.0.0 code dropped by revert+merge - #20

Merged
raftaar1191 merged 1 commit into
mainfrom
fix/restore-v2.0.0-code
Jun 30, 2026
Merged

raftaar1191 merged 1 commit into
mainfrom
fix/restore-v2.0.0-code

Conversation

@raftaar1191

Copy link
Copy Markdown
Contributor

Why

PR #19 merged `feat/per-consumer-tables` into `main`, but the merge brought only the README docs — the entire v2.0.0 source tree was missing afterward. Root cause: the branch was never rebased after the v2.0.0 revert (#18), so Git treated the v2.0.0 code as already-merged and skipped it.

After PR #19 landed on `c8694a3`, `main` had a README describing per-consumer tables, slug-scoped REST routes, and `Slug::sanitize()` — none of which existed in the code.

What this PR does

Cherry-picks `2d7e48b` (the original v2.0.0 squashed commit) onto current `main`. That single commit re-introduces:

  • `src/Slug.php` (new) — `Slug::sanitize()` validator
  • `src/Database/Rule/RuleTable.php` — per-slug `$name` + `$db_version_key`
  • `src/Database/Rule/RuleQuery.php` — per-slug `$table_name`, `$cache_group`, transient key
  • `src/AccessControlManager.php` — required `$table_slug` ctor arg + `get_table_slug()`
  • `src/RestApi/RulesController.php` — slug-prefixed routes
  • `js/AccessControl.js`, `js/components/UserSearchPanel.js`, `js/index.js` — `pluginSlug` prop / `wpbAcConfig` field
  • `tests/Unit/SlugTest.php` (17 cases) + `tests/Unit/Database/Rule/RuleQueryConstructorTest.php` (8 cases) + 2 new `RulesControllerTest` cases
  • `CHANGELOG.md` v2.0.0 entry

The README auto-merged cleanly — "Two Plugins on One Site" and "Upgrading from 1.x" sections (already on main from #19) are preserved alongside the slug-aware code examples re-added by this commit.

Verification

```sh

Before this PR (on main)

ls src/Slug.php # No such file or directory
grep table_slug src/AccessControlManager.php # no matches

After this PR

ls src/Slug.php # exists
grep -c table_slug src/AccessControlManager.php # 9
```

After merge

Tag `v2.0.0` on the resulting main commit and publish the GitHub release.

🤖 Generated with Claude Code

BREAKING: each consumer plugin now owns its own database table, object-cache
group, and REST route prefix. AccessControlManager requires a second
constructor argument $table_slug (^[a-z0-9_]{1,32}$). Existing v1.x
consumers that pass only the providers filter tag will fail with
ArgumentCountError on upgrade.

Previously every consumer wrote into one shared {prefix}wpb_access_control
table and registered the same /wpb-ac/v1/... routes — two plugins on the
same WordPress install would collide on rules, on cached payloads (single
wpb_access_control cache group), and on REST handlers (last-loaded-wins).

Migration:

  // PHP bootstrap
  $manager = new AccessControlManager(
      'my_plugin_access_control_providers',
      'my_plugin'  // slug; pick one per plugin
  );

  // wpbAcConfig / React props
  wp_localize_script( 'wpb-ac-ui', 'wpbAcConfig', [
      'pluginSlug'  => 'my_plugin',  // NEW
      // …existing fields…
  ] );

  // REST URLs: /wpb-ac/v1/rules/... → /wpb-ac/v1/{slug}/rules/...

Optional one-off SQL copy from {prefix}wpb_access_control to the new
per-consumer table; see README's "Upgrading from 1.x" section. The
library does NOT auto-migrate — it doesn't know which namespaces each
consumer owns.

Files:
- src/Slug.php — new helper, Slug::sanitize() validates ^[a-z0-9_]{1,32}$
  and throws \InvalidArgumentException on invalid input.
- src/Database/Rule/RuleTable.php — constructor accepts $table_slug;
  derives $name and $db_version_key per instance; removes hardcoded
  defaults.
- src/Database/Rule/RuleQuery.php — constructor accepts $table_slug;
  derives $table_name and $cache_group; replaces single static
  $table_setup flag with per-slug registry; folds slug into the
  transient_key hash so cache cannot collide across consumers.
- src/AccessControlManager.php — second required constructor arg
  $table_slug; new get_table_slug() getter; passes the slug into
  RuleQuery + RulesController.
- src/RestApi/RulesController.php — accepts slug; every register_rest_route
  call now uses '/{slug}/rules/…', '/{slug}/providers', '/{slug}/users',
  '/{slug}/namespaces/{namespace}'.
- js/AccessControl.js + js/components/UserSearchPanel.js + js/index.js —
  new required pluginSlug prop / wpbAcConfig field; every apiFetch URL
  carries the slug segment. Auto-render path bails with a clear console
  error when pluginSlug is missing.
- tests: new SlugTest (17 cases covering accept/reject + error message
  shape), new RuleQueryConstructorTest (8 cases asserting slug-driven
  table_name / cache_group / two-instance isolation + slug validation
  propagation through the ctor), 2 new register_routes tests in
  RulesControllerTest (slug prefix on all four route groups + distinct
  prefix per slug). Existing tests untouched — Brain Monkey suites use
  newInstanceWithoutConstructor / disableOriginalConstructor / partial
  mocks, so the new required ctor arg is transparent to them.

PHPUnit: 190 tests / 267 assertions all green (was 160/218). JS assets
rebuilt via wp-scripts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@raftaar1191
raftaar1191 merged commit 4f0e94e into main Jun 30, 2026
5 checks passed
@raftaar1191
raftaar1191 deleted the fix/restore-v2.0.0-code branch June 30, 2026 18:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant