Skip to content

Commit e753781

Browse files
committed
Connectors: Improve inline documentation for the Connectors API
Adds comprehensive PHPDoc to `connectors.php` and `class-wp-connector-registry.php` covering API overview, AI provider auto-discovery, admin UI integration, initialization lifecycle, authentication, usage examples, cross-references, and metadata override patterns. Developed in WordPress#11244. Follow-up to [61943]. See #64791. git-svn-id: https://develop.svn.wordpress.org/trunk@62032 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 7453a4b commit e753781

File tree

2 files changed

+227
-25
lines changed

2 files changed

+227
-25
lines changed

src/wp-includes/class-wp-connector-registry.php

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
<?php
22
/**
3-
* Connectors API
4-
*
5-
* Defines WP_Connector_Registry class.
3+
* Connectors API: WP_Connector_Registry class.
64
*
75
* @package WordPress
86
* @subpackage Connectors
@@ -12,9 +10,23 @@
1210
/**
1311
* Manages the registration and lookup of connectors.
1412
*
13+
* This is an internal class. Use the public API functions to interact with connectors:
14+
*
15+
* - `wp_is_connector_registered()` — check if a connector exists.
16+
* - `wp_get_connector()` — retrieve a single connector's data.
17+
* - `wp_get_connectors()` — retrieve all registered connectors.
18+
*
19+
* Plugins receive the registry instance via the `wp_connectors_init` action
20+
* to register or override connectors directly.
21+
*
1522
* @since 7.0.0
1623
* @access private
1724
*
25+
* @see wp_is_connector_registered()
26+
* @see wp_get_connector()
27+
* @see wp_get_connectors()
28+
* @see _wp_connectors_init()
29+
*
1830
* @phpstan-type Connector array{
1931
* name: non-empty-string,
2032
* description: non-empty-string,
@@ -53,10 +65,22 @@ final class WP_Connector_Registry {
5365
/**
5466
* Registers a new connector.
5567
*
68+
* Validates the provided arguments and stores the connector in the registry.
69+
* For connectors with `api_key` authentication, a `setting_name` is automatically
70+
* generated using the pattern `connectors_ai_{$id}_api_key` (e.g., connector ID
71+
* `openai` produces `connectors_ai_openai_api_key`). This setting name is used
72+
* for the Settings API registration and REST API exposure.
73+
*
74+
* Registering a connector with an ID that is already registered will trigger a
75+
* `_doing_it_wrong()` notice and return `null`. To override an existing connector,
76+
* call `unregister()` first.
77+
*
5678
* @since 7.0.0
5779
*
58-
* @param string $id The unique connector identifier. Must contain only lowercase
59-
* alphanumeric characters and underscores.
80+
* @see WP_Connector_Registry::unregister()
81+
*
82+
* @param string $id The unique connector identifier. Must match the pattern
83+
* `/^[a-z0-9_]+$/` (lowercase alphanumeric and underscores only).
6084
* @param array $args {
6185
* An associative array of arguments for the connector.
6286
*
@@ -175,8 +199,17 @@ public function register( string $id, array $args ): ?array {
175199
/**
176200
* Unregisters a connector.
177201
*
202+
* Returns the connector data on success, which can be modified and passed
203+
* back to `register()` to override a connector's metadata.
204+
*
205+
* Triggers a `_doing_it_wrong()` notice if the connector is not registered.
206+
* Use `is_registered()` to check first when the connector may not exist.
207+
*
178208
* @since 7.0.0
179209
*
210+
* @see WP_Connector_Registry::register()
211+
* @see WP_Connector_Registry::is_registered()
212+
*
180213
* @param string $id The connector identifier.
181214
* @return array|null The unregistered connector data on success, null on failure.
182215
*
@@ -237,6 +270,9 @@ public function is_registered( string $id ): bool {
237270
*
238271
* Do not use this method directly. Instead, use the `wp_get_connector()` function.
239272
*
273+
* Triggers a `_doing_it_wrong()` notice if the connector is not registered.
274+
* Use `is_registered()` to check first when the connector may not exist.
275+
*
240276
* @since 7.0.0
241277
*
242278
* @see wp_get_connector()
@@ -272,9 +308,14 @@ public static function get_instance(): ?self {
272308
/**
273309
* Sets the main instance of the registry class.
274310
*
311+
* Called by `_wp_connectors_init()` during the `init` action. Must not be
312+
* called outside of that context.
313+
*
275314
* @since 7.0.0
276315
* @access private
277316
*
317+
* @see _wp_connectors_init()
318+
*
278319
* @param WP_Connector_Registry $registry The registry instance.
279320
*/
280321
public static function set_instance( WP_Connector_Registry $registry ): void {

src/wp-includes/connectors.php

Lines changed: 181 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,107 @@
11
<?php
22
/**
3-
* Connectors API.
3+
* Connectors API: core functions for registering and managing connectors.
4+
*
5+
* The Connectors API provides a unified framework for registering and managing
6+
* external service integrations within WordPress. A "connector" represents a
7+
* connection to an external service — currently focused on AI providers — with
8+
* standardized metadata, authentication configuration, and plugin association.
9+
*
10+
* ## Overview
11+
*
12+
* The Connectors API enables developers to:
13+
*
14+
* - Register AI provider connectors with standardized interfaces.
15+
* - Define authentication methods and credential sources.
16+
* - Associate connectors with WordPress.org plugins for install/activate UI.
17+
* - Expose connector settings through the REST API with automatic key masking.
18+
*
19+
* ## AI Provider Plugins
20+
*
21+
* AI provider plugins that register with the WP AI Client's `ProviderRegistry`
22+
* get automatic connector integration — no explicit connector registration is
23+
* needed. The system discovers providers from the WP AI Client registry and
24+
* creates connectors with the correct name, description, logo, authentication
25+
* method, and setting name derived from the provider's configuration.
26+
*
27+
* The authentication method (`api_key` or `none`) is determined by the provider's
28+
* metadata in the WP AI Client. For `api_key` providers, a `setting_name` is
29+
* automatically generated following the same naming convention used for environment
30+
* variables and PHP constants (e.g., provider `openai` maps to `OPENAI_API_KEY`
31+
* for env/constant lookup).
32+
*
33+
* @see WordPress\AiClient\Providers\ProviderRegistry
34+
*
35+
* ## Admin UI Integration
36+
*
37+
* Registered `ai_provider` connectors appear on the Settings → Connectors
38+
* admin screen. The screen renders each connector as a card using the
39+
* registry data:
40+
*
41+
* - `name`, `description`, and `logo_url` are displayed on the card.
42+
* - `plugin.slug` enables install/activate controls — the screen checks
43+
* whether the plugin is installed and active, and shows the appropriate
44+
* action button.
45+
* - `authentication.credentials_url` is rendered as a link directing users
46+
* to the provider's site to obtain API credentials.
47+
* - For `api_key` connectors, the screen shows the current key source
48+
* (environment variable, PHP constant, or database) and connection status.
49+
*
50+
* On the backend, `api_key` connectors also receive automatic settings
51+
* registration via the Settings API (`show_in_rest`), API key masking in
52+
* REST API responses, and key validation against the provider on update.
53+
*
54+
* Connectors with other authentication methods or types are registered in the PHP
55+
* registry and exposed via the script module data, but require a client-side
56+
* JavaScript registration for custom frontend UI. Support for additional
57+
* authentication methods and connector types is planned for future releases.
58+
*
59+
* ## Custom Connectors
60+
*
61+
* The `wp_connectors_init` action hook allows plugins to override metadata on
62+
* existing connectors. AI provider connectors are auto-discovered from the WP
63+
* AI Client registry and should not be manually registered here.
64+
*
65+
* Example — overriding the description of an auto-discovered connector:
66+
*
67+
* add_action( 'wp_connectors_init', function ( WP_Connector_Registry $registry ) {
68+
* if ( $registry->is_registered( 'openai' ) ) {
69+
* $connector = $registry->unregister( 'openai' );
70+
* $connector['description'] = __( 'Custom description for OpenAI.', 'my-plugin' );
71+
* $registry->register( 'openai', $connector );
72+
* }
73+
* } );
74+
*
75+
* Non-AI-provider connector types are not yet fully supported. The PHP registry
76+
* accepts any connector type, but only `ai_provider` connectors with `api_key`
77+
* authentication receive automatic admin UI. Support for additional connector
78+
* types with dedicated frontend integration is planned for future releases.
79+
* When available, this action will be the primary hook for registering those
80+
* new connector types.
81+
*
82+
* ## Initialization Lifecycle
83+
*
84+
* During `init`, the system:
85+
*
86+
* 1. Creates the `WP_Connector_Registry` singleton.
87+
* 2. Registers built-in connectors (Anthropic, Google, OpenAI) with hardcoded defaults.
88+
* 3. Auto-discovers providers from the WP AI Client registry and merges their
89+
* metadata (name, description, logo, authentication) on top of defaults,
90+
* with registry values taking precedence.
91+
* 4. Fires the `wp_connectors_init` action so plugins can override metadata
92+
* on existing connectors or register additional connectors.
93+
* 5. Registers settings and passes stored API keys to the WP AI Client.
94+
*
95+
* ## Authentication
96+
*
97+
* Connectors support two authentication methods:
98+
*
99+
* - `api_key`: Requires an API key, which can be provided via environment variable,
100+
* PHP constant, or the database (checked in that order).
101+
* - `none`: No authentication required.
102+
*
103+
* API keys stored in the database are automatically masked in REST API responses
104+
* and validated against the provider on update.
4105
*
5106
* @package WordPress
6107
* @subpackage Connectors
@@ -13,9 +114,17 @@
13114
/**
14115
* Checks if a connector is registered.
15116
*
117+
* Example:
118+
*
119+
* if ( wp_is_connector_registered( 'openai' ) ) {
120+
* // The OpenAI connector is available.
121+
* }
122+
*
16123
* @since 7.0.0
17124
*
18125
* @see WP_Connector_Registry::is_registered()
126+
* @see wp_get_connector()
127+
* @see wp_get_connectors()
19128
*
20129
* @param string $id The connector identifier.
21130
* @return bool True if the connector is registered, false otherwise.
@@ -32,9 +141,18 @@ function wp_is_connector_registered( string $id ): bool {
32141
/**
33142
* Retrieves a registered connector.
34143
*
144+
* Example:
145+
*
146+
* $connector = wp_get_connector( 'openai' );
147+
* if ( $connector ) {
148+
* echo $connector['name']; // 'OpenAI'
149+
* }
150+
*
35151
* @since 7.0.0
36152
*
37153
* @see WP_Connector_Registry::get_registered()
154+
* @see wp_is_connector_registered()
155+
* @see wp_get_connectors()
38156
*
39157
* @param string $id The connector identifier.
40158
* @return array|null {
@@ -85,9 +203,18 @@ function wp_get_connector( string $id ): ?array {
85203
/**
86204
* Retrieves all registered connectors.
87205
*
206+
* Example:
207+
*
208+
* $connectors = wp_get_connectors();
209+
* foreach ( $connectors as $id => $connector ) {
210+
* printf( '%s: %s', $connector['name'], $connector['description'] );
211+
* }
212+
*
88213
* @since 7.0.0
89214
*
90215
* @see WP_Connector_Registry::get_all_registered()
216+
* @see wp_is_connector_registered()
217+
* @see wp_get_connector()
91218
*
92219
* @return array {
93220
* Connector settings keyed by connector ID.
@@ -183,8 +310,21 @@ function _wp_connectors_resolve_ai_provider_logo_url( string $path ): ?string {
183310
/**
184311
* Initializes the connector registry with default connectors and fires the registration action.
185312
*
186-
* Creates the registry instance, registers built-in connectors (which cannot be unhooked),
187-
* and then fires the `wp_connectors_init` action for plugins to register their own connectors.
313+
* This function orchestrates the full connector initialization sequence:
314+
*
315+
* 1. Creates the `WP_Connector_Registry` singleton instance.
316+
* 2. Defines built-in connectors (Anthropic, Google, OpenAI) with hardcoded defaults
317+
* including name, description, type, plugin slug, and authentication configuration.
318+
* 3. Merges metadata from the WP AI Client provider registry on top of defaults.
319+
* Registry values (from provider plugins) take precedence over hardcoded fallbacks
320+
* for name, description, logo URL, and authentication method.
321+
* 4. Registers all connectors (built-in and AI Client-discovered) on the registry.
322+
* 5. Fires the `wp_connectors_init` action for plugins to override metadata
323+
* on existing connectors or register additional connectors.
324+
*
325+
* Built-in connectors are registered before the action fires and cannot be unhooked.
326+
* Plugins should use the `wp_connectors_init` action to override metadata or
327+
* register new connectors via `$registry->register()`.
188328
*
189329
* @since 7.0.0
190330
* @access private
@@ -294,24 +434,26 @@ function _wp_connectors_init(): void {
294434
/**
295435
* Fires when the connector registry is ready for plugins to register connectors.
296436
*
297-
* Default connectors have already been registered at this point and cannot be
298-
* unhooked. Use `$registry->register()` within this action to add new connectors.
437+
* Built-in connectors and any AI providers auto-discovered from the WP AI Client
438+
* registry have already been registered at this point and cannot be unhooked.
439+
*
440+
* AI provider plugins that register with the WP AI Client do not need to use
441+
* this action — their connectors are created automatically. This action is
442+
* primarily for registering non-AI-provider connectors or overriding metadata
443+
* on existing connectors.
444+
*
445+
* Use `$registry->register()` within this action to add new connectors.
446+
* To override an existing connector, unregister it first, then re-register
447+
* with updated data.
299448
*
300-
* Example usage:
449+
* Example — overriding metadata on an auto-discovered connector:
301450
*
302451
* add_action( 'wp_connectors_init', function ( WP_Connector_Registry $registry ) {
303-
* $registry->register(
304-
* 'my_custom_ai',
305-
* array(
306-
* 'name' => __( 'My Custom AI', 'my-plugin' ),
307-
* 'description' => __( 'Custom AI provider integration.', 'my-plugin' ),
308-
* 'type' => 'ai_provider',
309-
* 'authentication' => array(
310-
* 'method' => 'api_key',
311-
* 'credentials_url' => 'https://example.com/api-keys',
312-
* ),
313-
* )
314-
* );
452+
* if ( $registry->is_registered( 'openai' ) ) {
453+
* $connector = $registry->unregister( 'openai' );
454+
* $connector['description'] = __( 'Custom description for OpenAI.', 'my-plugin' );
455+
* $registry->register( 'openai', $connector );
456+
* }
315457
* } );
316458
*
317459
* @since 7.0.0
@@ -486,6 +628,11 @@ function _wp_connectors_rest_settings_dispatch( WP_REST_Response $response, WP_R
486628
/**
487629
* Registers default connector settings.
488630
*
631+
* Only registers settings for `ai_provider` connectors with `api_key`
632+
* authentication whose provider is present in the WP AI Client registry.
633+
* Each setting is registered with `show_in_rest` enabled, making it
634+
* accessible through the `/wp/v2/settings` REST endpoint.
635+
*
489636
* @since 7.0.0
490637
* @access private
491638
*/
@@ -573,13 +720,27 @@ function _wp_connectors_pass_default_keys_to_ai_client(): void {
573720
add_action( 'init', '_wp_connectors_pass_default_keys_to_ai_client', 20 );
574721

575722
/**
576-
* Exposes connector settings to the connectors-wp-admin script module.
723+
* Provides connector data to the Settings → Connectors admin screen.
724+
*
725+
* This function is the bridge between the PHP connector registry and the
726+
* frontend admin UI. It transforms each registered connector into the data
727+
* structure consumed by the `options-connectors-wp-admin` script module,
728+
* enriching registry data with runtime state:
729+
*
730+
* - Plugin install/activate status (via `get_plugins()` and `is_plugin_active()`).
731+
* - API key source detection (`env`, `constant`, `database`, or `none`).
732+
* - Connection status for `api_key` connectors (via the WP AI Client registry).
733+
*
734+
* Hooked to the `script_module_data_options-connectors-wp-admin` filter.
577735
*
578736
* @since 7.0.0
579737
* @access private
580738
*
739+
* @see _wp_connectors_get_api_key_source()
740+
*
581741
* @param array<string, mixed> $data Existing script module data.
582-
* @return array<string, mixed> Script module data with connectors added.
742+
* @return array<string, mixed> Script module data with a `connectors` key added,
743+
* keyed by connector ID and sorted alphabetically.
583744
*/
584745
function _wp_connectors_get_connector_script_module_data( array $data ): array {
585746
$registry = AiClient::defaultRegistry();

0 commit comments

Comments
 (0)