Abilities API: meta-box/* abilities not exposed to REST (show_in_rest: false)

Support › Meta Box AIO › Abilities API: meta-box/* abilities not exposed to REST (show_in_rest: false)

Viewing 1 post (of 1 total)
  • Author
    Posts
  • #50244
    Alan BlairAlan Blair
    Participant

    Hi team,

    We’re using Meta Box AIO with the WordPress Abilities API and found a couple of things worth raising.

    Environment

    WordPress 7.1.3
    Meta Box AIO 3.13.1
    Bricks 2.4.3
    Novamira plugin 1.12.9, Novamira CLI 1.3.4

    1. The abilities aren’t visible over REST

    We manage the site through the Novamira CLI, which talks to WordPress through the REST API (/wp-abilities/v1). Meta Box registers its 23 meta-box/* abilities, but all of them have meta.show_in_rest = false (with mcp.public = true). The REST abilities controller only lists and runs abilities where show_in_rest is true, so REST-based clients can’t see or call any of them. Other plugins on the same site (Bricks, for example) register theirs with show_in_rest: true, and those work fine.

    Is this deliberate? If there’s a reason (security, or MCP-only by design), we’d like to understand it. If not, would you consider setting show_in_rest: true, or adding a setting to turn it on? Each ability already has its own permission callback, so REST exposure wouldn’t change who can run them.

    For now we’re using this snippet, which turns REST exposure on for your namespace only:

    add_filter(
    'wp_register_ability_args',
    function ( $args, $name ) {
    if ( ! is_string( $name ) || 0 !== strpos( $name, 'meta-box/' ) ) {
    return $args;
    }
    if ( ! isset( $args['meta'] ) || ! is_array( $args['meta'] ) ) {
    $args['meta'] = array();
    }
    $args['meta']['show_in_rest'] = true;
    return $args;
    },
    10,
    2
    );

    With it in place, all 23 abilities show up and run over REST. Please let us know if we should keep using it, or whether you plan to change the default.

    2. Bugs in update-field, move-field and delete-field

    Once the abilities were reachable, we tested every write ability on a test site. These all worked correctly:

    create-field-group, update-field-group, get-field-group, delete-field-group
    create-field, list-fields
    update-field-value, get-field-value, delete-field-value
    create-post-type, update-post-type, delete-post-type
    create-taxonomy, update-taxonomy, delete-taxonomy

    update-field, move-field and delete-field fail. The cause is in vendor/meta-box/meta-box-builder/src/Abilities.php:

    a) Mixed storage keys in the fields post meta. create-field-group stores fields keyed by their internal _id, while create-field appends with a numeric key. After creating a group with one field and then adding a second with create-field, the stored keys were:

    ["text_6adc214d5982d", 0]

    b) update-field throws a TypeError for _id-keyed fields. find_field_index() returns the array key, which is a string here. That key is passed to ensure_unique_field_id( array $field_data, array $existing_fields, ?int $exclude_index = null ) at line 840:

    MBB\Abilities::ensure_unique_field_id(): Argument #3 ($exclude_index) must be of type ?int, string given

    c) The “not found” check fails for index 0. update_field() (line 819), delete_field() (line 857) and move_field() (lines 877 and 893) all use:

    if ( ! $found_index ) { … 'Field not found.' … }

    find_field_index() returns null when nothing matches, but a valid index of 0 is falsy, so a field at key 0 is reported as “Field not found.” These calls also come back with success: false inside an otherwise successful response, which is easy to miss.

    d) delete_field() uses array_splice( $fields, $index, 1 ). That expects a numeric position, so it can’t remove a field stored under a string _id key either.

    Suggested fixes:

    Normalise fields to one key style (for example array_values() after reading, or always key by _id).
    Use null === $index instead of ! $index.
    Widen $exclude_index to int|string|null, or pass a numeric position.
    In delete_field(), unset( $fields[ $index ] ) instead of array_splice().

    Our workaround for now is to change fields through update-field-group with the full fields array, which works.

    Thanks!

Viewing 1 post (of 1 total)
  • You must be logged in to reply to this topic.