Claude Skill

wp-view-config-api

Extend or audit WordPress 7.1 entity list and form defaults through the View Config API used by DataViews-based screens. Covers wp_get_entity_view_config, wp_get_entity_view_config_hook_name, dynamic get_entity_view_config filters, WP_View_Config_Data merge/replace/set/remove sem

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download lonsdale201-wp-agent-skills-wordpress_wp-view-config-api-52f6020.zip · 4 KB
Part of lonsdale201/wp-agent-skills — 226 skills

Install

skills CLI npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/wordpress/wp-view-config-api
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
Git git clone https://github.com/Lonsdale201/wp-agent-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

WordPress View Config API

WordPress 7.1 builds DataViews-style defaults for an entity through wp_get_entity_view_config(). Plugins contribute versioned patches with WP_View_Config_Data; they do not replace REST controllers, entity data, or authorization.

Choose the exact entity hook

The filter is dynamic and its kind/name segments are lowercased. Generate it instead of guessing:

$hook = wp_get_entity_view_config_hook_name( 'postType', 'book' );
// get_entity_view_config_posttype_book

For a REST-exposed book post type:

add_filter(
    'get_entity_view_config_posttype_book',
    static function ( WP_View_Config_Data $data, array $entity ): WP_View_Config_Data {
        return $data->merge(
            array(
                'default_view' => array(
                    'type'    => 'table',
                    'perPage' => 30,
                    'fields'  => array( 'author', 'status', 'genre' ),
                ),
                'view_list' => array(
                    array(
                        'title' => __( 'Published', 'myplugin' ),
                        'slug'  => 'myplugin-published',
                        'view'  => array(
                            'filters' => array(
                                array(
                                    'field'    => 'status',
                                    'operator' => 'isAny',
                                    'value'    => 'publish',
                                ),
                            ),
                        ),
                    ),
                ),
            ),
            1
        );
    },
    10,
    2
);

Pass the schema version the patch was authored against—currently literal 1. Do not automatically substitute WP_View_Config_Data::LATEST_VERSION forever: a future schema bump should prompt review/migration of the patch.

Understand the four top-level keys

  • default_view: initial type, filters, sorting, per-page, fields, title/media fields, and related view options.
  • default_layouts: defaults for table/grid/list layout types.
  • view_list: named view presets, merged by slug identity.
  • form: DataForm field/layout configuration for the entity.

The container exposes mutation methods, not a public read accessor. Do not reflect into private data or branch on an undocumented materialized shape. Contribute a minimal patch.

Pick the least destructive method

Method Effect Normal use
merge( $patch, 1 ) Deeply composes maps; merges lists by id, slug, field, or scalar identity Default choice for plugins
replace( $patch, 1 ) Like merge, but named lists are replaced wholesale Pin an exact list while preserving surrounding maps
set( $patch, 1 ) Replaces every named top-level key wholesale A plugin truly owns that full key
remove( $spec, 1 ) Removes selected nested members; top-level removal resets the core default Remove a precise inherited member

Prefer merge(). Broad set()/replace() patches can erase core additions and other plugins' contributions.

Examples:

// Remove one field from the inherited default fields list.
return $data->remove(
    array( 'default_view' => array( 'fields' => array( 'author' ) ) ),
    1
);
// Replace only the fields list, not the whole default_view key.
return $data->replace(
    array( 'default_view' => array( 'fields' => array( 'title', 'status' ) ) ),
    1
);

A nested null deletes that leaf. A top-level null or top-level remove() resets the key to its original default rather than leaving the response key absent. Shape mismatches are rejected with a notice; do not merge a map where a list is expected.

Compose correctly with other callbacks

Every filter callback must return the WP_View_Config_Data object it received. Mutation methods return the object for chaining. Returning an array, null, or a new unrelated container breaks later priorities.

Use prefixed view slugs and field IDs. Make additions deterministic; the filter may run more than once in a request. Do not perform database writes or remote calls while building configuration.

