Download the PHP package wpboilerplate/wpb-access-control without Composer

On this page you can find all versions of the php package wpboilerplate/wpb-access-control. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package wpb-access-control

wpb-access-control

Extensible per-resource access control library for WordPress plugins.

Answers one question: "Does this user have access to this resource?"

The library owns its own database table (managed by BerlinDB), ships WordPress role and user providers out of the box, exposes a REST API for managing rules from any client, and provides a ready-to-drop-in React component so consuming plugins get a full admin UI without writing any front-end code.


Table of Contents

  1. Requirements
  2. Installation
  3. PHP Setup
  4. Complete Integration Example
  5. Two Plugins on One Site
  6. Checking Access
  7. React Component UI
  8. Reading & Writing Rules (PHP)
  9. REST API
  10. Events
  11. Custom Providers
  12. Built-in Providers
  13. Important Notes
  14. Database Table Reference
  15. Upgrading from 1.x

Requirements

PHP 7.4+
WordPress 5.9+
Node.js 18+ (only needed if you rebuild the JS assets)
automattic/jetpack-autoloader ^6.0 (mandatory — see below)
berlindb/core ^2.0 (DB layer)

Installation

Your composer.json must include Jetpack Autoloader:

Why Jetpack Autoloader is mandatory

If two plugins install this library at different versions, PHP throws a fatal "class already declared" error. Jetpack Autoloader scans every installed plugin, finds all copies, and loads only the newest one.

In your plugin's main file, require the Jetpack Autoloader entry point — not the standard vendor/autoload.php:


PHP Setup

1. Boot the manager

Declare $manager at file scope (outside any closure) so every subsequent hook can capture it via use. Pass two arguments:

  1. A plugin-specific provider filter tag so your providers don't bleed into other plugins using the library.
  2. A per-plugin table slug (must match ^[a-z0-9_]{1,32}$) so your database table, object-cache group, and REST routes are isolated from every other plugin embedding the library.

AccessControlManager owns a RuleQuery internally. Instantiating it registers RuleTable via BerlinDB, which creates or upgrades the {prefix}my_plugin_access_control table automatically on admin_init.

Need to wait for other plugins first? Use a reference capture instead:

2. Register the REST API

Call register_rest_api() from rest_api_init to expose the wpb-ac/v1 endpoints. The consuming plugin decides whether to enable them.


Complete Integration Example

Below is a self-contained my-plugin.php showing all pieces wired together: initialising the manager, registering the REST API, enqueueing the React UI, rendering the mount point, and checking access.

Key points:

  • $manager is declared once at file scope; all hooks capture it with use ( $manager ).
  • add_submenu_page() (or add_menu_page()) returns the hook suffix — store it and compare in admin_enqueue_scripts to load assets only on your page.
  • vendor/autoload_packages.php is the Jetpack Autoloader entry point, not the standard vendor/autoload.php.

Two Plugins on One Site

The whole reason $table_slug exists: when two consumer plugins embed this library on the same WordPress install, each gets its own table, cache group, transient keys, and REST routes. They cannot collide. Pick a distinct slug per plugin — that is the only coordination required between them.

Plugin A — mcp-server

Plugin B — abilities-manager

What you actually get

Surface Plugin A (mcp) Plugin B (abilities)
Table {prefix}mcp_access_control {prefix}abilities_access_control
Cache group wpb_ac_mcp wpb_ac_abilities
Schema version option wpb_ac_mcp_db_version wpb_ac_abilities_db_version
REST routes /wpb-ac/v1/mcp/... /wpb-ac/v1/abilities/...
Providers filter tag mcp_server_access_control_providers abilities_manager_access_control_providers

Both managers can call $manager->register_rest_api() in the same request; the slug-scoped paths mean WordPress registers two distinct sets of routes instead of clobbering each other.

Picking a slug. Must match ^[a-z0-9_]{1,32}$ — lowercase ASCII letters, digits, and underscores; 1 to 32 characters. Invalid slugs throw \InvalidArgumentException at construction time, never reaching SQL. Recommend using your plugin's composer.json name (or a short form of it) so the slug is stable and obviously yours.


