diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b817b4..377f302 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,9 +28,10 @@ Prefix the change with one of these keywords: ### Changed +- **WordPress.org plugin directory compliance:** PHP functions and hooks renamed from the core-style `wp_*` prefix back to `validation_api_*`. The `wp_*` prefix is reserved for WordPress core; the plugin directory's automated checks flag any plugin that uses it. The mapping is mechanical and one-directional: `wp_register_*_validation_check()` → `validation_api_register_*_check()`, and `wp_validation_*` → `validation_api_*`. The names will be restored to `wp_*` at core-merge time per [docs/gutenberg-alignment/core-pr-migration.md](docs/gutenberg-alignment/core-pr-migration.md). Companion plugins (`validation-api-integration-example`, `validation-api-settings`) updated in lockstep. - **Gutenberg alignment refactor:** All public API surfaces renamed to core conventions -- PHP registration functions renamed: `wp_register_block_validation_check()`, `wp_register_meta_validation_check()`, `wp_register_editor_validation_check()` -- PHP hooks renamed from `validation_api_*` to `wp_validation_*` (e.g., `wp_validation_check_level`, `wp_validation_check_args`) +- PHP registration functions renamed: `wp_register_block_validation_check()`, `wp_register_meta_validation_check()`, `wp_register_editor_validation_check()` (subsequently renamed to `validation_api_register_*_check()` per the plugin-directory compliance entry above) +- PHP hooks renamed from `validation_api_*` to `wp_validation_*` (e.g., `wp_validation_check_level`, `wp_validation_check_args`) (subsequently renamed back to `validation_api_*` per the plugin-directory compliance entry above) - JS filter hooks renamed: `editor.validateBlock`, `editor.validateMeta`, `editor.validateEditor` - Data store renamed from `validation-api` to `core/validation` - Plugin registration renamed from `registerPlugin('validation-api')` to `registerPlugin('core-validation')` diff --git a/CLAUDE.md b/CLAUDE.md index f6bd32d..25a3fa6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,17 +8,17 @@ Three validation scopes, each with a PHP registry and JS filter: | Scope | PHP Registry | Registration Function | JS Filter | |---|---|---|---| -| Block attributes | `ValidationAPI\Block\Registry` | `wp_register_block_validation_check()` | `editor.validateBlock` | -| Post meta fields | `ValidationAPI\Meta\Registry` | `wp_register_meta_validation_check()` | `editor.validateMeta` | -| Editor / document | `ValidationAPI\Editor\Registry` | `wp_register_editor_validation_check()` | `editor.validateEditor` | +| Block attributes | `ValidationAPI\Block\Registry` | `validation_api_register_block_check()` | `editor.validateBlock` | +| Post meta fields | `ValidationAPI\Meta\Registry` | `validation_api_register_meta_check()` | `editor.validateMeta` | +| Editor / document | `ValidationAPI\Editor\Registry` | `validation_api_register_editor_check()` | `editor.validateEditor` | -All three concrete registries extend `ValidationAPI\AbstractRegistry`, which provides shared defaults, level validation, namespace stamping, priority sort, and `wp_validation_check_level` filter application. +All three concrete registries extend `ValidationAPI\AbstractRegistry`, which provides shared defaults, level validation, namespace stamping, priority sort, and `validation_api_check_level` filter application. All registration functions require `namespace`, `name`, and `error_msg` in the `$args` array. Meta checks also require `meta_key`. ### Severity -Three levels: `error` (blocks save), `warning` (shows feedback), `none` (disabled). Filterable at runtime via `wp_validation_check_level`. +Three levels: `error` (blocks save), `warning` (shows feedback), `none` (disabled). Filterable at runtime via `validation_api_check_level`. ### Data flow @@ -39,11 +39,11 @@ PHP registries (Block / Meta / Editor — all extend AbstractRegistry) ### Key PHP hooks -- `wp_validation_check_level` — Override check severity at runtime (the settings-addon extension point) -- `wp_validation_check_args` / `wp_validation_meta_check_args` / `wp_validation_editor_check_args` — Modify check config before registration -- `wp_validation_should_register_check` / `_meta_check` / `_editor_check` — Prevent specific checks from registering -- `wp_validation_initialized`, `wp_validation_ready`, `wp_validation_editor_checks_ready` — Lifecycle -- `wp_validation_check_registered`, `wp_validation_meta_check_registered`, `wp_validation_editor_check_registered` — Post-registration notifications +- `validation_api_check_level` — Override check severity at runtime (the settings-addon extension point) +- `validation_api_check_args` / `validation_api_meta_check_args` / `validation_api_editor_check_args` — Modify check config before registration +- `validation_api_should_register_check` / `_meta_check` / `_editor_check` — Prevent specific checks from registering +- `validation_api_initialized`, `validation_api_ready`, `validation_api_editor_checks_ready` — Lifecycle +- `validation_api_check_registered`, `validation_api_meta_check_registered`, `validation_api_editor_check_registered` — Post-registration notifications ### JS filters @@ -137,7 +137,7 @@ TypeScript: `src/store/constants.ts` is the only `.ts` file. Other modules run a ## Companion plugins (same local `wp-content/plugins/`) - **validation-api-integration-example** — Demo plugin with block, meta, and editor checks. Rebuild with `npm run build` in its directory after any JS filter-name changes. -- **validation-api-settings** — Admin settings page. Reads checks from `GET /wp-validation/v1/checks`, lets admins override severity via `wp_validation_check_level`. Rebuild with `npm run build` in its directory after REST path changes. +- **validation-api-settings** — Admin settings page. Reads checks from `GET /wp-validation/v1/checks`, lets admins override severity via `validation_api_check_level`. Rebuild with `npm run build` in its directory after REST path changes. ## Conventions @@ -154,11 +154,11 @@ External plugins register checks like this: ```php add_action( 'init', function() { - if ( ! function_exists( 'wp_register_block_validation_check' ) ) { + if ( ! function_exists( 'validation_api_register_block_check' ) ) { return; } - wp_register_block_validation_check( 'core/image', [ + validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-plugin', 'name' => 'alt_text', 'level' => 'error', diff --git a/README.md b/README.md index 3fc06fc..0a27e27 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,11 @@ Register a validation check in two steps. ```php add_action( 'init', function () { - if ( ! function_exists( 'wp_register_block_validation_check' ) ) { + if ( ! function_exists( 'validation_api_register_block_check' ) ) { return; } - wp_register_block_validation_check( 'core/image', [ + validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-content-rules', 'name' => 'alt_text', 'level' => 'error', @@ -58,9 +58,9 @@ Each registered check falls into one of three scopes, with a matching registrati | Scope | Validates | PHP | JS filter | |---|---|---|---| -| **Block** | Attributes on a specific block type | `wp_register_block_validation_check()` | `editor.validateBlock` | -| **Meta** | Post meta fields | `wp_register_meta_validation_check()` | `editor.validateMeta` | -| **Editor** | Document-level concerns (heading hierarchy, required sections) | `wp_register_editor_validation_check()` | `editor.validateEditor` | +| **Block** | Attributes on a specific block type | `validation_api_register_block_check()` | `editor.validateBlock` | +| **Meta** | Post meta fields | `validation_api_register_meta_check()` | `editor.validateMeta` | +| **Editor** | Document-level concerns (heading hierarchy, required sections) | `validation_api_register_editor_check()` | `editor.validateEditor` | All three route through a single `core/validation` `@wordpress/data` store, so UI components subscribe once and see every issue. @@ -72,10 +72,10 @@ All three route through a single `core/validation` `@wordpress/data` store, so U | `warning` | Yellow indicator. Allows saving. | | `none` | Skipped entirely. | -Every active check passes through the `wp_validation_check_level` filter at runtime. The core plugin has no storage — `wp_options`, admin pages, persistence of any kind are out of scope. Configurability is delegated entirely to the filter: +Every active check passes through the `validation_api_check_level` filter at runtime. The core plugin has no storage — `wp_options`, admin pages, persistence of any kind are out of scope. Configurability is delegated entirely to the filter: ```php -add_filter( 'wp_validation_check_level', function ( $level, $context ) { +add_filter( 'validation_api_check_level', function ( $level, $context ) { // $context => [ 'scope' => 'block', 'block_type' => 'core/image', 'check_name' => 'alt_text' ] if ( 'block' === $context['scope'] && 'alt_text' === $context['check_name'] ) { return 'warning'; // soften from error to warning @@ -108,7 +108,7 @@ A companion plugin ([validation-api-settings](https://github.com/troychaplin/val ## Related plugins -- **[validation-api-settings](https://github.com/troychaplin/validation-api-settings)** — Admin UI for overriding check severity. Hooks `wp_validation_check_level` and persists overrides in `wp_options`. Install only if you want a settings screen; the core plugin runs fine without it. +- **[validation-api-settings](https://github.com/troychaplin/validation-api-settings)** — Admin UI for overriding check severity. Hooks `validation_api_check_level` and persists overrides in `wp_options`. Install only if you want a settings screen; the core plugin runs fine without it. - **[validation-api-integration-example](https://github.com/troychaplin/validation-api-integration-example)** — Demo plugin that registers 9 checks (4 block, 3 meta, 2 editor) against a "Band" custom post type. Useful as a reference when writing your own integration. ## Documentation diff --git a/docs/INTEGRATION.md b/docs/INTEGRATION.md index 77f7378..54eada5 100644 --- a/docs/INTEGRATION.md +++ b/docs/INTEGRATION.md @@ -77,7 +77,7 @@ These items were adapted from plugin conventions to core conventions and are now | `ValidationSidebar` | Consolidated validation results panel | | `ValidationToolbarButton` | Per-block validation toolbar UI | | Block/Meta/Editor registries (+ AbstractRegistry base) | Declarative check registration | -| `wp_validation_check_level` filter | Runtime severity override | +| `validation_api_check_level` filter | Runtime severity override | | `editor.preSavePost` gate | Async save-time safety net layered on `lockPostSaving` | | REST `wp-validation/v1/checks` | Check introspection for admin tooling | @@ -111,13 +111,13 @@ This is where the bulk of the integration lives: ### PHP Side - New file (e.g., `wp-includes/validation.php`) or extend `wp-includes/blocks.php` -- Registration functions: `wp_register_block_validation_check()`, `wp_register_meta_validation_check()`, `wp_register_editor_validation_check()` +- Registration functions: `validation_api_register_block_check()`, `validation_api_register_meta_check()`, `validation_api_register_editor_check()` - Registry classes following the `WP_Block_Type_Registry` singleton pattern - Config export integrated into the editor settings bootstrap via `block_editor_settings_all` ## Current State and Upstream Strategy -The naming alignment refactor is complete. The plugin now uses core-style names for all public API surfaces. The remaining work is the actual Gutenberg contribution, structured as follows: +The naming alignment refactor is complete. JS filters and the store name are core-style and stay as-is at merge. PHP function/hook names use the `validation_api_*` prefix in the standalone plugin (a `wp_*` standalone plugin would fail WordPress.org plugin-check) and switch to `wp_*` at core merge — see the table at the bottom of this file. The remaining work is the actual Gutenberg contribution, structured as follows: ### Phase 1: RFC and Data Foundation @@ -140,11 +140,11 @@ The naming alignment refactor is complete. The plugin now uses core-style names **Goal**: Land the server-side check registration system. **Deliverables**: -- `wp_register_block_validation_check( $block_type, $args )` -- Register checks for block attributes -- `wp_register_meta_validation_check( $post_type, $args )` -- Register checks for post meta -- `wp_register_editor_validation_check( $post_type, $args )` -- Register checks for document state -- `wp_validation_check_level` filter for runtime severity override -- `wp_validation_check_args` filter for check modification before registration +- `validation_api_register_block_check( $block_type, $args )` -- Register checks for block attributes +- `validation_api_register_meta_check( $post_type, $args )` -- Register checks for post meta +- `validation_api_register_editor_check( $post_type, $args )` -- Register checks for document state +- `validation_api_check_level` filter for runtime severity override +- `validation_api_check_args` filter for check modification before registration - Validation config passed to JS via `block_editor_settings_all` filter **Check args structure**: @@ -203,30 +203,42 @@ The naming alignment refactor is complete. The plugin now uses core-style names - `block.json` declarative validation rules - Default check bundles -## Completed API Alignment +## Naming — standalone plugin vs. core merge -The following naming changes have been applied throughout the codebase. These reflect the current state of the plugin and the names that will be used in the Gutenberg PR. +The plugin's PHP API uses `validation_api_*` names. At core-merge time, these are renamed to `wp_*` per [docs/gutenberg-alignment/core-pr-migration.md](gutenberg-alignment/core-pr-migration.md). The JS filters and store name already match what core would use and don't need renaming. + +The reason for the dual naming: WordPress.org's plugin directory reserves the `wp_*` prefix for core, so a standalone plugin can't ship under those names without triggering plugin-check warnings. The names below reflect the standalone plugin's current state on the left and the target post-merge names on the right. ### PHP -| Old (Plugin) | Current | +| Standalone plugin (current) | Target at core merge | |---|---| -| `validation_api_register_plugin()` | Removed; `namespace` field in check args | | `validation_api_register_block_check()` | `wp_register_block_validation_check()` | | `validation_api_register_meta_check()` | `wp_register_meta_validation_check()` | | `validation_api_register_editor_check()` | `wp_register_editor_validation_check()` | | `validation_api_check_level` filter | `wp_validation_check_level` | | `validation_api_check_args` filter | `wp_validation_check_args` | - -### JavaScript - -| Old (Plugin) | Current | +| `validation_api_meta_check_args` filter | `wp_validation_meta_check_args` | +| `validation_api_editor_check_args` filter | `wp_validation_editor_check_args` | +| `validation_api_should_register_check` filter | `wp_validation_should_register_check` | +| `validation_api_should_register_meta_check` filter | `wp_validation_should_register_meta_check` | +| `validation_api_should_register_editor_check` filter | `wp_validation_should_register_editor_check` | +| `validation_api_check_registered` action | `wp_validation_check_registered` | +| `validation_api_meta_check_registered` action | `wp_validation_meta_check_registered` | +| `validation_api_editor_check_registered` action | `wp_validation_editor_check_registered` | +| `validation_api_initialized` action | `wp_validation_initialized` | +| `validation_api_ready` action | `wp_validation_ready` | +| `validation_api_editor_checks_ready` action | `wp_validation_editor_checks_ready` | + +### JavaScript (no rename — already core-style) + +| Identifier | Notes | |---|---| -| `validation_api_validate_block` filter | `editor.validateBlock` | -| `validation_api_validate_meta` filter | `editor.validateMeta` | -| `validation_api_validate_editor` filter | `editor.validateEditor` | -| Store: `validation-api` | `core/validation` | -| `window.ValidationAPI` | Config via `block_editor_settings_all` filter / editor settings | +| `editor.validateBlock` filter | Stays at core merge | +| `editor.validateMeta` filter | Stays at core merge | +| `editor.validateEditor` filter | Stays at core merge | +| Store: `core/validation` | Stays at core merge | +| Config via `block_editor_settings_all` filter / editor settings | Stays at core merge | ### REST API @@ -248,7 +260,7 @@ The following naming changes have been applied throughout the codebase. These re 1. **Performance at scale** -- Validating every block change in posts with hundreds of blocks needs benchmarking. The current per-block debouncing (300ms) and single-`useValidationSync` computation pattern help, but core demands higher standards. Polish item 6 (deferred) covers measurement; see [docs/TODO.md](TODO.md). -2. **API permanence** -- Once filter names and function signatures land in core, they cannot change without deprecation cycles. The current naming has been chosen to align with existing core conventions. +2. **API permanence** -- Once filter names and function signatures land in core, they cannot change without deprecation cycles. The standalone plugin uses `validation_api_*` for plugin-directory compliance; the core-merge translation to `wp_*` is mechanical and tracked in [gutenberg-alignment/core-pr-migration.md](gutenberg-alignment/core-pr-migration.md). 3. **Scope creep** -- Discussions may pull in content linting, accessibility auditing, or editorial workflows. The framework/rules boundary must hold. diff --git a/docs/PROPOSAL.md b/docs/PROPOSAL.md index 781bb55..f12ff2c 100644 --- a/docs/PROPOSAL.md +++ b/docs/PROPOSAL.md @@ -72,11 +72,11 @@ Checks are registered with a flat function call, using a `namespace` field to at ```php add_action( 'init', function() { - if ( ! function_exists( 'wp_register_block_validation_check' ) ) { + if ( ! function_exists( 'validation_api_register_block_check' ) ) { return; } - wp_register_block_validation_check( 'core/image', [ + validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-content-rules', 'name' => 'alt_text', 'error_msg' => __( 'Images must have alt text.', 'my-plugin' ), @@ -93,7 +93,7 @@ Validate individual block attributes such as image alt text, heading content, bu **PHP Registration:** ```php -wp_register_block_validation_check( 'core/image', [ +validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-plugin', 'name' => 'alt_text', 'level' => 'error', @@ -130,7 +130,7 @@ Validate WordPress post meta fields with real-time client-side feedback. The met **PHP Registration:** ```php -wp_register_meta_validation_check( 'post', [ +validation_api_register_meta_check( 'post', [ 'namespace' => 'my-plugin', 'name' => 'required', 'meta_key' => 'seo_description', @@ -184,7 +184,7 @@ Validate the overall editor state: block order, document structure, required ele **PHP Registration:** ```php -wp_register_editor_validation_check( 'post', [ +validation_api_register_editor_check( 'post', [ 'namespace' => 'my-plugin', 'name' => 'first_block_heading', 'level' => 'warning', @@ -226,7 +226,7 @@ Every active check passes through a filter that allows any plugin to override it ```php apply_filters( - 'wp_validation_check_level', + 'validation_api_check_level', $registered_level, $context // [ 'scope' => 'block', 'block_type' => 'core/image', 'check_name' => 'alt_text' ] ); @@ -286,7 +286,7 @@ The [Validation API](https://github.com/troychaplin/validation-api) plugin demon ### Architecture -- **PHP Registries** — Singleton registries (`Block\Registry`, `Meta\Registry`, `Editor\Registry`) extending a shared `AbstractRegistry` base class. The abstract holds defaults, required-field validation, namespace stamping, priority sort, and `wp_validation_check_level` filter application; the concrete registries differ only in storage shape and scope-specific hook names. +- **PHP Registries** — Singleton registries (`Block\Registry`, `Meta\Registry`, `Editor\Registry`) extending a shared `AbstractRegistry` base class. The abstract holds defaults, required-field validation, namespace stamping, priority sort, and `validation_api_check_level` filter application; the concrete registries differ only in storage shape and scope-specific hook names. - **`@wordpress/data` Store** — A dedicated Redux store (`core/validation`) centralizes all validation state with actions, selectors, and a reducer. - **`useValidationSync` hook** — Single computation point. Calls `useInvalidBlocks`/`useInvalidMeta`/`useInvalidEditorChecks`, dispatches the results to the store. - **`useValidationLifecycle` hook** — Manages editor-wide side effects: `lockPostSaving`/`unlockPostSaving`, `lockPostAutosaving`/`unlockPostAutosaving`, `disablePublishSidebar`/`enablePublishSidebar`, and body CSS classes. @@ -303,13 +303,13 @@ A read-only endpoint exposes all registered checks grouped by scope (block, meta ### External Plugin Integration -Plugins register checks using `wp_register_block_validation_check()` (and related functions) with a `function_exists` guard, and validation logic is added via JavaScript filters: +Plugins register checks using `validation_api_register_block_check()` (and related functions) with a `function_exists` guard, and validation logic is added via JavaScript filters: - [Integration Example Plugin](https://github.com/troychaplin/validation-api-integration-example) -- A complete example demonstrating block, meta, and editor checks. ### Companion Settings Package -The [validation-api-settings](https://github.com/troychaplin/validation-api-settings) companion plugin provides an admin settings page built on WordPress DataForm. It reads registered checks from the REST API and lets admins override severity levels globally via the `wp_validation_check_level` filter. +The [validation-api-settings](https://github.com/troychaplin/validation-api-settings) companion plugin provides an admin settings page built on WordPress DataForm. It reads registered checks from the REST API and lets admins override severity levels globally via the `validation_api_check_level` filter. This separation is intentional: the core framework has no settings UI and no storage, making it suitable for core merge. The companion stays in plugin-land. @@ -320,16 +320,16 @@ The proposal is specifically for the **Validation API framework** -- the infrast **Included:** - Check registration system (PHP registries for block, meta, and editor checks) -- Global registration functions (`wp_register_block_validation_check()`, `wp_register_meta_validation_check()`, `wp_register_editor_validation_check()`) +- Global registration functions (`validation_api_register_block_check()`, `validation_api_register_meta_check()`, `validation_api_register_editor_check()`) - JavaScript validation filter hooks (`editor.validateBlock`, `editor.validateMeta`, `editor.validateEditor`) - Dedicated `@wordpress/data` store (`core/validation`) for validation state -- Severity model with runtime override via `wp_validation_check_level` filter +- Severity model with runtime override via `validation_api_check_level` filter - Validation result model (severity levels, issue reporting, standardized result objects) - Post-locking integration (automatic `lockPostSaving` based on error-level failures) - Standardized UI components (block indicators, validation sidebar, toolbar button) - Editor context scoping (post editor only, content blocks within templates) -- PHP action hooks for lifecycle events (`wp_validation_initialized`, `wp_validation_ready`, `wp_validation_editor_checks_ready`) -- PHP filter hooks for check modification (`wp_validation_check_args`, `wp_validation_should_register_check`, `wp_validation_check_level`) +- PHP action hooks for lifecycle events (`validation_api_initialized`, `validation_api_ready`, `validation_api_editor_checks_ready`) +- PHP filter hooks for check modification (`validation_api_check_args`, `validation_api_should_register_check`, `validation_api_check_level`) - REST API endpoint for admin tooling (plugin exposes at `GET /wp-validation/v1/checks`; final namespace in core TBD) **Not included (remains in plugin territory):** diff --git a/docs/TODO.md b/docs/TODO.md index 6bbb77f..061e2b4 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -12,8 +12,7 @@ Remaining work items to prepare the Validation API plugin for a Gutenberg core p - **JS filter hooks renamed** to `editor.validateBlock`, `editor.validateMeta`, `editor.validateEditor` - **`window.ValidationAPI` replaced** with `block_editor_settings_all` filter. Config available via `select('core/editor').getEditorSettings().validationApi` - **`PluginContext` dropped**. Replaced with required `namespace` field in check registration args -- **PHP functions renamed** to `wp_register_block_validation_check()`, `wp_register_meta_validation_check()`, `wp_register_editor_validation_check()` -- **PHP hooks renamed** from `validation_api_*` to `wp_validation_*` +- **PHP functions and hooks** currently named `validation_api_*`. Originally renamed to core-style `wp_*` for Gutenberg alignment, then renamed back to `validation_api_*` for WordPress.org plugin directory compliance. The `wp_*` names will be restored at core-merge time per [gutenberg-alignment/core-pr-migration.md](gutenberg-alignment/core-pr-migration.md). - **REST endpoint** moved to `wp-validation/v1/checks` (plugin-owned namespace; final core namespace TBD during PR) - **Issue model standardized** to camelCase only in JS. PHP still uses snake_case; transformation happens at the boundary in `createIssue()` - **`window.ValidationAPI.useMetaField` export dropped**. External plugins import directly or consume via the store diff --git a/docs/guide/README.md b/docs/guide/README.md index d273a55..02cf7ed 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -18,11 +18,11 @@ This example registers an image alt text check. If a `core/image` block has no a ```php add_action( 'init', function() { - if ( ! function_exists( 'wp_register_block_validation_check' ) ) { + if ( ! function_exists( 'validation_api_register_block_check' ) ) { return; } - wp_register_block_validation_check( 'core/image', [ + validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-content-rules', 'name' => 'alt_text', 'level' => 'error', @@ -59,19 +59,19 @@ That's it. The Validation API handles the sidebar panel, block indicators, and p Your plugin must not break when the Validation API is deactivated. Always wrap registration in: ```php -if ( ! function_exists( 'wp_register_block_validation_check' ) ) { +if ( ! function_exists( 'validation_api_register_block_check' ) ) { return; } ``` -This is the only dependency check you need. If `wp_register_block_validation_check` exists, the entire API is available. +This is the only dependency check you need. If `validation_api_register_block_check` exists, the entire API is available. ### The namespace Field The `namespace` field in the check args declares your plugin identity and scopes your checks: ```php -wp_register_block_validation_check( 'core/image', [ +validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-plugin', 'name' => 'alt_text', 'error_msg' => 'Alt text required.', @@ -88,9 +88,9 @@ The Validation API has three registries, each for a different kind of check: | Scope | Function | What It Validates | |---|---|---| -| Block | `wp_register_block_validation_check()` | Block attributes (alt text, links, required fields) | -| Meta | `wp_register_meta_validation_check()` | Post meta fields (SEO description, custom fields) | -| Editor | `wp_register_editor_validation_check()` | Document-level concerns (heading hierarchy, content structure) | +| Block | `validation_api_register_block_check()` | Block attributes (alt text, links, required fields) | +| Meta | `validation_api_register_meta_check()` | Post meta fields (SEO description, custom fields) | +| Editor | `validation_api_register_editor_check()` | Document-level concerns (heading hierarchy, content structure) | Each has its own PHP registration function and JS validation filter. See the dedicated guides: @@ -109,7 +109,7 @@ Every check has a `level` that controls its behavior: | `none` | Check is disabled. Skipped entirely. | | *(omitted)* | Defaults to `error`. | -Every active check passes through the `wp_validation_check_level` filter, so any check's severity can be overridden at runtime — without modifying the registering plugin. See [Severity Model](severity.md) for details. +Every active check passes through the `validation_api_check_level` filter, so any check's severity can be overridden at runtime — without modifying the registering plugin. See [Severity Model](severity.md) for details. ## What the API Provides diff --git a/docs/guide/block-checks.md b/docs/guide/block-checks.md index d60aab4..5c6d12d 100644 --- a/docs/guide/block-checks.md +++ b/docs/guide/block-checks.md @@ -7,7 +7,7 @@ Block checks validate the attributes of individual blocks. If a `core/image` is Register a block check with the `namespace` field to identify your plugin: ```php -wp_register_block_validation_check( 'core/image', [ +validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-plugin', 'name' => 'alt_text', 'level' => 'error', @@ -39,14 +39,14 @@ The second argument is an array of check configuration: Register as many checks as needed for a single block type: ```php -wp_register_block_validation_check( 'core/image', [ +validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-plugin', 'name' => 'alt_text', 'level' => 'error', 'error_msg' => 'This image is missing alt text.', ] ); -wp_register_block_validation_check( 'core/image', [ +validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-plugin', 'name' => 'decorative_flag', 'level' => 'warning', diff --git a/docs/guide/editor-checks.md b/docs/guide/editor-checks.md index 28ea5c9..ff79e01 100644 --- a/docs/guide/editor-checks.md +++ b/docs/guide/editor-checks.md @@ -7,7 +7,7 @@ Editor checks validate the document as a whole. Heading hierarchy, minimum conte Register an editor check with the `namespace` field to identify your plugin: ```php -wp_register_editor_validation_check( 'post', [ +validation_api_register_editor_check( 'post', [ 'namespace' => 'my-plugin', 'name' => 'heading_hierarchy', 'level' => 'warning', @@ -41,7 +41,7 @@ Register the same check for multiple post types: ```php // Option 1: Loop foreach ( [ 'post', 'page' ] as $post_type ) { - wp_register_editor_validation_check( $post_type, [ + validation_api_register_editor_check( $post_type, [ 'namespace' => 'my-plugin', 'name' => 'heading_hierarchy', 'level' => 'warning', diff --git a/docs/guide/examples.md b/docs/guide/examples.md index 31f5f92..3fd8ae0 100644 --- a/docs/guide/examples.md +++ b/docs/guide/examples.md @@ -16,12 +16,12 @@ A full plugin that registers block, meta, and editor checks with both PHP and Ja */ add_action( 'init', function() { - if ( ! function_exists( 'wp_register_block_validation_check' ) ) { + if ( ! function_exists( 'validation_api_register_block_check' ) ) { return; } // Block checks - wp_register_block_validation_check( 'core/image', [ + validation_api_register_block_check( 'core/image', [ 'namespace' => 'content-quality-rules', 'name' => 'alt_text', 'level' => 'error', @@ -30,7 +30,7 @@ add_action( 'init', function() { 'warning_msg' => 'Consider adding alt text to this image.', ] ); - wp_register_block_validation_check( 'core/button', [ + validation_api_register_block_check( 'core/button', [ 'namespace' => 'content-quality-rules', 'name' => 'has_link', 'level' => 'error', @@ -39,7 +39,7 @@ add_action( 'init', function() { 'warning_msg' => 'Consider adding a link to this button.', ] ); - wp_register_block_validation_check( 'core/button', [ + validation_api_register_block_check( 'core/button', [ 'namespace' => 'content-quality-rules', 'name' => 'has_text', 'level' => 'error', @@ -48,7 +48,7 @@ add_action( 'init', function() { ] ); // Meta checks - wp_register_meta_validation_check( 'post', [ + validation_api_register_meta_check( 'post', [ 'namespace' => 'content-quality-rules', 'name' => 'required', 'meta_key' => 'seo_description', @@ -59,7 +59,7 @@ add_action( 'init', function() { ] ); // Editor checks - wp_register_editor_validation_check( 'post', [ + validation_api_register_editor_check( 'post', [ 'namespace' => 'content-quality-rules', 'name' => 'heading_hierarchy', 'level' => 'warning', @@ -68,7 +68,7 @@ add_action( 'init', function() { 'warning_msg' => 'Headings skip levels — consider fixing the hierarchy.', ] ); - wp_register_editor_validation_check( 'post', [ + validation_api_register_editor_check( 'post', [ 'namespace' => 'content-quality-rules', 'name' => 'has_image', 'level' => 'warning', @@ -184,7 +184,7 @@ function getHeadingLevels( blocks ) { Validate attributes on a custom block: ```php -wp_register_block_validation_check( 'my-plugin/testimonial', [ +validation_api_register_block_check( 'my-plugin/testimonial', [ 'namespace' => 'my-plugin', 'name' => 'has_author', 'level' => 'error', @@ -212,12 +212,12 @@ The Validation API covers client-side validation. For server-side enforcement (R ```php add_action( 'init', function() { - if ( ! function_exists( 'wp_register_meta_validation_check' ) ) { + if ( ! function_exists( 'validation_api_register_meta_check' ) ) { return; } // Client-side validation (editor UX) - wp_register_meta_validation_check( 'event', [ + validation_api_register_meta_check( 'event', [ 'namespace' => 'my-events-plugin', 'name' => 'event_date_required', 'meta_key' => 'event_date', @@ -246,11 +246,11 @@ add_action( 'init', function() { ## Recipe: Conditional Severity by Post Type -Use the `wp_validation_check_level` filter to vary severity by context: +Use the `validation_api_check_level` filter to vary severity by context: ```php // Alt text is an error on posts, a warning on pages -add_filter( 'wp_validation_check_level', function( $level, $context ) { +add_filter( 'validation_api_check_level', function( $level, $context ) { if ( $context['scope'] === 'block' && $context['block_type'] === 'core/image' && $context['check_name'] === 'alt_text' @@ -266,11 +266,11 @@ add_filter( 'wp_validation_check_level', function( $level, $context ) { ## Recipe: Preventing Check Registration -Use the `wp_validation_should_register_check` filter to conditionally prevent checks from registering: +Use the `validation_api_should_register_check` filter to conditionally prevent checks from registering: ```php // Don't register image checks on the 'attachment' post type screen -add_filter( 'wp_validation_should_register_check', function( $should, $block_type, $check_name, $args ) { +add_filter( 'validation_api_should_register_check', function( $should, $block_type, $check_name, $args ) { if ( $block_type === 'core/image' && get_post_type() === 'attachment' ) { return false; } diff --git a/docs/guide/meta-checks.md b/docs/guide/meta-checks.md index 6846ac8..e5742e3 100644 --- a/docs/guide/meta-checks.md +++ b/docs/guide/meta-checks.md @@ -9,7 +9,7 @@ Meta checks have a unique advantage: they integrate with WordPress's `register_p Register a meta check with the `namespace` field to identify your plugin: ```php -wp_register_meta_validation_check( 'post', [ +validation_api_register_meta_check( 'post', [ 'namespace' => 'my-plugin', 'name' => 'required', 'meta_key' => 'seo_description', @@ -44,7 +44,7 @@ Register the same check for multiple post types by calling the function for each ```php foreach ( [ 'post', 'page' ] as $post_type ) { - wp_register_meta_validation_check( $post_type, [ + validation_api_register_meta_check( $post_type, [ 'namespace' => 'my-plugin', 'name' => 'required', 'meta_key' => 'seo_description', @@ -109,7 +109,7 @@ register_post_meta( 'post', 'seo_description', [ ] ); ``` -Client-side validation (via `wp_register_meta_validation_check()` + the `editor.validateMeta` JS filter) covers the editor experience. Server-side `validate_callback` covers REST writes and other non-editor save paths. They are independent; register both if you need both. +Client-side validation (via `validation_api_register_meta_check()` + the `editor.validateMeta` JS filter) covers the editor experience. Server-side `validate_callback` covers REST writes and other non-editor save paths. They are independent; register both if you need both. ## Meta Validation Data Flow diff --git a/docs/guide/severity.md b/docs/guide/severity.md index 1762a3d..860d220 100644 --- a/docs/guide/severity.md +++ b/docs/guide/severity.md @@ -28,27 +28,27 @@ If you don't declare a `level`, it defaults to `error`: ```php // These are equivalent: -wp_register_block_validation_check( 'core/image', [ +validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-plugin', 'name' => 'alt_text', 'level' => 'error', 'error_msg' => 'Alt text is required.', ] ); -wp_register_block_validation_check( 'core/image', [ +validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-plugin', 'name' => 'alt_text', 'error_msg' => 'Alt text is required.', ] ); ``` -## The wp_validation_check_level Filter +## The validation_api_check_level Filter This is the central mechanism for severity configuration. Every active check (level is not `none`) passes through this filter before validation runs: ```php $effective_level = apply_filters( - 'wp_validation_check_level', + 'validation_api_check_level', $registered_level, $context ); @@ -97,7 +97,7 @@ This is the core architectural decision: the Validation API has no settings stor ### Override a Specific Check ```php -add_filter( 'wp_validation_check_level', function( $level, $context ) { +add_filter( 'validation_api_check_level', function( $level, $context ) { // Downgrade image alt text from error to warning if ( $context['scope'] === 'block' && $context['block_type'] === 'core/image' @@ -112,7 +112,7 @@ add_filter( 'wp_validation_check_level', function( $level, $context ) { ### Disable a Check ```php -add_filter( 'wp_validation_check_level', function( $level, $context ) { +add_filter( 'validation_api_check_level', function( $level, $context ) { // Disable heading hierarchy check entirely if ( $context['check_name'] === 'heading_hierarchy' ) { return 'none'; @@ -124,7 +124,7 @@ add_filter( 'wp_validation_check_level', function( $level, $context ) { ### Override All Checks from a Scope ```php -add_filter( 'wp_validation_check_level', function( $level, $context ) { +add_filter( 'validation_api_check_level', function( $level, $context ) { // Make all editor checks warnings instead of errors if ( $context['scope'] === 'editor' && $level === 'error' ) { return 'warning'; @@ -136,7 +136,7 @@ add_filter( 'wp_validation_check_level', function( $level, $context ) { ### Override Based on Environment ```php -add_filter( 'wp_validation_check_level', function( $level, $context ) { +add_filter( 'validation_api_check_level', function( $level, $context ) { // In staging, downgrade all errors to warnings if ( wp_get_environment_type() === 'staging' && $level === 'error' ) { return 'warning'; @@ -147,11 +147,11 @@ add_filter( 'wp_validation_check_level', function( $level, $context ) { ## How the Companion Settings Package Uses This -The [validation-api-settings](https://github.com/troychaplin/validation-api-settings) companion plugin provides an admin UI for overriding check severity. Under the hood, it stores overrides in `wp_options` and hooks into `wp_validation_check_level`: +The [validation-api-settings](https://github.com/troychaplin/validation-api-settings) companion plugin provides an admin UI for overriding check severity. Under the hood, it stores overrides in `wp_options` and hooks into `validation_api_check_level`: ```php // This is what the companion does internally: -add_filter( 'wp_validation_check_level', function( $level, $context ) { +add_filter( 'validation_api_check_level', function( $level, $context ) { $options = get_option( 'validation_api_settings', [] ); $key = $context['block_type'] . '_' . $context['check_name']; return $options[ $key ] ?? $level; diff --git a/docs/guide/troubleshooting.md b/docs/guide/troubleshooting.md index 358f82b..57612a2 100644 --- a/docs/guide/troubleshooting.md +++ b/docs/guide/troubleshooting.md @@ -18,7 +18,7 @@ Most common causes, in order: 2. **The validation hook returns `true` (valid).** The sidebar only lists *invalid* results. If your `editor.validateBlock` / `editor.validateMeta` / `editor.validateEditor` filter callback always returns `true`, nothing surfaces. Add a `console.log` inside your filter to confirm it's being called and returning the expected value. -3. **`check_name` mismatch.** The filter callback's `checkName` parameter must match the `name` field you passed to `wp_register_block_validation_check()`. A typo here silently does nothing. +3. **`check_name` mismatch.** The filter callback's `checkName` parameter must match the `name` field you passed to `validation_api_register_block_check()`. A typo here silently does nothing. 4. **Wrong scope / post type.** Meta and editor checks register per post type. If you registered for `'post'` but you're editing a `'page'`, the check isn't loaded. @@ -37,7 +37,7 @@ Most common causes, in order: ```php add_action( 'init', function() { - if ( ! function_exists( 'wp_register_block_validation_check' ) ) { + if ( ! function_exists( 'validation_api_register_block_check' ) ) { return; // ← if this fires, your check never registers } // ... @@ -144,8 +144,8 @@ The settings addon stores overrides in `wp_options['validation_api_settings']`. 1. **Key format changed.** The override stored is keyed by scope + identifier + check_name. If you renamed a check, the stored override no longer matches and falls back to the default. 2. **Another filter is running later with a higher priority.** Debug by adding: ```php - add_filter( 'wp_validation_check_level', function( $level, $context ) { - error_log( 'wp_validation_check_level: ' . print_r( $context, true ) . ' → ' . $level ); + add_filter( 'validation_api_check_level', function( $level, $context ) { + error_log( 'validation_api_check_level: ' . print_r( $context, true ) . ' → ' . $level ); return $level; }, 999, 2 ); ``` diff --git a/docs/gutenberg-alignment/consolidated-plan.md b/docs/gutenberg-alignment/consolidated-plan.md index 50614b2..d19a100 100644 --- a/docs/gutenberg-alignment/consolidated-plan.md +++ b/docs/gutenberg-alignment/consolidated-plan.md @@ -15,17 +15,17 @@ All five shipped to `review/multiple-plugins`. Public API unchanged across every | **1** | `16b1dce` | JS source reshape to Gutenberg-package layout. Flat `src/{store, utils, hooks, components}/`. Renderless `ValidationProvider`/`ValidationAPI` converted to `useValidationSync` + `useValidationLifecycle` hooks (invoked from sibling renderless wrappers to avoid render loops). `editor.preSavePost` save gate added. `useValidationIssues()` consolidated hook. `useMetaField` dual `useSelect` collapsed. `getInvalid*` → `useInvalid*`. Webpack aliases dropped. `package.json` `sideEffects` declared. | | **2** | `c927184` + `0088bc8` (addon) | REST namespace: `wp/v2/validation-checks` → `wp-validation/v1/checks`. Plugin-owned namespace; final core namespace TBD during PR review. Settings addon updated in lockstep. | | **3** | `3d35352` | `includes/Core/I18n.php` deleted; `wp_set_script_translations()` inlined in `Core/Assets.php`. 58 LOC removed. | -| **4** | `7ab948d` + `826847d` (addon hot-fix) | PHP dead-code deletions (~260 LOC). Removed: `Meta\Validator` class, `Contracts/CheckProvider` interface, `Block\Registry::unregister_check()` + `set_check_enabled()`, `Editor\Registry::register_editor_check_for_post_types()`, `EditorDetection` `get_current_screen()` fallback, two orphan actions (`wp_validation_check_unregistered`, `wp_validation_check_toggled`), one orphan filter (`wp_validation_validate_meta`). Settings addon hot-fix restored meta-field border styling after a prior commit had broken it. | -| **5** | `c44e389` | `includes/AbstractRegistry.php` extracted. Block/Meta/Editor registries extend it. Shared: defaults merge, required-field check, level validation, `warning_msg` fallback, `namespace` stamping, priority sort, `wp_validation_check_level` filter application. Priority validation now consistent across all three scopes (was only Block). Logger trait methods changed from `private` to `protected` so subclasses inherit. | +| **4** | `7ab948d` + `826847d` (addon hot-fix) | PHP dead-code deletions (~260 LOC). Removed: `Meta\Validator` class, `Contracts/CheckProvider` interface, `Block\Registry::unregister_check()` + `set_check_enabled()`, `Editor\Registry::register_editor_check_for_post_types()`, `EditorDetection` `get_current_screen()` fallback, two orphan actions (`validation_api_check_unregistered`, `validation_api_check_toggled`), one orphan filter (`validation_api_validate_meta`). Settings addon hot-fix restored meta-field border styling after a prior commit had broken it. | +| **5** | `c44e389` | `includes/AbstractRegistry.php` extracted. Block/Meta/Editor registries extend it. Shared: defaults merge, required-field check, level validation, `warning_msg` fallback, `namespace` stamping, priority sort, `validation_api_check_level` filter application. Priority validation now consistent across all three scopes (was only Block). Logger trait methods changed from `private` to `protected` so subclasses inherit. | ### What's unchanged (still true) Public API surface preserved through every batch: -- Global PHP functions: `wp_register_block_validation_check()`, `wp_register_meta_validation_check()`, `wp_register_editor_validation_check()` +- Global PHP functions: `validation_api_register_block_check()`, `validation_api_register_meta_check()`, `validation_api_register_editor_check()` - JS filter names: `editor.validateBlock`, `editor.validateMeta`, `editor.validateEditor` - Store name: `core/validation` -- PHP hook prefix: `wp_validation_*` +- PHP hook prefix: `validation_api_*` - Registry singleton pattern (`::get_instance()`) - `block_editor_settings_all` injection mechanism - Severity model (`error` / `warning` / `none`) diff --git a/docs/gutenberg-alignment/core-pr-migration.md b/docs/gutenberg-alignment/core-pr-migration.md index 61f75f7..9ab74c3 100644 --- a/docs/gutenberg-alignment/core-pr-migration.md +++ b/docs/gutenberg-alignment/core-pr-migration.md @@ -25,7 +25,7 @@ Each deferred item either: ## Migration overview -Five major migrations: +Six major migrations: | # | Migration | Blocker until | Est. effort | |---|---|---|---| @@ -34,6 +34,7 @@ Five major migrations: | 3 | i18n: `'validation-api'` text domain → `'gutenberg'` (plugin) or `'default'` (core) | PR branch cut | Small (find-replace) | | 4 | Versioning: `@since 1.0.0` → target WP version | WP version known | Small | | 5 | Naming: CSS classes, namespace keys, tag prefixes | Core review | Small-medium | +| 6 | API rename back to core prefix: `validation_api_*` → `wp_*` (functions and hooks) | PR branch cut | Small (find-replace) | ## Target PHP architecture @@ -63,12 +64,24 @@ gutenberg/lib/validation/ | `ValidationAPI\Core\Traits\Logger` | Inlined (WP core doesn't use traits) | | `ValidationAPI\Core\Traits\EditorDetection` | Inlined or moved to a helper function | -### Global function signatures (unchanged) +### Global function signatures (rename to core prefix) -These stay identical — they're already core-style: -- `wp_register_block_validation_check( $block_type, $args )` -- `wp_register_meta_validation_check( $post_type, $args )` -- `wp_register_editor_validation_check( $post_type, $args )` +The standalone plugin uses `validation_api_*` for plugin-directory compliance (the `wp_*` prefix is reserved for core, so the plugin-check tool flags any plugin function/hook using it). At core merge, rename back to the core-style prefix. The function signatures themselves are identical; only the names change: + +| Standalone plugin | Target at core | +|---|---| +| `validation_api_register_block_check( $block_type, $args )` | `wp_register_block_validation_check( $block_type, $args )` | +| `validation_api_register_meta_check( $post_type, $args )` | `wp_register_meta_validation_check( $post_type, $args )` | +| `validation_api_register_editor_check( $post_type, $args )` | `wp_register_editor_validation_check( $post_type, $args )` | + +Find-and-replace recipe (run from the migrated `lib/validation/` tree): +```bash +sed -i '' \ + -e 's/validation_api_register_block_check/wp_register_block_validation_check/g' \ + -e 's/validation_api_register_meta_check/wp_register_meta_validation_check/g' \ + -e 's/validation_api_register_editor_check/wp_register_editor_validation_check/g' \ + $(grep -rl validation_api_register_ lib/validation/) +``` ### Autoload change @@ -85,8 +98,8 @@ These stay identical — they're already core-style: ### Trait migration -- `Logger` trait's `log_error()` and `log_debug()` methods: inline as two standalone functions (likely `_wp_validation_log_error()`, `_wp_validation_log_debug()`) or use the `wp_trigger_error()` / `error_log()` conventions preferred by core. Confirm the current WP core convention at migration time. -- `EditorDetection` trait: collapse the `get_editor_context()` logic into a helper function in `lib/validation/load.php` (e.g., `_wp_validation_get_editor_context()`). +- `Logger` trait's `log_error()` and `log_debug()` methods: inline as two standalone functions (likely `_validation_api_log_error()`, `_validation_api_log_debug()`) or use the `wp_trigger_error()` / `error_log()` conventions preferred by core. Confirm the current WP core convention at migration time. +- `EditorDetection` trait: collapse the `get_editor_context()` logic into a helper function in `lib/validation/load.php` (e.g., `_validation_api_get_editor_context()`). ### Singleton preservation @@ -226,7 +239,30 @@ Internal `_namespace` field stamped from `namespace` arg. Keep; it's internal im ### PHP hook names -All `wp_validation_*` prefixed hooks stay — already core-style. No rename. +The standalone plugin uses `validation_api_*` for plugin-directory compliance. At core merge, rename to `wp_validation_*`: + +| Standalone plugin | Target at core | +|---|---| +| `validation_api_check_level` | `wp_validation_check_level` | +| `validation_api_check_args` | `wp_validation_check_args` | +| `validation_api_meta_check_args` | `wp_validation_meta_check_args` | +| `validation_api_editor_check_args` | `wp_validation_editor_check_args` | +| `validation_api_should_register_check` | `wp_validation_should_register_check` | +| `validation_api_should_register_meta_check` | `wp_validation_should_register_meta_check` | +| `validation_api_should_register_editor_check` | `wp_validation_should_register_editor_check` | +| `validation_api_check_registered` | `wp_validation_check_registered` | +| `validation_api_meta_check_registered` | `wp_validation_meta_check_registered` | +| `validation_api_editor_check_registered` | `wp_validation_editor_check_registered` | +| `validation_api_initialized` | `wp_validation_initialized` | +| `validation_api_ready` | `wp_validation_ready` | +| `validation_api_editor_checks_ready` | `wp_validation_editor_checks_ready` | + +Mechanical find-and-replace (do this **after** the function-name rename above so substring overlap doesn't matter — the hook names don't share prefixes with the function names): +```bash +sed -i '' 's/validation_api_/wp_validation_/g' $(grep -rl validation_api_ lib/validation/) +``` + +Note the recipe also affects internal helpers like `_validation_api_log_error()`/`_validation_api_get_editor_context()` if they exist — review the diff before committing, since core conventions prefer `_wp_*` underscore-prefixed internals. ### JS filter names @@ -255,14 +291,16 @@ Suggested procedure for creating the actual PR: 4. Copy JS tree to `packages/validation/src/` (see JS package section) 5. Add `packages/validation/package.json` based on a similar package 6. Run mechanical find-and-replace migrations (text domain, `@since`, CSS prefix, `@package`) -7. Inline trait methods (Logger, EditorDetection) -8. Remove `Core/Plugin.php` initialization pattern; replace with functional `lib/validation/load.php` -9. Wire the new `lib/validation/` loader into Gutenberg's main loader -10. Register the new `packages/validation/` in `lerna.json` and root `package.json` -11. Adapt sidebar mount to use `ComplementaryArea` directly instead of `registerPlugin` -12. Run Gutenberg's `npm run build` and `phpcs` -13. Fix any core-convention violations caught by lint -14. Smoke test: activate Gutenberg in a local WP, register a test check, verify it surfaces in the editor +7. **Rename functions and hooks back to `wp_*` prefix** — run the sed recipes from "Global function signatures" and "PHP hook names" sections above. Update PHP, JS (any `addFilter` calls referencing PHP hook names), and docs. +8. Inline trait methods (Logger, EditorDetection) +9. Remove `Core/Plugin.php` initialization pattern; replace with functional `lib/validation/load.php` +10. Wire the new `lib/validation/` loader into Gutenberg's main loader +11. Register the new `packages/validation/` in `lerna.json` and root `package.json` +12. Adapt sidebar mount to use `ComplementaryArea` directly instead of `registerPlugin` +13. Run Gutenberg's `npm run build` and `phpcs` +14. Fix any core-convention violations caught by lint +15. Smoke test: activate Gutenberg in a local WP, register a test check, verify it surfaces in the editor +16. Update the integration-example and settings companion plugins (in their separate repos) to consume the new `wp_*` names; see each plugin's `docs/CORE-MERGE-REVERT.md` for the full rename map. ## PR description template @@ -324,10 +362,8 @@ These stay as-is through core merge: | Item | Reason | |---|---| -| Global PHP function names (`wp_register_*_check`) | Already core-style | | JS filter names (`editor.validate*`) | Already core-style | | Store name (`core/validation`) | Already core-style | -| PHP hook prefix (`wp_validation_*`) | Already core-style | | Severity model (`error`/`warning`/`none`) | Stable | | `block_editor_settings_all` injection | Canonical mechanism | | Registry singleton pattern | Matches `WP_Connector_Registry` | diff --git a/docs/technical/README.md b/docs/technical/README.md index 67332f0..921c4d8 100644 --- a/docs/technical/README.md +++ b/docs/technical/README.md @@ -54,7 +54,7 @@ The entry point is `validation_api_init_plugin()`, called on `init`. This bootst 2. Resolves the three registry singletons 3. Registers the REST API controller on `rest_api_init` 4. Registers `enqueue_block_editor_assets` / `enqueue_block_assets` for script/style loading -5. Fires `wp_validation_ready` (with Block Registry), `wp_validation_editor_checks_ready` (with Editor Registry), and `wp_validation_initialized` (with the Plugin instance) +5. Fires `validation_api_ready` (with Block Registry), `validation_api_editor_checks_ready` (with Editor Registry), and `validation_api_initialized` (with the Plugin instance) ### Registries @@ -63,13 +63,13 @@ Each registry is a singleton (`::get_instance()`) and extends `ValidationAPI\Abs - `normalize_args()` — defaults merge, required-field check (`error_msg`), `warning_msg` fallback, level validation, priority coercion - `stamp_namespace()` — moves the public `namespace` arg to the internal `_namespace` key - `sort_by_priority()` — `uasort` by the `priority` value -- `apply_level_filter()` — applies `wp_validation_check_level` with a `none` short-circuit +- `apply_level_filter()` — applies `validation_api_check_level` with a `none` short-circuit The concrete registries differ in their storage shape and scope-specific hook names: -- **`ValidationAPI\Block\Registry`** — `checks[block_type][check_name] = config`. Filters: `wp_validation_check_args`, `wp_validation_should_register_check`. Action: `wp_validation_check_registered`. -- **`ValidationAPI\Meta\Registry`** — `meta_checks[post_type][meta_key][check_name] = config` (3-level). Filters: `wp_validation_meta_check_args`, `wp_validation_should_register_meta_check`. Action: `wp_validation_meta_check_registered`. -- **`ValidationAPI\Editor\Registry`** — `editor_checks[post_type][check_name] = config`. Filters: `wp_validation_editor_check_args`, `wp_validation_should_register_editor_check`. Action: `wp_validation_editor_check_registered`. +- **`ValidationAPI\Block\Registry`** — `checks[block_type][check_name] = config`. Filters: `validation_api_check_args`, `validation_api_should_register_check`. Action: `validation_api_check_registered`. +- **`ValidationAPI\Meta\Registry`** — `meta_checks[post_type][meta_key][check_name] = config` (3-level). Filters: `validation_api_meta_check_args`, `validation_api_should_register_meta_check`. Action: `validation_api_meta_check_registered`. +- **`ValidationAPI\Editor\Registry`** — `editor_checks[post_type][check_name] = config`. Filters: `validation_api_editor_check_args`, `validation_api_should_register_editor_check`. Action: `validation_api_editor_check_registered`. ### Namespace Field @@ -170,15 +170,15 @@ Exposed for external plugins that build custom UI: ### No storage -The core plugin has no `wp_options`, no custom tables, no settings pages. Check definitions live in PHP memory (populated on each request), exported to JS via the `block_editor_settings_all` filter. The `wp_validation_check_level` filter is the extension point for runtime configuration — the companion settings package hooks into it and reads from its own `wp_options` key. +The core plugin has no `wp_options`, no custom tables, no settings pages. Check definitions live in PHP memory (populated on each request), exported to JS via the `block_editor_settings_all` filter. The `validation_api_check_level` filter is the extension point for runtime configuration — the companion settings package hooks into it and reads from its own `wp_options` key. ### Filter-first architecture Every significant behavior passes through a filter: -- Check args can be modified before registration (`wp_validation_check_args`) -- Checks can be prevented from registering (`wp_validation_should_register_check`) -- Severity is overridable at runtime (`wp_validation_check_level`) +- Check args can be modified before registration (`validation_api_check_args`) +- Checks can be prevented from registering (`validation_api_should_register_check`) +- Severity is overridable at runtime (`validation_api_check_level`) - Validation results come from JS filters (`editor.validateBlock`, etc.) - Save-time gating runs via `editor.preSavePost` as a safety net diff --git a/docs/technical/api.md b/docs/technical/api.md index 1fc07be..63356b2 100644 --- a/docs/technical/api.md +++ b/docs/technical/api.md @@ -4,12 +4,12 @@ All public registration functions, registry methods, and contracts. ## Global Functions -### wp_register_block_validation_check() +### validation_api_register_block_check() Register a validation check for a block type. ```php -wp_register_block_validation_check( string $block_type, array $args ): void +validation_api_register_block_check( string $block_type, array $args ): void ``` | Parameter | Type | Description | @@ -17,12 +17,12 @@ wp_register_block_validation_check( string $block_type, array $args ): void | `$block_type` | `string` | Block type name (e.g., `'core/image'`). | | `$args` | `array` | Check configuration (see [Check Arguments](#check-arguments)). Must include `'namespace'`. | -### wp_register_meta_validation_check() +### validation_api_register_meta_check() Register a validation check for a post meta field. ```php -wp_register_meta_validation_check( string $post_type, array $args ): void +validation_api_register_meta_check( string $post_type, array $args ): void ``` | Parameter | Type | Description | @@ -30,12 +30,12 @@ wp_register_meta_validation_check( string $post_type, array $args ): void | `$post_type` | `string` | Post type (e.g., `'post'`, `'page'`). | | `$args` | `array` | Check configuration. Must include `'namespace'` and `'meta_key'`. See [Check Arguments](#check-arguments). | -### wp_register_editor_validation_check() +### validation_api_register_editor_check() Register a validation check for the editor (document-level). ```php -wp_register_editor_validation_check( string $post_type, array $args ): void +validation_api_register_editor_check( string $post_type, array $args ): void ``` | Parameter | Type | Description | diff --git a/docs/technical/companion-package.md b/docs/technical/companion-package.md index a8397fe..7d218a4 100644 --- a/docs/technical/companion-package.md +++ b/docs/technical/companion-package.md @@ -9,7 +9,7 @@ The Validation API is a pure framework — no settings UI, no storage, no opinio - Three registries (Block, Meta, Editor) - Registration functions and hooks - JS validation runners and UI components -- `wp_validation_check_level` filter as the configuration extension point +- `validation_api_check_level` filter as the configuration extension point - No `wp_options`, no settings page, no storage ### Layer 2: Settings Companion (separate plugin) @@ -17,7 +17,7 @@ The Validation API is a pure framework — no settings UI, no storage, no opinio - Admin settings page built on WordPress DataForm - Reads registered checks from the REST API - Writes severity overrides to `wp_options` -- Hooks into `wp_validation_check_level` to apply overrides +- Hooks into `validation_api_check_level` to apply overrides The core plugin has no knowledge of the companion. It fires the filter; the companion hooks in. Any plugin could replace the companion with a different settings implementation. @@ -67,7 +67,7 @@ update_option( 'validation_api_settings', [ The companion registers one filter that bridges `wp_options` to the check level system: ```php -add_filter( 'wp_validation_check_level', function( $level, $context ) { +add_filter( 'validation_api_check_level', function( $level, $context ) { $options = get_option( 'validation_api_settings', [] ); $key = $context['block_type'] . '_' . $context['check_name']; return $options[ $key ] ?? $level; diff --git a/docs/technical/data-flow.md b/docs/technical/data-flow.md index 9ffc88d..e375776 100644 --- a/docs/technical/data-flow.md +++ b/docs/technical/data-flow.md @@ -8,7 +8,7 @@ This document traces how a registered check moves from PHP registration through ```php add_action( 'init', function() { - wp_register_block_validation_check( 'core/image', [ + validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-rules', 'name' => 'alt_text', 'level' => 'error', @@ -31,8 +31,8 @@ The global function dispatches to `BlockRegistry::get_instance()->register_check Two filters fire before storage (scope-specific names; block scope shown): -- `wp_validation_check_args` — allows modifying the check config -- `wp_validation_should_register_check` — allows preventing registration +- `validation_api_check_args` — allows modifying the check config +- `validation_api_should_register_check` — allows preventing registration ### 4. Namespace attribution @@ -60,7 +60,7 @@ The registry calls `sort_by_priority()` to keep the entries in ascending priorit ### 6. Post-registration action -After storage, the scope-specific action fires (e.g. `wp_validation_check_registered` for blocks). External plugins can hook it if they need to know when checks land. +After storage, the scope-specific action fires (e.g. `validation_api_check_registered` for blocks). External plugins can hook it if they need to know when checks land. ## Export Phase (PHP → JS) @@ -70,7 +70,7 @@ When `Assets::inject_editor_settings()` runs on `block_editor_settings_all`, eac ```php $effective_level = apply_filters( - 'wp_validation_check_level', + 'validation_api_check_level', $registered_level, [ 'scope' => 'block', // or 'meta' / 'editor' @@ -223,14 +223,14 @@ Two side-effect modules cooperate for per-block feedback: ``` PHP registration → AbstractRegistry::normalize_args (defaults, level validation, required-field check) - → wp_validation_check_args filter (scope-specific name) - → wp_validation_should_register_check filter (scope-specific name) + → validation_api_check_args filter (scope-specific name) + → validation_api_should_register_check filter (scope-specific name) → AbstractRegistry::stamp_namespace (`namespace` → `_namespace`) → Registry storage + sort_by_priority - → wp_validation_check_registered action (scope-specific name) + → validation_api_check_registered action (scope-specific name) PHP → JS export (once, on editor load) - → AbstractRegistry::apply_level_filter (wp_validation_check_level) + → AbstractRegistry::apply_level_filter (validation_api_check_level) → block_editor_settings_all → editorSettings.validationApi JS validation (continuous, in the editor) diff --git a/docs/technical/decisions.md b/docs/technical/decisions.md index dfe383e..24964c7 100644 --- a/docs/technical/decisions.md +++ b/docs/technical/decisions.md @@ -4,11 +4,11 @@ All resolved design decisions for the Validation API. This is a new identity and ## #1 — Hook Prefix -**Decision: `wp_validation_*`** +**Decision: `validation_api_*` in the standalone plugin; `wp_*` at core merge.** -All PHP actions/filters use the `wp_validation_` prefix. JS filters use `editor.*` namespacing. The old `ba11yc_` prefix tied the plugin to "Block Accessibility Checks", which was too narrow for a general validation framework. +All PHP actions/filters use the `validation_api_` prefix in the standalone plugin. JS filters use `editor.*` namespacing (already core-style; no rename needed at merge). The old `ba11yc_` prefix tied the plugin to "Block Accessibility Checks", which was too narrow for a general validation framework. -The prefix is descriptive, follows WordPress conventions (`wp_{feature}_*`), and signals that this is a general-purpose validation API — not an accessibility-specific tool. +The prefix history: originally chosen as `validation_api_*`. During the Gutenberg alignment refactor, hooks were renamed to the core-style `wp_*` prefix so the names would match what core would use post-merge. Submitting to the WordPress.org plugin directory then required reverting to `validation_api_*` because `wp_*` is reserved for core. The `wp_*` names will be restored as a mechanical find-and-replace at core-merge time — see [../gutenberg-alignment/core-pr-migration.md](../gutenberg-alignment/core-pr-migration.md). ## #2 — PHP Namespace @@ -35,7 +35,7 @@ Check data is exported to the editor via the `block_editor_settings_all` filter, The old model had four explicit types: `error`, `warning`, `settings`, `none`. The `settings` type existed to mark checks as "configurable via the settings page." -The insight: **every check is inherently configurable** because every check passes through `wp_validation_check_level`. You don't need to declare something as "configurable" — that's just the default behavior. The `settings` type was redundant. +The insight: **every check is inherently configurable** because every check passes through `validation_api_check_level`. You don't need to declare something as "configurable" — that's just the default behavior. The `settings` type was redundant. New model: @@ -46,10 +46,10 @@ New model: | `none` | Check disabled. Filter does **not** fire. Skipped entirely. | | *(omitted)* | Defaults to `error`. Filter fires, can override. | -The `wp_validation_check_level` filter is the settings mechanism: +The `validation_api_check_level` filter is the settings mechanism: ```php -apply_filters( 'wp_validation_check_level', $registered_level, $context ); +apply_filters( 'validation_api_check_level', $registered_level, $context ); ``` The companion settings package hooks into this filter and reads from `wp_options`. The core plugin has no storage — it just fires the filter. This is the Gutenberg-merge-friendly pattern: zero storage opinions in the framework. @@ -94,7 +94,7 @@ The new pattern uses flat global functions with a `namespace` field: ```php // New -wp_register_block_validation_check( 'core/image', [ +validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-plugin', 'name' => 'alt_text', 'error_msg' => 'Alt text required.', @@ -116,7 +116,7 @@ The old `category` parameter (`'accessibility'`, `'validation'`) was only used f | # | Question | Decision | Rationale | |---|---|---|---| -| 1 | Hook prefix | `wp_validation_*` (PHP), `editor.*` (JS) | Core-aligned naming | +| 1 | Hook prefix | `validation_api_*` (PHP, standalone) → `wp_*` at core merge; `editor.*` (JS, no rename) | Plugin-directory compliance now; core naming at merge | | 2 | PHP namespace | `ValidationAPI\*` | Matches new identity | | 3 | Data export | `block_editor_settings_all` filter | Core-aligned pattern | | 4 | Severity model | 3 levels, filter-first | All checks are configurable by default | diff --git a/docs/technical/hooks.md b/docs/technical/hooks.md index 4c11ae1..6353161 100644 --- a/docs/technical/hooks.md +++ b/docs/technical/hooks.md @@ -4,24 +4,24 @@ Complete list of PHP actions, PHP filters, and JavaScript filters provided by th ## PHP Actions -### wp_validation_initialized +### validation_api_initialized Fires after plugin initialization completes. ```php -do_action( 'wp_validation_initialized', Plugin $plugin ); +do_action( 'validation_api_initialized', Plugin $plugin ); ``` | Parameter | Type | Description | |---|---|---| | `$plugin` | `ValidationAPI\Core\Plugin` | The plugin instance | -### wp_validation_ready +### validation_api_ready -Fires after the Block Registry is ready. Use this to interact with the block registry directly (most integrations should use `wp_register_block_validation_check()` instead). +Fires after the Block Registry is ready. Use this to interact with the block registry directly (most integrations should use `validation_api_register_block_check()` instead). ```php -do_action( 'wp_validation_ready', BlockChecksRegistry $registry, Plugin $plugin ); +do_action( 'validation_api_ready', BlockChecksRegistry $registry, Plugin $plugin ); ``` | Parameter | Type | Description | @@ -29,12 +29,12 @@ do_action( 'wp_validation_ready', BlockChecksRegistry $registry, Plugin $plugin | `$registry` | `ValidationAPI\Block\Registry` | The block checks registry | | `$plugin` | `ValidationAPI\Core\Plugin` | The plugin instance | -### wp_validation_editor_checks_ready +### validation_api_editor_checks_ready Fires after the Editor Registry is ready. ```php -do_action( 'wp_validation_editor_checks_ready', EditorChecksRegistry $registry, Plugin $plugin ); +do_action( 'validation_api_editor_checks_ready', EditorChecksRegistry $registry, Plugin $plugin ); ``` | Parameter | Type | Description | @@ -42,12 +42,12 @@ do_action( 'wp_validation_editor_checks_ready', EditorChecksRegistry $registry, | `$registry` | `ValidationAPI\Editor\Registry` | The editor checks registry | | `$plugin` | `ValidationAPI\Core\Plugin` | The plugin instance | -### wp_validation_check_registered +### validation_api_check_registered Fires when a block check is successfully registered. ```php -do_action( 'wp_validation_check_registered', string $block_type, string $check_name, array $check_args ); +do_action( 'validation_api_check_registered', string $block_type, string $check_name, array $check_args ); ``` | Parameter | Type | Description | @@ -56,12 +56,12 @@ do_action( 'wp_validation_check_registered', string $block_type, string $check_n | `$check_name` | `string` | Check identifier | | `$check_args` | `array` | The final check configuration | -### wp_validation_editor_check_registered +### validation_api_editor_check_registered Fires when an editor check is successfully registered. ```php -do_action( 'wp_validation_editor_check_registered', string $post_type, string $check_name, array $check_args ); +do_action( 'validation_api_editor_check_registered', string $post_type, string $check_name, array $check_args ); ``` | Parameter | Type | Description | @@ -70,12 +70,12 @@ do_action( 'wp_validation_editor_check_registered', string $post_type, string $c | `$check_name` | `string` | Check identifier | | `$check_args` | `array` | The final check configuration | -### wp_validation_meta_check_registered +### validation_api_meta_check_registered Fires when a meta check is successfully registered. ```php -do_action( 'wp_validation_meta_check_registered', string $post_type, string $meta_key, string $check_name, array $check_args ); +do_action( 'validation_api_meta_check_registered', string $post_type, string $meta_key, string $check_name, array $check_args ); ``` | Parameter | Type | Description | @@ -87,12 +87,12 @@ do_action( 'wp_validation_meta_check_registered', string $post_type, string $met ## PHP Filters -### wp_validation_check_args +### validation_api_check_args Modify block check arguments before registration. ```php -$check_args = apply_filters( 'wp_validation_check_args', array $check_args, string $block_type, string $check_name ); +$check_args = apply_filters( 'validation_api_check_args', array $check_args, string $block_type, string $check_name ); ``` | Parameter | Type | Description | @@ -103,12 +103,12 @@ $check_args = apply_filters( 'wp_validation_check_args', array $check_args, stri **Return:** `array` — Modified check arguments. -### wp_validation_editor_check_args +### validation_api_editor_check_args Modify editor check arguments before registration. ```php -$check_args = apply_filters( 'wp_validation_editor_check_args', array $check_args, string $post_type, string $check_name ); +$check_args = apply_filters( 'validation_api_editor_check_args', array $check_args, string $post_type, string $check_name ); ``` | Parameter | Type | Description | @@ -119,12 +119,12 @@ $check_args = apply_filters( 'wp_validation_editor_check_args', array $check_arg **Return:** `array` — Modified check arguments. -### wp_validation_meta_check_args +### validation_api_meta_check_args Modify meta check arguments before registration. ```php -$check_args = apply_filters( 'wp_validation_meta_check_args', array $check_args, string $post_type, string $meta_key, string $check_name ); +$check_args = apply_filters( 'validation_api_meta_check_args', array $check_args, string $post_type, string $meta_key, string $check_name ); ``` | Parameter | Type | Description | @@ -136,12 +136,12 @@ $check_args = apply_filters( 'wp_validation_meta_check_args', array $check_args, **Return:** `array` — Modified check arguments. -### wp_validation_should_register_check +### validation_api_should_register_check Prevent a block check from being registered. ```php -$should = apply_filters( 'wp_validation_should_register_check', bool $should, string $block_type, string $check_name, array $check_args ); +$should = apply_filters( 'validation_api_should_register_check', bool $should, string $block_type, string $check_name, array $check_args ); ``` | Parameter | Type | Description | @@ -153,12 +153,12 @@ $should = apply_filters( 'wp_validation_should_register_check', bool $should, st **Return:** `bool` — `false` to prevent registration. -### wp_validation_should_register_editor_check +### validation_api_should_register_editor_check Prevent an editor check from being registered. ```php -$should = apply_filters( 'wp_validation_should_register_editor_check', bool $should, string $post_type, string $check_name, array $check_args ); +$should = apply_filters( 'validation_api_should_register_editor_check', bool $should, string $post_type, string $check_name, array $check_args ); ``` | Parameter | Type | Description | @@ -170,12 +170,12 @@ $should = apply_filters( 'wp_validation_should_register_editor_check', bool $sho **Return:** `bool` — `false` to prevent registration. -### wp_validation_should_register_meta_check +### validation_api_should_register_meta_check Prevent a meta check from being registered. ```php -$should = apply_filters( 'wp_validation_should_register_meta_check', bool $should, string $post_type, string $meta_key, string $check_name, array $check_args ); +$should = apply_filters( 'validation_api_should_register_meta_check', bool $should, string $post_type, string $meta_key, string $check_name, array $check_args ); ``` | Parameter | Type | Description | @@ -188,12 +188,12 @@ $should = apply_filters( 'wp_validation_should_register_meta_check', bool $shoul **Return:** `bool` — `false` to prevent registration. -### wp_validation_check_level +### validation_api_check_level Override the effective severity level of any check at runtime. This is the central configuration mechanism. ```php -$level = apply_filters( 'wp_validation_check_level', string $level, array $context ); +$level = apply_filters( 'validation_api_check_level', string $level, array $context ); ``` | Parameter | Type | Description | diff --git a/includes/AbstractRegistry.php b/includes/AbstractRegistry.php index 95703f3..47957ec 100644 --- a/includes/AbstractRegistry.php +++ b/includes/AbstractRegistry.php @@ -4,7 +4,7 @@ * * Base class extracted from the scope-specific registries (Block, Meta, Editor). * Provides shared helpers for check normalization, namespace stamping, priority - * sorting, and the wp_validation_check_level filter application. + * sorting, and the validation_api_check_level filter application. * * Subclasses retain their own storage shape, public registration signature, * and scope-specific filter/action hook names. @@ -130,7 +130,7 @@ static function ( $a, $b ) { } /** - * Apply the wp_validation_check_level filter with a 'none' short-circuit. + * Apply the validation_api_check_level filter with a 'none' short-circuit. * * @param string $registered_level The level as registered. * @param array $context Scope-specific context passed to consumers of the filter. @@ -141,6 +141,6 @@ protected function apply_level_filter( string $registered_level, array $context return 'none'; } - return \apply_filters( 'wp_validation_check_level', $registered_level, $context ); + return \apply_filters( 'validation_api_check_level', $registered_level, $context ); } } diff --git a/includes/Block/Registry.php b/includes/Block/Registry.php index 50bd076..553d0ca 100644 --- a/includes/Block/Registry.php +++ b/includes/Block/Registry.php @@ -80,10 +80,10 @@ public function register_check( string $block_type, string $check_name, array $c } // Allow developers to filter check arguments before registration. - $check_args = \apply_filters( 'wp_validation_check_args', $check_args, $block_type, $check_name ); + $check_args = \apply_filters( 'validation_api_check_args', $check_args, $block_type, $check_name ); // Allow developers to prevent specific checks from being registered. - if ( ! \apply_filters( 'wp_validation_should_register_check', true, $block_type, $check_name, $check_args ) ) { + if ( ! \apply_filters( 'validation_api_should_register_check', true, $block_type, $check_name, $check_args ) ) { $this->log_debug( "Check registration prevented by filter: {$context_label}" ); return false; } @@ -106,7 +106,7 @@ public function register_check( string $block_type, string $check_name, array $c $this->sort_by_priority( $this->checks[ $block_type ] ); // Action hook for developers to know when a validation check is registered. - \do_action( 'wp_validation_check_registered', $block_type, $check_name, $check_args ); + \do_action( 'validation_api_check_registered', $block_type, $check_name, $check_args ); return true; @@ -173,7 +173,7 @@ public function get_registered_block_types(): array { /** * Get the effective check level for a specific check * - * Passes the registered level through the wp_validation_check_level filter, + * Passes the registered level through the validation_api_check_level filter, * allowing external plugins (e.g. a settings companion) to override the level * at runtime. Checks set to 'none' are skipped without firing the filter. * diff --git a/includes/Core/Plugin.php b/includes/Core/Plugin.php index 4bc959d..18f8f44 100644 --- a/includes/Core/Plugin.php +++ b/includes/Core/Plugin.php @@ -82,13 +82,13 @@ public function init(): void { $this->init_rest_api(); // Allow other plugins to hook into our initialization. - \do_action( 'wp_validation_initialized', $this ); + \do_action( 'validation_api_initialized', $this ); // Allow developers to access the registry and add custom checks. - \do_action( 'wp_validation_ready', $this->get_service( 'block_checks_registry' ), $this ); + \do_action( 'validation_api_ready', $this->get_service( 'block_checks_registry' ), $this ); // Allow developers to register editor checks. - \do_action( 'wp_validation_editor_checks_ready', $this->get_service( 'editor_checks_registry' ), $this ); + \do_action( 'validation_api_editor_checks_ready', $this->get_service( 'editor_checks_registry' ), $this ); } catch ( \Exception $e ) { $this->log_error( 'Failed to initialize plugin: ' . $e->getMessage() ); diff --git a/includes/Editor/Registry.php b/includes/Editor/Registry.php index 96babe1..8ca907c 100644 --- a/includes/Editor/Registry.php +++ b/includes/Editor/Registry.php @@ -82,10 +82,10 @@ public function register_editor_check( string $post_type, string $check_name, ar } // Allow developers to filter check arguments before registration. - $check_args = \apply_filters( 'wp_validation_editor_check_args', $check_args, $post_type, $check_name ); + $check_args = \apply_filters( 'validation_api_editor_check_args', $check_args, $post_type, $check_name ); // Allow developers to prevent specific checks from being registered. - if ( ! \apply_filters( 'wp_validation_should_register_editor_check', true, $post_type, $check_name, $check_args ) ) { + if ( ! \apply_filters( 'validation_api_should_register_editor_check', true, $post_type, $check_name, $check_args ) ) { $this->log_debug( "Editor check registration prevented by filter: {$context_label}" ); return false; } @@ -103,7 +103,7 @@ public function register_editor_check( string $post_type, string $check_name, ar $this->sort_by_priority( $this->editor_checks[ $post_type ] ); // Action hook for developers to know when a check is registered. - \do_action( 'wp_validation_editor_check_registered', $post_type, $check_name, $check_args ); + \do_action( 'validation_api_editor_check_registered', $post_type, $check_name, $check_args ); return true; @@ -150,7 +150,7 @@ public function get_editor_check_config( string $post_type, string $check_name ) /** * Get the effective check level for a specific editor check * - * Passes the registered level through the wp_validation_check_level filter, + * Passes the registered level through the validation_api_check_level filter, * allowing external plugins (e.g. a settings companion) to override the level * at runtime. Checks set to 'none' are skipped without firing the filter. * diff --git a/includes/Meta/Registry.php b/includes/Meta/Registry.php index 8e6d1cd..ec14fe4 100644 --- a/includes/Meta/Registry.php +++ b/includes/Meta/Registry.php @@ -88,10 +88,10 @@ public function register_meta_check( string $post_type, string $meta_key, string } // Allow developers to filter check arguments before registration. - $check_args = \apply_filters( 'wp_validation_meta_check_args', $check_args, $post_type, $meta_key, $check_name ); + $check_args = \apply_filters( 'validation_api_meta_check_args', $check_args, $post_type, $meta_key, $check_name ); // Allow developers to prevent specific checks from being registered. - if ( ! \apply_filters( 'wp_validation_should_register_meta_check', true, $post_type, $meta_key, $check_name, $check_args ) ) { + if ( ! \apply_filters( 'validation_api_should_register_meta_check', true, $post_type, $meta_key, $check_name, $check_args ) ) { $this->log_debug( "Meta check registration prevented by filter: {$context_label}" ); return false; } @@ -114,7 +114,7 @@ public function register_meta_check( string $post_type, string $meta_key, string $this->sort_by_priority( $this->meta_checks[ $post_type ][ $meta_key ] ); // Action hook for developers to know when a check is registered. - \do_action( 'wp_validation_meta_check_registered', $post_type, $meta_key, $check_name, $check_args ); + \do_action( 'validation_api_meta_check_registered', $post_type, $meta_key, $check_name, $check_args ); return true; @@ -162,7 +162,7 @@ public function get_meta_check_config( string $post_type, string $meta_key, stri /** * Get the effective check level for a specific meta check * - * Passes the registered level through the wp_validation_check_level filter, + * Passes the registered level through the validation_api_check_level filter, * allowing external plugins (e.g. a settings companion) to override the level * at runtime. Checks set to 'none' are skipped without firing the filter. * diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 6b71967..7763ae6 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -44,8 +44,6 @@ - - diff --git a/readme.txt b/readme.txt index 91bf2d4..d9bc39d 100644 --- a/readme.txt +++ b/readme.txt @@ -30,11 +30,11 @@ Each check has a configurable severity level: * **Warning** — Advisory only; allows publishing; shown with a yellow indicator * **None** — Check is disabled; no validation runs -All severity levels are filterable at runtime via `wp_validation_check_level`, enabling a companion settings plugin to expose per-check configuration to site administrators without modifying registration code. +All severity levels are filterable at runtime via `validation_api_check_level`, enabling a companion settings plugin to expose per-check configuration to site administrators without modifying registration code. **For Developers:** -* Register checks using `wp_register_block_validation_check()`, `wp_register_meta_validation_check()`, and `wp_register_editor_validation_check()` with a `namespace` field for attribution +* Register checks using `validation_api_register_block_check()`, `validation_api_register_meta_check()`, and `validation_api_register_editor_check()` with a `namespace` field for attribution * Zero built-in checks — the framework ships clean; all checks come from integrating plugins * `function_exists()` guard pattern for safe integration across plugin load orders * Full PHP Registry API with singleton access for advanced use cases @@ -46,11 +46,11 @@ All severity levels are filterable at runtime via `wp_validation_check_level`, e ` add_action( 'init', function() { - if ( ! function_exists( 'wp_register_block_validation_check' ) ) { + if ( ! function_exists( 'validation_api_register_block_check' ) ) { return; } - wp_register_block_validation_check( 'core/image', [ + validation_api_register_block_check( 'core/image', [ 'namespace' => 'my-plugin', 'name' => 'alt_text', 'error_msg' => 'Images must have alt text.', @@ -95,15 +95,15 @@ No. Validation API ships with zero built-in checks. After activation, no validat = How do I add validation checks? = -Use the registration functions (`wp_register_block_validation_check()`, `wp_register_meta_validation_check()`, `wp_register_editor_validation_check()`) within an `init` action hook with a `function_exists` guard. See the `docs/guide/` directory for a complete getting started guide and examples. +Use the registration functions (`validation_api_register_block_check()`, `validation_api_register_meta_check()`, `validation_api_register_editor_check()`) within an `init` action hook with a `function_exists` guard. See the `docs/guide/` directory for a complete getting started guide and examples. = Can I control which checks are errors vs. warnings? = -Yes, in two ways. First, the registering plugin sets the default severity level. Second, any plugin can filter severity at runtime via the `wp_validation_check_level` filter. This enables a companion settings plugin to let administrators configure severity per check without touching registration code. +Yes, in two ways. First, the registering plugin sets the default severity level. Second, any plugin can filter severity at runtime via the `validation_api_check_level` filter. This enables a companion settings plugin to let administrators configure severity per check without touching registration code. = Where are the settings? = -Validation API has no settings UI. It is a framework. A separate companion settings plugin can consume the `wp_validation_check_level` filter and the REST API to expose per-check configuration to administrators. +Validation API has no settings UI. It is a framework. A separate companion settings plugin can consume the `validation_api_check_level` filter and the REST API to expose per-check configuration to administrators. = What are the three validation scopes? = diff --git a/validation-api.php b/validation-api.php index 7d3cfb1..61f3f29 100644 --- a/validation-api.php +++ b/validation-api.php @@ -59,7 +59,7 @@ function validation_api_init_plugin() { * @param array $args Check configuration. Required keys: 'namespace' (string), 'name' (string), 'error_msg' (string). * @return bool True on success, false on failure. */ -function wp_register_block_validation_check( string $block_type, array $args ): bool { +function validation_api_register_block_check( string $block_type, array $args ): bool { if ( empty( $args['namespace'] ) ) { _doing_it_wrong( __FUNCTION__, @@ -94,7 +94,7 @@ function wp_register_block_validation_check( string $block_type, array $args ): * @param array $args Check configuration. Required keys: 'namespace' (string), 'name' (string), 'meta_key' (string), 'error_msg' (string). * @return bool True on success, false on failure. */ -function wp_register_meta_validation_check( string $post_type, array $args ): bool { +function validation_api_register_meta_check( string $post_type, array $args ): bool { if ( empty( $args['namespace'] ) ) { _doing_it_wrong( __FUNCTION__, @@ -139,7 +139,7 @@ function wp_register_meta_validation_check( string $post_type, array $args ): bo * @param array $args Check configuration. Required keys: 'namespace' (string), 'name' (string), 'error_msg' (string). * @return bool True on success, false on failure. */ -function wp_register_editor_validation_check( string $post_type, array $args ): bool { +function validation_api_register_editor_check( string $post_type, array $args ): bool { if ( empty( $args['namespace'] ) ) { _doing_it_wrong( __FUNCTION__,