abilities.php
WordPress Abilities API integration.
Two read-only abilities: the language vocabulary this site actually uses, and the translation sets whose hreflang output comes out incomplete.
The second is the one worth having. The emitter resolves each version to a BCP 47 tag and keeps the FIRST entry per tag, so two versions that map to the same tag - two de_DE posts, or de_DE plus de_DE_formal - contribute one entry and the other URL gets no annotation at all. That is deliberate (a contradictory pair would be worse) but it is also silent: nothing in the admin says a page was dropped. Same for a set with no version in the site's default language, which is emitted without x-default on purpose.
Tags
Table of Contents
Constants
- JPKCOM_SIMPLELANG_ABILITY_CATEGORY : mixed = 'jpkcom-content'
- Ability category.
- JPKCOM_SIMPLELANG_ABILITY_INPUT_KEYS : mixed = ['jpkcom-simple-lang/list-languages' => [], 'jp...
- Top-level input keys each ability declares.
- JPKCOM_SIMPLELANG_ABILITY_PER_PAGE_DEFAULT : mixed = 20
- Default page size for the set check.
- JPKCOM_SIMPLELANG_ABILITY_PER_PAGE_MAX : mixed = 100
- Largest page size honoured.
- JPKCOM_SIMPLELANG_ABILITY_SCAN_LIMIT : mixed = 2000
- Largest number of linked posts examined in one call.
Functions
- jpkcom_simplelang_abilities_enabled() : bool
- Decide whether the abilities should be registered at all.
- jpkcom_simplelang_ability_log() : void
- Write a debug line, and only with WP_DEBUG.
- jpkcom_simplelang_ability_error() : WP_Error
- Build a WP_Error carrying an HTTP status.
- jpkcom_simplelang_ability_boundary() : array<string, mixed>|WP_Error
- Turn a Throwable out of a callback into a WP_Error.
- jpkcom_simplelang_ability_json_object() : array<string, mixed>|stdClass
- Wrap an empty map so it encodes as {} rather than [].
- jpkcom_simplelang_ability_capability() : bool
- Check the capability required to run an ability.
- jpkcom_simplelang_ability_meta() : array<string, mixed>
- Build the meta array for an ability.
- jpkcom_simplelang_ability_normalise_input() : array<string, mixed>|null
- Bring the value core hands the callback into array form.
- jpkcom_simplelang_ability_validate_input_keys() : true|WP_Error
- Refuse a top-level input key the ability does not declare.
- jpkcom_simplelang_ability_enabled_post_types() : array<string|int, string>
- The post types language selection is enabled for.
- jpkcom_simplelang_ability_describe_locale() : array<string, mixed>
- Describe a locale the way the front end resolves it.
- jpkcom_simplelang_ability_list_languages_inner() : array<string, mixed>|WP_Error
- Report which languages this site actually uses.
-
jpkcom_simplelang_ability_build_sets()
: array{sets: array
, scanned: int, truncated: bool} - Collect the translation sets on this site.
- jpkcom_simplelang_ability_inspect_set() : array<string, mixed>
- Report what the hreflang output for one set will and will not contain.
- jpkcom_simplelang_ability_check_sets_inner() : array<string, mixed>|WP_Error
- Report the translation sets whose hreflang output comes out incomplete.
- jpkcom_simplelang_ability_permission_list_languages() : bool
- Permission callback for list-languages.
- jpkcom_simplelang_ability_permission_check_sets() : bool
- Permission callback for check-translation-sets.
- jpkcom_simplelang_ability_list_languages() : array<string, mixed>|WP_Error
- Execute callback for jpkcom-simple-lang/list-languages.
- jpkcom_simplelang_ability_check_sets() : array<string, mixed>|WP_Error
- Execute callback for jpkcom-simple-lang/check-translation-sets.
- jpkcom_simplelang_get_ability_definitions() : array<string, array<string, mixed>>
- Build the registration arguments for both abilities.
- jpkcom_simplelang_register_ability_category() : void
- Register the shared category, unless a sibling plugin already did.
- jpkcom_simplelang_register_abilities() : void
- Register both abilities.
Constants
JPKCOM_SIMPLELANG_ABILITY_CATEGORY
Ability category.
public
mixed
JPKCOM_SIMPLELANG_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_SIMPLELANG_ABILITY_INPUT_KEYS
Top-level input keys each ability declares.
public
mixed
JPKCOM_SIMPLELANG_ABILITY_INPUT_KEYS
= ['jpkcom-simple-lang/list-languages' => [], 'jpkcom-simple-lang/check-translation-sets' => ['page', 'per_page']]
Cross-checked against the registered schemas by tests/test-abilities.php. additionalProperties is deliberately not declared on the schema that carries properties: validate_input() runs before the execute callback and would preempt the guard below, replacing a message naming the accepted keys with core's "not a valid property of the object".
Tags
JPKCOM_SIMPLELANG_ABILITY_PER_PAGE_DEFAULT
Default page size for the set check.
public
mixed
JPKCOM_SIMPLELANG_ABILITY_PER_PAGE_DEFAULT
= 20
Tags
JPKCOM_SIMPLELANG_ABILITY_PER_PAGE_MAX
Largest page size honoured.
public
mixed
JPKCOM_SIMPLELANG_ABILITY_PER_PAGE_MAX
= 100
Tags
JPKCOM_SIMPLELANG_ABILITY_SCAN_LIMIT
Largest number of linked posts examined in one call.
public
mixed
JPKCOM_SIMPLELANG_ABILITY_SCAN_LIMIT
= 2000
Building the sets means reading every post that carries a translation link, which is unbounded on a large site. The cap is reported back rather than applied silently: an answer that stopped early while looking complete is the failure this field exists to prevent.
Tags
Functions
jpkcom_simplelang_abilities_enabled()
Decide whether the abilities should be registered at all.
jpkcom_simplelang_abilities_enabled() : bool
Tags
Return values
bool —True when registration should proceed.
jpkcom_simplelang_ability_log()
Write a debug line, and only with WP_DEBUG.
jpkcom_simplelang_ability_log(string $message) : void
Parameters
- $message : string
-
Message.
Tags
jpkcom_simplelang_ability_error()
Build a WP_Error carrying an HTTP status.
jpkcom_simplelang_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_simplelang_ability_boundary()
Turn a Throwable out of a callback into a WP_Error.
jpkcom_simplelang_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_simplelang_ability_json_object()
Wrap an empty map so it encodes as {} rather than [].
jpkcom_simplelang_ability_json_object(array<string, mixed> $map) : array<string, mixed>|stdClass
Parameters
- $map : array<string, mixed>
-
Map.
Tags
Return values
array<string, mixed>|stdClass —Map, or an empty object.
jpkcom_simplelang_ability_capability()
Check the capability required to run an ability.
jpkcom_simplelang_ability_capability(string $ability) : bool
edit_posts, not read. This reports an editorial and SEO condition of
the site - which pages are annotated for which language, and where that
annotation comes out incomplete - and it names unpublished and dangling
posts while doing so. That is not visitor-facing content.
Parameters
- $ability : string
-
Ability name.
Tags
Return values
bool —True when the current user may run it.
jpkcom_simplelang_ability_meta()
Build the meta array for an ability.
jpkcom_simplelang_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_simplelang_ability_normalise_input()
Bring the value core hands the callback into array form.
jpkcom_simplelang_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_simplelang_ability_validate_input_keys()
Refuse a top-level input key the ability does not declare.
jpkcom_simplelang_ability_validate_input_keys(array<string, mixed> $input, array<string|int, string> $allowed) : true|WP_Error
On EVERY ability, not a subset: a caller that learned the refusal on one assumes it everywhere, and the ability that silently accepts is the one it will trust.
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_simplelang_ability_enabled_post_types()
The post types language selection is enabled for.
jpkcom_simplelang_ability_enabled_post_types() : array<string|int, string>
Reads the same option and the same default the rest of the plugin reads, rather than restating either.
Tags
Return values
array<string|int, string> —Post type names.
jpkcom_simplelang_ability_describe_locale()
Describe a locale the way the front end resolves it.
jpkcom_simplelang_ability_describe_locale(string $locale, array<string|int, string> $installed) : array<string, mixed>
installed matters more than it looks: a locale whose language pack was
removed stays in the post meta, and switch_to_locale() then returns false,
so the front end deliberately does NOT switch. The page keeps the site
language while its meta still claims another one.
Parameters
- $locale : string
-
Locale, or '' for "no language of its own".
- $installed : array<string|int, string>
-
Installed locales.
Tags
Return values
array<string, mixed> —Description.
jpkcom_simplelang_ability_list_languages_inner()
Report which languages this site actually uses.
jpkcom_simplelang_ability_list_languages_inner([mixed $input = null ]) : array<string, mixed>|WP_Error
Parameters
- $input : mixed = null
-
Ability input.
Tags
Return values
array<string, mixed>|WP_Error —Result.
jpkcom_simplelang_ability_build_sets()
Collect the translation sets on this site.
jpkcom_simplelang_ability_build_sets(array<string|int, string> $types) : array{sets: array, scanned: int, truncated: bool}
A set is a post plus everything it links to. Because the links are bidirectional, the same set is reachable from each of its members, so sets are deduplicated by their sorted member list.
Parameters
- $types : array<string|int, string>
-
Enabled post types.
Tags
Return values
array{sets: arraySets.
jpkcom_simplelang_ability_inspect_set()
Report what the hreflang output for one set will and will not contain.
jpkcom_simplelang_ability_inspect_set(array<string|int, int> $members, string $default_tag, array<string|int, string> $installed) : array<string, mixed>
Every finding below is derived from what the emitter does, not from an opinion about what it should do:
- It keys entries by BCP 47 tag and keeps the FIRST per tag, so two members resolving to one tag yield one entry and the other URL is annotated nowhere. Which of the two survives depends on the order the posts come back in, so this reports the collision and does NOT claim a winner.
- A member with no language of its own is read as the site default, so it collides with an explicit member in that language rather than being ignored.
- x-default is emitted only when some member carries the site default tag.
- Only published posts are fetched, so an unpublished member never appears.
Parameters
- $members : array<string|int, int>
-
Member post IDs.
- $default_tag : string
-
Site default BCP 47 tag.
- $installed : array<string|int, string>
-
Installed locales.
Tags
Return values
array<string, mixed> —Report for this set.
jpkcom_simplelang_ability_check_sets_inner()
Report the translation sets whose hreflang output comes out incomplete.
jpkcom_simplelang_ability_check_sets_inner([mixed $input = null ]) : array<string, mixed>|WP_Error
Parameters
- $input : mixed = null
-
Ability input.
Tags
Return values
array<string, mixed>|WP_Error —Result.
jpkcom_simplelang_ability_permission_list_languages()
Permission callback for list-languages.
jpkcom_simplelang_ability_permission_list_languages([mixed $input = null ]) : bool
Parameters
- $input : mixed = null
-
Validated input, unused.
Tags
Return values
bool —True when the current user may run it.
jpkcom_simplelang_ability_permission_check_sets()
Permission callback for check-translation-sets.
jpkcom_simplelang_ability_permission_check_sets([mixed $input = null ]) : bool
Parameters
- $input : mixed = null
-
Validated input, unused.
Tags
Return values
bool —True when the current user may run it.
jpkcom_simplelang_ability_list_languages()
Execute callback for jpkcom-simple-lang/list-languages.
jpkcom_simplelang_ability_list_languages([mixed $input = null ]) : array<string, mixed>|WP_Error
Parameters
- $input : mixed = null
-
Ability input.
Tags
Return values
array<string, mixed>|WP_Error —Result.
jpkcom_simplelang_ability_check_sets()
Execute callback for jpkcom-simple-lang/check-translation-sets.
jpkcom_simplelang_ability_check_sets([mixed $input = null ]) : array<string, mixed>|WP_Error
Parameters
- $input : mixed = null
-
Ability input.
Tags
Return values
array<string, mixed>|WP_Error —Result.
jpkcom_simplelang_get_ability_definitions()
Build the registration arguments for both abilities.
jpkcom_simplelang_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 of these arrays without a WordPress installation.
Tags
Return values
array<string, array<string, mixed>> —Ability name => registration args.
jpkcom_simplelang_register_ability_category()
Register the shared category, unless a sibling plugin already did.
jpkcom_simplelang_register_ability_category() : void
Tags
jpkcom_simplelang_register_abilities()
Register both abilities.
jpkcom_simplelang_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.