Checking Access

Access hierarchy

Step Condition Result
1 access_control_key is empty or 'everyone' Allow (public — no login required)
2 access_control_key is 'authenticated' Allow iff $user_id > 0, else Deny
3 User has manage_options (administrator) Always allow
4 User ID = 0 (unauthenticated) Deny
5 No provider registered for the configured key Deny
6 provider->user_has_access() Allow or Deny

React Component UI

The library ships a pre-built React component that renders a complete Access Control settings panel. Drop it into any WordPress admin page and it wires itself to the wpb-ac/v1 REST API automatically.

What it looks like

The component is driven by a single "Who can access" dropdown:

Dropdown option Extra UI
No user access added by admin Nothing — resource is locked (except admins)
Public (no login required) Nothing — anyone can access, including anonymous visitors
Any logged-in user Nothing — any authenticated WordPress user passes, no role/capability check
WordPress Role Checkboxes for each WordPress role
WordPress Capability Checkboxes for each WordPress capability (discovered across all roles)
Users Search-as-you-type field + selected-user tags

Custom providers registered via the filter also appear in the dropdown. If they expose options, checkboxes are rendered automatically.

Third-party integrations (BuddyBoss, MemberPress, LearnDash, LifterLMS, Paid Memberships Pro, Restrict Content Pro, WooCommerce Memberships, s2Member, Wishlist Member, Memberium) shipped in the library through v2.0.x have moved to a separate add-on plugin: AcrossAI User Access Pro (acrossai/user-access-pro). Install and activate it and the corresponding option appears in the dropdown automatically whenever the underlying plugin is active — no add_filter wiring required. See "Writing a third-party provider add-on" below to build your own.

Enqueue the built assets

The compiled assets live in assets/build/. The .asset.php file declares all required WordPress script dependencies so you never need to list them manually.

Getting the right hook suffix: add_menu_page() and add_submenu_page() both return a hook suffix string (e.g. "settings_page_my-plugin"). Capture that return value and compare it in admin_enqueue_scripts so assets load only on your page.

Render target

Add an empty <div> with the id wpb-access-control anywhere in your admin page template. The component mounts itself automatically.

Component props reference

Prop Type Required Default Description
pluginSlug string ✅ — Consumer slug — must match the PHP table_slug. Used to build every REST URL (/wpb-ac/v1/{pluginSlug}/...).
namespace string ✅ — Resource namespace, e.g. "mcp"
resourceKey string ✅ — Resource key within the namespace
restApiRoot string ✅ — WP REST API root URL (get_rest_url())
nonce string ✅ — wp_create_nonce('wp_rest')
title string "Access Control" Card heading
description string (MCP-server copy) Subtitle paragraph
saveLabel string "Save Access Control" Save button label
onSave Function — Callback (acKey, acOptions) after a successful save

Using the component as a JS import

If your plugin has its own webpack build, import the component directly:

Note: When importing directly the nonce middleware must be registered before the first apiFetch call. The auto-render path (index.js) handles this automatically.

Namespace slashes

Namespaces containing slashes (e.g. procureco/v1) are handled automatically by the component — each segment is encodeURIComponent-encoded so they reach the REST API as %2F.


Reading & Writing Rules (PHP)

Use RuleQuery when you need to read or write rules from PHP directly.

You can also access the same instance through the manager:


REST API

REST namespace: wpb-ac/v1. Every route is scoped under the consumer's table slug — {slug} in the paths below is the same string you pass to new AccessControlManager(...).

All endpoints require manage_options (administrator) by default. Use the wpb_access_control_rest_permission filter to override.

Endpoints

Method Path Description
GET /{slug}/rules/{namespace}/{key} Read the current rule
PUT /{slug}/rules/{namespace}/{key} Create or replace a rule
DELETE /{slug}/rules/{namespace}/{key} Clear a rule (revert to unrestricted)
DELETE /{slug}/namespaces/{namespace} Purge all rules for a namespace
GET /{slug}/providers List registered providers and their options
GET /{slug}/users?search=...&limit=10 Search WordPress users