The API keeps only documented top-level keys. Attaching arbitrary top-level plugin data will not survive materialization.

REST route and permissions

GET /wp-json/wp/v2/view-config?kind=postType&name=book exposes the built configuration and schema version. It is not anonymous:

  • a post type requires that the type exists, has show_in_rest, and the user has its edit_posts capability;
  • a taxonomy requires show_in_rest and its manage_terms capability;
  • root requires manage_options;
  • other custom kinds fall back to edit_posts.

The response is configuration only. Register the entity's REST fields/data separately and apply their own authorization. Hiding a field from a view config is not a data-access control.

Audit checklist

  • Exact dynamic hook for the intended kind/name.
  • Entity is registered and REST-exposed when a core post type/taxonomy route is expected.
  • Literal authored schema version is supplied.
  • merge() used unless replacement ownership is explicit.
  • View/field identities are stable and plugin-prefixed where custom.
  • Callback returns the same container and has no side effects.
  • Fields referenced by configuration actually exist in the entity/DataViews definition.
  • REST capability is tested with allowed, lower-privileged, and logged-out users.
  • Other plugin/core patches still compose at different priorities.

Critical rules

  • Treat view config as presentation defaults, never authorization.
  • Return WP_View_Config_Data, not the materialized array.
  • Use small merge() patches for interoperability.
  • Review patches when the schema version changes.
  • Do not depend on private container state or undocumented keys.

Cross-references

  • Use wp-rest-api for the entity data and permission contract.
  • Use wp-metadata-api when view fields depend on registered REST meta.
  • Use wp-block-editor-iframe-compatibility for DOM/UI extensions around DataViews screens.

References

