feat(db,rest,ui)!: per-consumer table + slug-scoped REST routes - #19
Merged
Merged
Conversation
Adds a focused side-by-side example (mcp + abilities) showing what each
consumer plugin's bootstrap, React config, and resulting surfaces (table,
cache group, REST routes) look like when both embed the library. This is
the canonical use case the slug parameter exists to solve, so the README
should call it out directly instead of leaving readers to infer it from
the Complete Integration Example.
Also:
- Adds the new section + the (already-present) "Upgrading from 1.x" to
the Table of Contents.
- Documents the slug pattern (^[a-z0-9_]{1,32}$) and where the validation
fires (InvalidArgumentException at construction time).
Refs: #17
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #17.
Summary
AccessControlManagernow requires a second constructor argument — a per-consumer$table_slug. Each embedding plugin gets its own database table, object-cache group, transient prefix, and REST route prefix. Previously every consumer wrote into the single shared{prefix}wpb_access_controltable and registered the same/wpb-ac/v1/...routes, causing silent collisions when two plugins embedded the library on the same WordPress install.The README adds a focused "Two Plugins on One Site" section showing two consumers (
mcp,abilities) side-by-side — bootstrap, React config, and the resulting tables / cache groups / REST routes — so the use case the slug exists to solve is documented directly.What changes
src/Slug.php(NEW) —Slug::sanitize()validates^[a-z0-9_]{1,32}$and throws\InvalidArgumentExceptionon invalid input.src/Database/Rule/RuleTable.php— ctor accepts$table_slug; sets$name({slug}_access_control) and$db_version_key(wpb_ac_{slug}_db_version) per instance.src/Database/Rule/RuleQuery.php— ctor accepts$table_slug; sets$table_nameand$cache_group(wpb_ac_{slug}); replaces single static table-setup flag with a per-slug registry; folds slug into thetransient_keyhash.src/AccessControlManager.php— second required ctor arg$table_slug; newget_table_slug()getter; threads slug intoRuleQuery+RulesController.src/RestApi/RulesController.php— accepts the slug; everyregister_rest_routecall now uses'/{slug}/...'.js/AccessControl.js+js/components/UserSearchPanel.js+js/index.js— new requiredpluginSlugprop /wpbAcConfigfield; everyapiFetchURL carries the slug segment. Auto-render path bails with aconsole.errorwhen missing.SlugTest(17 cases), newRuleQueryConstructorTest(8 cases including two-instance isolation), 2 newregister_routestests inRulesControllerTestverifying the slug prefix on every route group and distinct slugs producing distinct paths.README.md— new "Two Plugins on One Site" section + "Upgrading from 1.x" section + every PHP/JS/REST example updated to include the slug.CHANGELOG.md—2.0.0entry with BREAKING banner, migration steps, and rationale.Migration
Documented in detail in
README.md→ "Upgrading from 1.x". TL;DR:new AccessControlManager(...).pluginSlugtowpbAcConfig(or the React component prop)./wpb-ac/v1/...to/wpb-ac/v1/{slug}/....INSERT ... SELECTto copy rows from the legacy{prefix}wpb_access_controltable.The library does NOT auto-migrate — consumers know which namespaces they own.
Re-merge notes (action required before merge)
This branch was originally merged as v2.0.0 (#16) and immediately reverted (#18). Because the branch was not rebased after the revert, merging as-is will appear as a no-op for the v2.0.0 code (Git treats it as already-merged). Pick one before merging:
Test plan
composer test— 190 tests / 267 assertions, all green (was 160/218 before this branch)npm run build— wp-scripts compiles cleanly with the newpluginSlugprop wiring'','Has-Caps','../etc/passwd'all throw with a readable message🤖 Generated with Claude Code