Slashes in namespace: The {namespace} URL segment cannot contain literal slashes — encode them as %2F: .../my_plugin/rules/procureco%2Fv1/my-key. The {key} segment allows literal slashes.

Request / response shapes

GET /rules/{namespace}/{key}

PUT /rules/{namespace}/{key} — body:

Response:

DELETE /rules/{namespace}/{key}

DELETE /namespaces/{namespace}

GET /providers

GET /users?search=jane&limit=10


Authentication

WordPress admin (nonce)

Include the wp_rest nonce in the X-WP-Nonce header:

Application Passwords (external clients)


Code examples

cURL

PHP (wp_remote_request)

@wordpress/api-fetch

Vanilla fetch


Permission filter

Override who may call any endpoint:

Write authorization filter

Restrict which namespace/key pairs may be modified:


Events

wpb_access_control_denied

Fires whenever user_has_access() returns false (steps 3–5 of the hierarchy).

wpb_access_control_saved

Fires after any successful write via the REST API (PUT rule, DELETE rule, DELETE namespace). $ac_key is '' on a clear.


Custom Providers

Register

The filter tag must match the string passed to AccessControlManager. Register at init priority ≤ 4 (the filter fires at priority 5).

Contract (AbstractProvider)

Method Required Description
get_id(): string ✅ Unique slug stored as access_control_key
get_label(): string ✅ Human-readable label shown in the UI dropdown
get_options(): array ✅ [['id'=>'slug','label'=>'Name'], ...]; return [] for dynamic providers
user_has_access(int $user_id, array $selected): bool ✅ Core access check
is_available(): bool Return false when a required dependency is inactive

Example provider

Providers and their options are surfaced by GET /wpb-ac/v1/providers, so any front-end UI (including the built-in React component) can render the correct controls dynamically without hard-coding provider IDs.


Built-in Providers

Provider ID Class Description
wp_role WpRoleProvider Restricts by WordPress user role. Administrator is always bypassed.
wp_user WpUserProvider Restricts to specific WordPress users by ID.
wp_capability WpCapabilityProvider Restricts by one or more WordPress capability slugs. Users holding any of the selected capabilities pass.

Providers for BuddyBoss, MemberPress, LearnDash, LifterLMS, Paid Memberships Pro, Restrict Content Pro, WooCommerce Memberships, s2Member, Wishlist Member, and Memberium ship in the AcrossAI User Access Pro add-on plugin — not in this library. See "Writing a third-party provider add-on" below for how to add your own.

WpRoleProvider filters

Filter Signature Description
wpb_access_control_wp_role_options (array $options): array Add or remove selectable role options
wpb_access_control_wp_role_has_access (bool $result, int $user_id, array $selected): bool Override the final role-based decision

WpUserProvider

Options are user IDs stored as strings ("42"), not usernames or emails — sanitize_key() strips @ and ., so email addresses would be corrupted.

Filter Signature Description
wpb_access_control_wp_user_has_access (bool $result, int $user_id, array $selected): bool Override the final per-user decision

WpCapabilityProvider

Options are WordPress capability slugs (e.g. install_plugins, edit_posts, manage_options). The list is built dynamically from every role returned by wp_roles() — capabilities added by plugins like WooCommerce, Members, or User Role Editor appear automatically. Access is granted when user_can() returns true for any selected capability.

Filter Signature Description
wpb_access_control_wp_capability_options (array $options): array Add or remove selectable capability options (e.g. to surface a custom cap that no role holds yet)
wpb_access_control_wp_capability_has_access (bool $result, int $user_id, array $selected): bool Override the final capability-based decision

Writing a third-party provider add-on

Anyone can ship a WordPress plugin that adds providers to every consumer of wpb-access-control on the site, with no per-consumer bootstrap code. The reference implementation is AcrossAI User Access Pro, which packages 10 membership-plugin integrations this way.

The mechanism is one global filter registered by the library since v3.0.0:

