abilities.php
WordPress Abilities API integration.
Registers one read-only ability: which blocks the calling user may actually insert, and how the restriction is configured per role.
The effective answer is produced BY the filter this plugin registers, not by a re-derivation of it. Two rules make a re-derivation get it wrong:
- A user's blocked set is the INTERSECTION across their roles, not the union. A user holding two roles is blocked only from what both roles block, and a single role with an empty list lifts the restriction entirely.
manage_optionsexempts a user completely, and that exemption is itself filterable, so a site can move it.
Tags
Table of Contents
Constants
- JPKCOM_ALLOWBLOCKS_ABILITY_CATEGORY : mixed = 'jpkcom-content'
- Ability category.
- JPKCOM_ALLOWBLOCKS_ABILITY_INPUT_KEYS : mixed = ['jpkcom-allow-blocks/list-allowed-blocks' => []]
- Top-level input keys the ability declares.
Functions
- jpkcom_allow_blocks_abilities_enabled() : bool
- Decide whether the ability should be registered at all.
- jpkcom_allow_blocks_ability_log() : void
- Write a debug line, and only with WP_DEBUG.
- jpkcom_allow_blocks_ability_error() : WP_Error
- Build a WP_Error carrying an HTTP status.
- jpkcom_allow_blocks_ability_boundary() : array<string, mixed>|WP_Error
- Turn a Throwable out of the callback into a WP_Error.
- jpkcom_allow_blocks_ability_capability() : bool
- Check the capability required to run the ability.
- jpkcom_allow_blocks_ability_meta() : array<string, mixed>
- Build the meta array for the ability.
- jpkcom_allow_blocks_ability_normalise_input() : array<string, mixed>|null
- Bring the value core hands the callback into array form.
- jpkcom_allow_blocks_ability_validate_input_keys() : true|WP_Error
- Refuse a top-level input key the ability does not declare.
- jpkcom_allow_blocks_ability_list_inner() : array<string, mixed>|WP_Error
- Report which blocks the calling user may insert, and how roles are configured.
- jpkcom_allow_blocks_ability_permission() : bool
- Permission callback.
- jpkcom_allow_blocks_ability_list() : array<string, mixed>|WP_Error
- Execute callback.
- jpkcom_allow_blocks_get_ability_definitions() : array<string, array<string, mixed>>
- Build the registration arguments.
- jpkcom_allow_blocks_register_ability_category() : void
- Register the shared category, unless a sibling plugin already did.
- jpkcom_allow_blocks_register_abilities() : void
- Register the ability.
Constants
JPKCOM_ALLOWBLOCKS_ABILITY_CATEGORY
Ability category.
public
mixed
JPKCOM_ALLOWBLOCKS_ABILITY_CATEGORY
= 'jpkcom-content'
Categories are global and registration is FIRST-WINS, so this goes through wp_has_ability_category() rather than assuming.
Tags
JPKCOM_ALLOWBLOCKS_ABILITY_INPUT_KEYS
Top-level input keys the ability declares.
public
mixed
JPKCOM_ALLOWBLOCKS_ABILITY_INPUT_KEYS
= ['jpkcom-allow-blocks/list-allowed-blocks' => []]
Cross-checked against the registered schema by tests/test-abilities.php.
Tags
Functions
jpkcom_allow_blocks_abilities_enabled()
Decide whether the ability should be registered at all.
jpkcom_allow_blocks_abilities_enabled() : bool
Both spellings of the kill switch are honoured. README.md and CLAUDE.md have always documented the separated JPKCOM_ALLOW_BLOCKS_ABILITIES, but 3.1.0 shipped a check for the run-together JPKCOM_ALLOWBLOCKS_ABILITIES, so the documented constant did nothing and only the undocumented one worked. Accepting both keeps a 3.1.0 workaround working while making the documented spelling authoritative.
The plugin's constant naming is genuinely split, which is how the slip survived review: the main file uses JPKCOM_ALLOW_BLOCKS_* (VERSION, PATH, IMPORT_MAX_BYTES), while the two other constants in THIS file run the words together (JPKCOM_ALLOWBLOCKS_ABILITY_CATEGORY, _ABILITY_INPUT_KEYS). Writing the local spelling here was the natural mistake to make.
Tags
Return values
bool —True when registration should proceed.
jpkcom_allow_blocks_ability_log()
Write a debug line, and only with WP_DEBUG.
jpkcom_allow_blocks_ability_log(string $message) : void
Parameters
- $message : string
-
Message.
Tags
jpkcom_allow_blocks_ability_error()
Build a WP_Error carrying an HTTP status.
jpkcom_allow_blocks_ability_error(string $code, string $message[, int $status = 400 ]) : WP_Error
Without data['status'] rest_ensure_response() defaults to 500, and a 5xx tells an agent "transient fault, retry unchanged" - the opposite of what a caller mistake needs to hear.
Parameters
- $code : string
-
Error code.
- $message : string
-
Message.
- $status : int = 400
-
HTTP status.
Tags
Return values
WP_Error —Error.
jpkcom_allow_blocks_ability_boundary()
Turn a Throwable out of the callback into a WP_Error.
jpkcom_allow_blocks_ability_boundary(callable $body, string $ability) : array<string, mixed>|WP_Error
Parameters
- $body : callable
-
Callback.
- $ability : string
-
Ability name.
Tags
Return values
array<string, mixed>|WP_Error —Result or error.
jpkcom_allow_blocks_ability_capability()
Check the capability required to run the ability.
jpkcom_allow_blocks_ability_capability(string $ability) : bool
edit_posts: the answer is only meaningful to someone who edits content,
and it reports how the site restricts every role, which is configuration
rather than visitor-facing content.
Parameters
- $ability : string
-
Ability name.
Tags
Return values
bool —True when the current user may run it.
jpkcom_allow_blocks_ability_meta()
Build the meta array for the ability.
jpkcom_allow_blocks_ability_meta(string $ability) : array<string, mixed>
All three annotations explicit: they default to null and the REST run controller derives the HTTP verb from them, so without readonly the run route would be POST-only.
Parameters
- $ability : string
-
Ability name.
Tags
Return values
array<string, mixed> —Meta array.
jpkcom_allow_blocks_ability_normalise_input()
Bring the value core hands the callback into array form.
jpkcom_allow_blocks_ability_normalise_input(mixed $input) : array<string, mixed>|null
normalize_input() substitutes the schema's top-level default when the input is exactly null, and that default is a stdClass - so the callback receives an object and must read it.
Parameters
- $input : mixed
-
Raw input.
Tags
Return values
array<string, mixed>|null —Array form, or null when unusable.
jpkcom_allow_blocks_ability_validate_input_keys()
Refuse a top-level input key the ability does not declare.
jpkcom_allow_blocks_ability_validate_input_keys(array<string, mixed> $input, array<string|int, string> $allowed) : true|WP_Error
Parameters
- $input : array<string, mixed>
-
Raw input.
- $allowed : array<string|int, string>
-
Declared keys.
Tags
Return values
true|WP_Error —True when every key is declared.
jpkcom_allow_blocks_ability_list_inner()
Report which blocks the calling user may insert, and how roles are configured.
jpkcom_allow_blocks_ability_list_inner([mixed $input = null ]) : array<string, mixed>|WP_Error
The effective list comes from running the plugin's OWN filter with true
as the incoming value - "everything is allowed so far" - so the answer is
whatever the editor would actually be handed. It is not re-derived from the
option, and that matters twice over:
- The blocked set for a user is the INTERSECTION across their roles. A user with two roles is blocked only from what both block, and one role with an empty list lifts the restriction entirely. A union would be the opposite answer.
- The exemption is
manage_optionsand is itself filterable, so a site can move it somewhere this ability has no way to predict.
Parameters
- $input : mixed = null
-
Ability input.
Tags
Return values
array<string, mixed>|WP_Error —Result.
jpkcom_allow_blocks_ability_permission()
Permission callback.
jpkcom_allow_blocks_ability_permission([mixed $input = null ]) : bool
Parameters
- $input : mixed = null
-
Validated input, unused.
Tags
Return values
bool —True when the current user may run the ability.
jpkcom_allow_blocks_ability_list()
Execute callback.
jpkcom_allow_blocks_ability_list([mixed $input = null ]) : array<string, mixed>|WP_Error
Parameters
- $input : mixed = null
-
Ability input.
Tags
Return values
array<string, mixed>|WP_Error —Result.
jpkcom_allow_blocks_get_ability_definitions()
Build the registration arguments.
jpkcom_allow_blocks_get_ability_definitions() : array<string, array<string, mixed>>
Reads no WordPress state and touches no registry, which is what lets the CI harness assert the shape without a WordPress installation.
Tags
Return values
array<string, array<string, mixed>> —Ability name => registration args.
jpkcom_allow_blocks_register_ability_category()
Register the shared category, unless a sibling plugin already did.
jpkcom_allow_blocks_register_ability_category() : void
Tags
jpkcom_allow_blocks_register_abilities()
Register the ability.
jpkcom_allow_blocks_register_abilities() : void
wp_register_ability() returns null on EVERY failure path and reports only through _doing_it_wrong(), which is silent in production - and so is the debug log without WP_DEBUG.