Files (wp-agent-skills)
  • agents
    • openai.yaml 240 B
      interface:
        display_name: "WP View Config API"
        short_description: "Extend WordPress 7.1 DataViews entity configurations"
        default_prompt: "Use $wp-view-config-api to implement or audit a WordPress 7.1 entity View Config API extension."
      
  • references
    • patch-semantics.md 2.2 KB
      # View Config patch semantics
      
      ## Method depth
      
      Assume the current configuration contains:
      
      ```php
      array(
          'default_view' => array(
              'type'   => 'table',
              'sort'   => array( 'field' => 'title', 'direction' => 'asc' ),
              'fields' => array( 'author', 'status' ),
          ),
      )
      ```
      
      - `merge( [ 'default_view' => [ 'sort' => [ 'direction' => 'desc' ] ] ], 1 )` keeps the sort field and changes direction.
      - `replace()` behaves the same for associative maps, but replaces a list such as `fields` wholesale.
      - `set( [ 'default_view' => [ 'type' => 'grid' ] ], 1 )` replaces the whole `default_view` value and drops inherited members.
      - `remove( [ 'default_view' => [ 'sort' => [ 'direction' ] ] ], 1 )` removes only the nested direction.
      
      ## List identity
      
      `merge()` identifies list members by `id`, then `slug`, then `field`, or by the scalar value for scalar lists. A contribution with the same identity patches the existing member; a new identity appends. Lists without a usable identity cannot compose predictably and should be replaced only deliberately.
      
      An empty list passed to `merge()` is a no-op. Use `replace()` when an intentionally empty exact list is required.
      
      ## Null and defaults
      
      - Nested `null` removes a leaf.
      - Top-level `null` resets that key to the base default.
      - Naming a top-level key in `remove()` also resets it to the base default.
      - Unsupported top-level keys are discarded from the final materialized response.
      - Unsupported schema versions and incompatible list/map shapes are rejected without applying the patch.
      
      ## Dynamic hook
      
      `wp_get_entity_view_config_hook_name( $kind, $name )` lowercases both dynamic segments inside:
      
      ```text
      get_entity_view_config_{kind}_{name}
      ```
      
      Use the helper in diagnostics and tests. Hook names are still literal when passed to `add_filter()`.
      
      ## REST contract
      
      Route:
      
      ```text
      GET /wp-json/wp/v2/view-config?kind={kind}&name={name}
      ```
      
      Response keys include `kind`, `name`, `version`, `default_view`, `default_layouts`, `view_list`, and `form`. Empty object-typed values are serialized as `{}`, not `[]`, to match the REST schema.
      
      ## Source paths
      
      - `wp-includes/view-config.php`
      - `wp-includes/class-wp-view-config-data.php`
      - `wp-includes/rest-api/endpoints/class-wp-rest-view-config-controller.php`
      
  • SKILL.md 7.4 KB
    ---
    name: wp-view-config-api
    description: Extend or audit WordPress 7.1 entity list and form defaults through the View Config API used by DataViews-based screens. Covers wp_get_entity_view_config, wp_get_entity_view_config_hook_name, dynamic get_entity_view_config filters, WP_View_Config_Data merge/replace/set/remove semantics, schema version 1 patches, default_view, default_layouts, view_list, form, list identity merging, null/reset behavior, callback composition, the authenticated wp/v2/view-config route, custom post type/taxonomy capability mapping, and safe plugin interoperability. Use when a plugin customizes Site Editor or DataViews fields, layouts, filters, saved-view presets, or entity forms.
    license: GPLv2-or-later
    metadata:
      wp-skills-author: "Soczó Kristóf"
      wp-skills-contact: "mailto:lonsdale201@hotmail.com"
      wp-skills-plugin: "wordpress"
      wp-skills-plugin-version-tested: "7.1"
      wp-skills-wp-version-tested: "7.1"
      wp-skills-php-min: "7.4"
      wp-skills-last-updated: "2026-08-19"
    ---
    
    # WordPress View Config API
    
    WordPress 7.1 builds DataViews-style defaults for an entity through `wp_get_entity_view_config()`. Plugins contribute versioned patches with `WP_View_Config_Data`; they do not replace REST controllers, entity data, or authorization.
    
    ## Choose the exact entity hook
    
    The filter is dynamic and its kind/name segments are lowercased. Generate it instead of guessing:
    
    ```php
    $hook = wp_get_entity_view_config_hook_name( 'postType', 'book' );
    // get_entity_view_config_posttype_book
    ```
    
    For a REST-exposed `book` post type:
    
    ```php
    add_filter(
        'get_entity_view_config_posttype_book',
        static function ( WP_View_Config_Data $data, array $entity ): WP_View_Config_Data {
            return $data->merge(
                array(
                    'default_view' => array(
                        'type'    => 'table',
                        'perPage' => 30,
                        'fields'  => array( 'author', 'status', 'genre' ),
                    ),
                    'view_list' => array(
                        array(
                            'title' => __( 'Published', 'myplugin' ),
                            'slug'  => 'myplugin-published',
                            'view'  => array(
                                'filters' => array(
                                    array(
                                        'field'    => 'status',
                                        'operator' => 'isAny',
                                        'value'    => 'publish',
                                    ),
                                ),
                            ),
                        ),
                    ),
                ),
                1
            );
        },
        10,
        2
    );
    ```
    
    Pass the schema version the patch was authored against—currently literal `1`. Do not automatically substitute `WP_View_Config_Data::LATEST_VERSION` forever: a future schema bump should prompt review/migration of the patch.
    
    ## Understand the four top-level keys
    
    - `default_view`: initial type, filters, sorting, per-page, fields, title/media fields, and related view options.
    - `default_layouts`: defaults for table/grid/list layout types.
    - `view_list`: named view presets, merged by `slug` identity.
    - `form`: DataForm field/layout configuration for the entity.
    
    The container exposes mutation methods, not a public read accessor. Do not reflect into private data or branch on an undocumented materialized shape. Contribute a minimal patch.
    
    ## Pick the least destructive method
    
    | Method | Effect | Normal use |
    |---|---|---|
    | `merge( $patch, 1 )` | Deeply composes maps; merges lists by `id`, `slug`, `field`, or scalar identity | Default choice for plugins |
    | `replace( $patch, 1 )` | Like merge, but named lists are replaced wholesale | Pin an exact list while preserving surrounding maps |
    | `set( $patch, 1 )` | Replaces every named top-level key wholesale | A plugin truly owns that full key |
    | `remove( $spec, 1 )` | Removes selected nested members; top-level removal resets the core default | Remove a precise inherited member |
    
    Prefer `merge()`. Broad `set()`/`replace()` patches can erase core additions and other plugins' contributions.
    
    Examples:
    
    ```php
    // Remove one field from the inherited default fields list.
    return $data->remove(
        array( 'default_view' => array( 'fields' => array( 'author' ) ) ),
        1
    );
    ```
    
    ```php
    // Replace only the fields list, not the whole default_view key.
    return $data->replace(
        array( 'default_view' => array( 'fields' => array( 'title', 'status' ) ) ),
        1
    );
    ```
    
    A nested `null` deletes that leaf. A top-level `null` or top-level `remove()` resets the key to its original default rather than leaving the response key absent. Shape mismatches are rejected with a notice; do not merge a map where a list is expected.
    
    ## Compose correctly with other callbacks
    
    Every filter callback must return the `WP_View_Config_Data` object it received. Mutation methods return the object for chaining. Returning an array, `null`, or a new unrelated container breaks later priorities.
    
    Use prefixed view slugs and field IDs. Make additions deterministic; the filter may run more than once in a request. Do not perform database writes or remote calls while building configuration.
    
    The API keeps only documented top-level keys. Attaching arbitrary top-level plugin data will not survive materialization.
    
    ## REST route and permissions
    
    `GET /wp-json/wp/v2/view-config?kind=postType&name=book` exposes the built configuration and schema version. It is not anonymous:
    
    - a post type requires that the type exists, has `show_in_rest`, and the user has its `edit_posts` capability;
    - a taxonomy requires `show_in_rest` and its `manage_terms` capability;
    - `root` requires `manage_options`;
    - other custom kinds fall back to `edit_posts`.
    
    The response is configuration only. Register the entity's REST fields/data separately and apply their own authorization. Hiding a field from a view config is not a data-access control.
    
    ## Audit checklist
    
    - Exact dynamic hook for the intended kind/name.
    - Entity is registered and REST-exposed when a core post type/taxonomy route is expected.
    - Literal authored schema version is supplied.
    - `merge()` used unless replacement ownership is explicit.
    - View/field identities are stable and plugin-prefixed where custom.
    - Callback returns the same container and has no side effects.
    - Fields referenced by configuration actually exist in the entity/DataViews definition.
    - REST capability is tested with allowed, lower-privileged, and logged-out users.
    - Other plugin/core patches still compose at different priorities.
    
    ## Critical rules
    
    - Treat view config as presentation defaults, never authorization.
    - Return `WP_View_Config_Data`, not the materialized array.
    - Use small `merge()` patches for interoperability.
    - Review patches when the schema version changes.
    - Do not depend on private container state or undocumented keys.
    
    ## Cross-references
    
    - Use **`wp-rest-api`** for the entity data and permission contract.
    - Use **`wp-metadata-api`** when view fields depend on registered REST meta.
    - Use **`wp-block-editor-iframe-compatibility`** for DOM/UI extensions around DataViews screens.
    
    ## References
    
    - Read `references/patch-semantics.md` for merge identities, removal shapes, REST behavior, and source paths.
    - View Config dev note: <https://make.wordpress.org/core/2026/07/31/filtering-site-editor-screens-in-wordpress-7-1/>
    - Core sources: `wp-includes/view-config.php`, `wp-includes/class-wp-view-config-data.php`, `wp-includes/rest-api/endpoints/class-wp-rest-view-config-controller.php`.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related