It fires once per consumer instance during load_providers(), before the consumer-specific filter, and receives the running providers array plus the consumer's $table_slug. Any provider you append here is visible to that consumer's REST /providers endpoint and its React dropdown.

Minimal add-on skeleton

Providers extend \WPBoilerplate\AccessControl\AbstractProvider and implement get_id(), get_label(), get_options(), and user_has_access(). Override is_available() when the provider depends on an optional plugin — the library's REST layer forwards that flag to the React UI so unavailable options are hidden automatically.

To scope an add-on to specific consumers, inspect the $table_slug argument and short-circuit for consumers you don't want to inject into.

Consumers can still filter the resulting list per-instance via the consumer-specific filter passed to AccessControlManager, so they retain final say over what shows up in their own UI.


Important Notes

Filter tag isolation

Always pass a plugin-specific tag to AccessControlManager. Two plugins sharing the same filter tag will bleed providers into each other's checks.

Table management

BerlinDB handles all table creation and upgrades automatically on admin_init. No activation hook is needed — instantiating new AccessControlManager(...) is sufficient.

Caching

Always use RuleQuery::set_rule() and clear_rule(). Direct $wpdb writes bypass BerlinDB's object cache and leave it stale.

Administrator bypass is unconditional

Any user with manage_options always passes user_has_access() regardless of the stored rule. This cannot be disabled.

Uninstall cleanup

Each consuming plugin removes its own rows:

Multisite

The table uses $wpdb->prefix — each sub-site has its own {prefix}wpb_access_control table. Network-wide rules must be handled by the consuming plugin.


Database Table Reference

Table: {prefix}{slug}_access_control — one per consumer (e.g. wp_mcp_access_control, wp_abilities_access_control). DB layer: BerlinDB ^3.0 · Schema version: 202605120001

Each consumer's table is created on the first admin_init after the manager is instantiated. The schema is identical across consumers; only the name and the wpb_ac_{slug}_db_version option differ.

Column Type Notes
id BIGINT UNSIGNED PK AI
namespace VARCHAR(100) NOT NULL Plugin-scoped prefix, e.g. mcp, procureco/v1
key VARCHAR(255) NOT NULL Resource identifier within the namespace
access_control_key VARCHAR(100) NOT NULL Rule type slug — same for every row of a (ns, key) pair
access_control_value VARCHAR(255) NOT NULL One option per row; '' for the everyone / authenticated sentinels
created_at DATETIME BerlinDB-managed on INSERT
updated_at DATETIME BerlinDB-managed on UPDATE

Indexes: PRIMARY KEY (id) · UNIQUE (namespace, key(191), access_control_value) · KEY (namespace, key(191))

Rule storage convention

Logical state Rows in table
No rule configured No rows for that (namespace, key)
everyone One row: access_control_key='everyone', access_control_value=''
authenticated One row: access_control_key='authenticated', access_control_value=''
wp_role + ['editor','author'] Two rows, both access_control_key='wp_role'; values 'editor', 'author'
wp_user + ['1','42'] Two rows, both access_control_key='wp_user'; values '1', '42'

Upgrading from 1.x

v2.0.0 introduces a required $table_slug constructor argument. Each consumer plugin now owns its own table, object-cache group, and REST route prefix — fixing the silent collision when two plugins embed the library on the same WordPress install.

1. Update the manager constructor

Invalid slugs throw \InvalidArgumentException immediately.

2. Update wpbAcConfig / React props

3. Update REST URLs

Every endpoint moves under /wpb-ac/v1/{slug}/...:

4. (Optional) Migrate existing rows

The library does not auto-migrate from {prefix}wpb_access_control. Run a one-off SQL copy from your plugin's update routine, filtering by the namespaces your plugin owns:

Drop the legacy table only after every consumer plugin on the site has upgraded — otherwise an un-upgraded plugin will lose its rules.


All versions of wpb-access-control with dependencies

PHP Build Version
Package Version
Requires php Version >=8.1
automattic/jetpack-autoloader Version ^6.0
berlindb/core Version ^3.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package wpboilerplate/wpb-access-control contains the following files

Loading the files please wait ...